From f4f57fbb638c4b24f0dbdb8375e6b76ab077642e Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 17 Mar 2020 12:19:37 +0100 Subject: [PATCH 1/4] Pass fMasternode variable in VERSION so that the other end knows about it --- src/masternode/masternode-utils.cpp | 2 +- src/net_processing.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/masternode/masternode-utils.cpp b/src/masternode/masternode-utils.cpp index d7e6b4097ef0..fdff535ae7c0 100644 --- a/src/masternode/masternode-utils.cpp +++ b/src/masternode/masternode-utils.cpp @@ -39,7 +39,7 @@ void CMasternodeUtils::ProcessMasternodeConnections(CConnman& connman) } connman.ForEachNode(CConnman::AllNodes, [&](CNode* pnode) { - if (pnode->fMasternode && !connman.IsMasternodeQuorumNode(pnode)) { + if (!pnode->fInbound && pnode->fMasternode && !connman.IsMasternodeQuorumNode(pnode)) { #ifdef ENABLE_WALLET bool fFound = false; for (const auto& dmn : vecDmns) { diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 80dbfa569305..51197b61625c 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -321,7 +321,7 @@ void PushNodeVersion(CNode *pnode, CConnman* connman, int64_t nTime) } connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe, - nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes, mnauthChallenge)); + nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes, mnauthChallenge, pnode->fMasternode)); if (fLogIPs) { LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid); @@ -1870,6 +1870,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(pfrom->cs_mnauth); vRecv >> pfrom->receivedMNAuthChallenge; } + if (!vRecv.empty()) { + bool fOtherMasternode = false; + vRecv >> fOtherMasternode; + if (pfrom->fInbound) { + pfrom->fMasternode = fOtherMasternode; + } + } // Disconnect if we connected to ourself if (pfrom->fInbound && !connman->CheckIncomingNonce(nNonce)) { From 31825146a36c46e7b25a247d32efdf3418b218ed Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 17 Mar 2020 12:20:05 +0100 Subject: [PATCH 2/4] Don't relay anything to fMasternode connections This reduces traffic on these connections to PS and DKG/LLMQ traffic only. --- src/llmq/quorums_signing.cpp | 2 +- src/net.cpp | 21 +++++++++++++-------- src/net.h | 6 +++--- src/net_processing.cpp | 15 +++++++++++++-- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index 6e2b56cad45c..79c1b7fc1caf 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -713,7 +713,7 @@ void CSigningManager::ProcessRecoveredSig(NodeId nodeId, const CRecoveredSig& re CInv inv(MSG_QUORUM_RECOVERED_SIG, recoveredSig.GetHash()); g_connman->ForEachNode([&](CNode* pnode) { - if (pnode->nVersion >= LLMQS_PROTO_VERSION && pnode->fSendRecSigs) { + if (pnode->nVersion >= LLMQS_PROTO_VERSION && pnode->fSendRecSigs && !pnode->fMasternode) { pnode->PushInventory(inv); } }); diff --git a/src/net.cpp b/src/net.cpp index 09a729c0ca49..c67833d01547 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2944,22 +2944,26 @@ void CConnman::RelayTransaction(const CTransaction& tx) LOCK(cs_vNodes); for (CNode* pnode : vNodes) { + if (pnode->fMasternode) + continue; pnode->PushInventory(inv); } } -void CConnman::RelayInv(CInv &inv, const int minProtoVersion) { +void CConnman::RelayInv(CInv &inv, const int minProtoVersion, bool fAllowMasternodeConnections) { LOCK(cs_vNodes); - for (const auto& pnode : vNodes) - if(pnode->nVersion >= minProtoVersion) - pnode->PushInventory(inv); + for (const auto& pnode : vNodes) { + if (pnode->nVersion < minProtoVersion || (pnode->fMasternode && !fAllowMasternodeConnections)) + continue; + pnode->PushInventory(inv); + } } -void CConnman::RelayInvFiltered(CInv &inv, const CTransaction& relatedTx, const int minProtoVersion) +void CConnman::RelayInvFiltered(CInv &inv, const CTransaction& relatedTx, const int minProtoVersion, bool fAllowMasternodeConnections) { LOCK(cs_vNodes); for (const auto& pnode : vNodes) { - if(pnode->nVersion < minProtoVersion) + if (pnode->nVersion < minProtoVersion || (pnode->fMasternode && !fAllowMasternodeConnections)) continue; { LOCK(pnode->cs_filter); @@ -2970,11 +2974,12 @@ void CConnman::RelayInvFiltered(CInv &inv, const CTransaction& relatedTx, const } } -void CConnman::RelayInvFiltered(CInv &inv, const uint256& relatedTxHash, const int minProtoVersion) +void CConnman::RelayInvFiltered(CInv &inv, const uint256& relatedTxHash, const int minProtoVersion, bool fAllowMasternodeConnections) { LOCK(cs_vNodes); for (const auto& pnode : vNodes) { - if(pnode->nVersion < minProtoVersion) continue; + if (pnode->nVersion < minProtoVersion || (pnode->fMasternode && !fAllowMasternodeConnections)) + continue; { LOCK(pnode->cs_filter); if(pnode->pfilter && !pnode->pfilter->contains(relatedTxHash)) continue; diff --git a/src/net.h b/src/net.h index 5e0507858954..0e272704a137 100644 --- a/src/net.h +++ b/src/net.h @@ -353,10 +353,10 @@ class CConnman void ReleaseNodeVector(const std::vector& vecNodes); void RelayTransaction(const CTransaction& tx); - void RelayInv(CInv &inv, const int minProtoVersion = MIN_PEER_PROTO_VERSION); - void RelayInvFiltered(CInv &inv, const CTransaction &relatedTx, const int minProtoVersion = MIN_PEER_PROTO_VERSION); + void RelayInv(CInv &inv, const int minProtoVersion = MIN_PEER_PROTO_VERSION, bool fAllowMasternodeConnections = false); + void RelayInvFiltered(CInv &inv, const CTransaction &relatedTx, const int minProtoVersion = MIN_PEER_PROTO_VERSION, bool fAllowMasternodeConnections = false); // This overload will not update node filters, so use it only for the cases when other messages will update related transaction data in filters - void RelayInvFiltered(CInv &inv, const uint256 &relatedTxHash, const int minProtoVersion = MIN_PEER_PROTO_VERSION); + void RelayInvFiltered(CInv &inv, const uint256 &relatedTxHash, const int minProtoVersion = MIN_PEER_PROTO_VERSION, bool fAllowMasternodeConnections = false); void RemoveAskFor(const uint256& hash); // Addrman functions diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 51197b61625c..67712dd0d933 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -955,6 +955,7 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB } // Relay inventory, but don't relay old inventory during initial block download. connman->ForEachNode([nNewHeight, &vHashes](CNode* pnode) { + if (pnode->fMasternode) return; if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) { for (const uint256& hash : reverse_iterate(vHashes)) { pnode->PushBlockHash(hash); @@ -1875,6 +1876,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr vRecv >> fOtherMasternode; if (pfrom->fInbound) { pfrom->fMasternode = fOtherMasternode; + if (fOtherMasternode) { + LogPrint(BCLog::NET, "peer=%d is an inbound masternode connection, not relaying anything to it\n", pfrom->GetId()); + if (!fMasternodeMode) { + LogPrint(BCLog::NET, "but we're not a masternode, disconnecting\n"); + pfrom->fDisconnect = true; + return true; + } + } } } // Disconnect if we connected to ourself @@ -2316,7 +2325,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); break; } - pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash())); + if (!pfrom->fMasternode) { + pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash())); + } if (--nLimit <= 0) { // When this block is requested, we'll send an inv that'll @@ -3613,7 +3624,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic& interruptM if (pindexBestHeader == nullptr) pindexBestHeader = chainActive.Tip(); bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do. - if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) { + if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex && !pto->fMasternode) { // Only actively request headers from a single peer, unless we're close to end of initial download. if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) { state.fSyncStarted = true; From 71e57a25fa680ad32c92c60e656f7bb28dd40309 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 20 Mar 2020 12:22:05 +0100 Subject: [PATCH 3/4] Add masternode flag to result of getpeerinfo --- src/net.cpp | 1 + src/net.h | 1 + src/rpc/net.cpp | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/net.cpp b/src/net.cpp index c67833d01547..d9fc2d1bf774 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -760,6 +760,7 @@ void CNode::copyStats(CNodeStats &stats) LOCK(cs_mnauth); X(verifiedProRegTxHash); } + X(fMasternode); } #undef X diff --git a/src/net.h b/src/net.h index 0e272704a137..603ca4412783 100644 --- a/src/net.h +++ b/src/net.h @@ -707,6 +707,7 @@ class CNodeStats CAddress addrBind; // In case this is a verified MN, this value is the proTx of the MN uint256 verifiedProRegTxHash; + bool fMasternode; }; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index ab3425881631..e4d22d205944 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -97,6 +97,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) " \"subver\": \"/Dash Core:x.x.x/\", (string) The string version\n" " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n" " \"addnode\": true|false, (boolean) Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n" + " \"masternode\": true|false, (boolean) Whether connection was due to masternode connection attempt\n" " \"startingheight\": n, (numeric) The starting height (block) of the peer\n" " \"banscore\": n, (numeric) The ban score\n" " \"synced_headers\": n, (numeric) The last header we have in common with this peer\n" @@ -164,6 +165,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) obj.push_back(Pair("subver", stats.cleanSubVer)); obj.push_back(Pair("inbound", stats.fInbound)); obj.push_back(Pair("addnode", stats.m_manual_connection)); + obj.push_back(Pair("masternode", stats.fMasternode)); obj.push_back(Pair("startingheight", stats.nStartingHeight)); if (fStateStats) { obj.push_back(Pair("banscore", statestats.nMisbehavior)); From 0635659288c9b3fe25df616a620373d765d675fe Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Sat, 21 Mar 2020 13:30:35 +0100 Subject: [PATCH 4/4] Connect all nodes to node1 in llmq-chainlocks.py --- test/functional/llmq-chainlocks.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/functional/llmq-chainlocks.py b/test/functional/llmq-chainlocks.py index b5277c8bef5b..76ddd3160c59 100755 --- a/test/functional/llmq-chainlocks.py +++ b/test/functional/llmq-chainlocks.py @@ -23,6 +23,13 @@ def set_test_params(self): def run_test(self): + # Connect all nodes to node1 so that we always have the whole network connected + # Otherwise only masternode connections will be established between nodes, which won't propagate TXs/blocks + # Usually node0 is the one that does this, but in this test we isolate it multiple times + for i in range(len(self.nodes)): + if i != 1: + connect_nodes(self.nodes[i], 1) + self.log.info("Wait for dip0008 activation") while self.nodes[0].getblockchaininfo()["bip9_softforks"]["dip0008"]["status"] != "active":