From 1e545bff027fec3500996baf656782947501a18e Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 22 Mar 2019 13:46:11 +0100 Subject: [PATCH 1/5] Pass CNode* to IsMasternodeQuorumNode and let it also check verifiedProRegTxHash This makes IsMasternodeQuorumNode return true on incoming peer connections as well. --- src/masternode-utils.cpp | 2 +- src/net.cpp | 11 ++++++++--- src/net.h | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/masternode-utils.cpp b/src/masternode-utils.cpp index 1b8a755deda9c..9d46050867112 100644 --- a/src/masternode-utils.cpp +++ b/src/masternode-utils.cpp @@ -73,7 +73,7 @@ void CMasternodeUtils::ProcessMasternodeConnections(CConnman& connman) #endif // ENABLE_WALLET connman.ForEachNode(CConnman::AllNodes, [&](CNode* pnode) { - if (pnode->fMasternode && !connman.IsMasternodeQuorumNode(pnode->addr)) { + if (pnode->fMasternode && !connman.IsMasternodeQuorumNode(pnode)) { #ifdef ENABLE_WALLET bool fFound = false; for (const auto& dmn : vecDmns) { diff --git a/src/net.cpp b/src/net.cpp index c58fd1f6c4c10..a2b4426e0fd58 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2785,12 +2785,17 @@ void CConnman::RemoveMasternodeQuorumNodes(Consensus::LLMQType llmqType, const u masternodeQuorumNodes.erase(std::make_pair(llmqType, quorumHash)); } -bool CConnman::IsMasternodeQuorumNode(const CService& addr) +bool CConnman::IsMasternodeQuorumNode(const CNode* pnode) { LOCK(cs_vPendingMasternodes); for (const auto& p : masternodeQuorumNodes) { - if (p.second.count(addr)) { - return true; + for (const auto& p2 : p.second) { + if (p2.first == (CService)pnode->addr) { + return true; + } + if (!pnode->verifiedProRegTxHash.IsNull() && p2.second == pnode->verifiedProRegTxHash) { + return true; + } } } return false; diff --git a/src/net.h b/src/net.h index 1d8f3f3f2db0a..a4b1473d48b29 100644 --- a/src/net.h +++ b/src/net.h @@ -365,7 +365,7 @@ class CConnman // also returns QWATCH nodes std::set GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const; void RemoveMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash); - bool IsMasternodeQuorumNode(const CService& addr); + bool IsMasternodeQuorumNode(const CNode* pnode); size_t GetNodeCount(NumConnections num); void GetNodeStats(std::vector& vstats); From dc5f8d52a243770d63e5f2593e40aef7058f2dfc Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 22 Mar 2019 13:47:23 +0100 Subject: [PATCH 2/5] Let GetMasternodeQuorumNodes also take verifiedProRegTxHash into account This makes it return NodeIds for incoming peer connections as well. --- src/net.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/net.cpp b/src/net.cpp index a2b4426e0fd58..b75e6a558615b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2766,12 +2766,18 @@ std::set CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType if (it == masternodeQuorumNodes.end()) { return {}; } + std::set proRegTxHashes; + for (auto& p : it->second) { + proRegTxHashes.emplace(p.second); + } + std::set nodes; for (const auto pnode : vNodes) { if (pnode->fDisconnect) { continue; } - if (!pnode->qwatch && !it->second.count(pnode->addr)) { + if (!pnode->qwatch && !it->second.count(pnode->addr) && + (pnode->verifiedProRegTxHash.IsNull() || !proRegTxHashes.count(pnode->verifiedProRegTxHash))) { continue; } nodes.emplace(pnode->id); From 7b7b4d0c26b1d5df8c95db76994192f7fffaf39a Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 22 Mar 2019 13:50:22 +0100 Subject: [PATCH 3/5] Remove AddParticipatingNode and the need for it This was needed in the past when we were unable to identify incoming connections from other quorum members. Now that we have MNAUTH, we can easily identify all connected members. --- src/llmq/quorums_dkgsession.cpp | 23 +++++++---------------- src/llmq/quorums_dkgsession.h | 2 -- src/llmq/quorums_dkgsessionhandler.cpp | 14 -------------- src/llmq/quorums_dkgsessionmgr.cpp | 4 ---- 4 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/llmq/quorums_dkgsession.cpp b/src/llmq/quorums_dkgsession.cpp index 8b04d01d0d391..d439485307965 100644 --- a/src/llmq/quorums_dkgsession.cpp +++ b/src/llmq/quorums_dkgsession.cpp @@ -1244,26 +1244,17 @@ void CDKGSession::MarkBadMember(size_t idx) member->bad = true; } -void CDKGSession::AddParticipatingNode(NodeId nodeId) -{ - LOCK(invCs); - g_connman->ForNode(nodeId, [&](CNode* pnode) { - if (!participatingNodes.emplace(pnode->addr).second) { - return true; - } - - for (const auto& inv : invSet) { - pnode->PushInventory(inv); - } - return true; - }); -} - void CDKGSession::RelayInvToParticipants(const CInv& inv) const { LOCK(invCs); g_connman->ForEachNode([&](CNode* pnode) { - if (participatingNodes.count(pnode->addr)) { + bool relay = false; + if (pnode->qwatch) { + relay = true; + } else if (!pnode->verifiedProRegTxHash.IsNull() && membersMap.count(pnode->verifiedProRegTxHash)) { + relay = true; + } + if (relay) { pnode->PushInventory(inv); } }); diff --git a/src/llmq/quorums_dkgsession.h b/src/llmq/quorums_dkgsession.h index b0e110abd1c4c..4f4adca45871f 100644 --- a/src/llmq/quorums_dkgsession.h +++ b/src/llmq/quorums_dkgsession.h @@ -277,7 +277,6 @@ class CDKGSession std::map justifications; std::map prematureCommitments; std::set invSet; - std::set participatingNodes; std::vector pendingContributionVerifications; @@ -336,7 +335,6 @@ class CDKGSession bool AreWeMember() const { return !myProTxHash.IsNull(); } void MarkBadMember(size_t idx); - void AddParticipatingNode(NodeId nodeId); void RelayInvToParticipants(const CInv& inv) const; public: diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index 6110a0414f113..01163ce472278 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -435,14 +435,6 @@ bool ProcessPendingMessageBatch(CDKGSession& session, CDKGPendingMessages& pendi } } - for (const auto& p : preverifiedMessages) { - NodeId nodeId = p.first; - if (badNodes.count(nodeId)) { - continue; - } - session.AddParticipatingNode(nodeId); - } - return true; } @@ -492,12 +484,6 @@ void CDKGSessionHandler::HandleDKGRound() } LogPrint("llmq", debugMsg); g_connman->AddMasternodeQuorumNodes(params.type, curQuorumHash, connections); - - auto participatingNodesTmp = g_connman->GetMasternodeQuorumAddresses(params.type, curQuorumHash); - LOCK(curSession->invCs); - for (auto& p : participatingNodesTmp) { - curSession->participatingNodes.emplace(p.first); - } } } diff --git a/src/llmq/quorums_dkgsessionmgr.cpp b/src/llmq/quorums_dkgsessionmgr.cpp index edb4556744ecb..173634e4e88cf 100644 --- a/src/llmq/quorums_dkgsessionmgr.cpp +++ b/src/llmq/quorums_dkgsessionmgr.cpp @@ -81,10 +81,6 @@ void CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strComm if (strCommand == NetMsgType::QWATCH) { pfrom->qwatch = true; - for (auto& p : dkgSessionHandlers) { - LOCK2(p.second.cs, p.second.curSession->invCs); - p.second.curSession->participatingNodes.emplace(pfrom->addr); - } return; } From f62fe08f7809c3a560d6b99751eee29e8f7d2fe3 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 22 Mar 2019 13:53:11 +0100 Subject: [PATCH 4/5] Don't track interestedIn quorums in CSigSharesNodeState anymore Same as with the previous commit, we're now able to easily identify which nodes to announce sig shares to. --- src/llmq/quorums_signing_shares.cpp | 50 +++++++---------------------- src/llmq/quorums_signing_shares.h | 4 --- 2 files changed, 12 insertions(+), 42 deletions(-) diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index 072d4ca32cdda..bb3fd2d863d44 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -644,13 +644,7 @@ void CSigSharesManager::ProcessPendingSigSharesFromNode(NodeId nodeId, cxxtimer::Timer t(true); for (auto& sigShare : sigShares) { - // he sent us some valid sig shares, so he must be part of this quorum and is thus interested in our sig shares as well - // if this is the first time we received a sig share from this node, we won't announce the currently locally known sig shares to him. - // only the upcoming sig shares will be announced to him. this means the first signing session for a fresh quorum will be a bit - // slower than for older ones. TODO: fix this (risk of DoS when announcing all at once?) auto quorumKey = std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash); - nodeState.interestedIn.emplace(quorumKey); - ProcessSigShare(nodeId, sigShare, connman, quorums.at(quorumKey)); } t.stop(); @@ -670,10 +664,6 @@ void CSigSharesManager::ProcessSigShare(NodeId nodeId, const CSigShare& sigShare std::set quorumNodes; if (sigShare.quorumMember == quorum->GetMemberIndex(activeMasternodeInfo.proTxHash)) { quorumNodes = connman.GetMasternodeQuorumNodes((Consensus::LLMQType) sigShare.llmqType, sigShare.quorumHash); - // make sure node states are created for these nodes (we might have not received any message from these yet) - for (auto otherNodeId : quorumNodes) { - nodeStates[otherNodeId].interestedIn.emplace(std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash)); - } } if (quorumSigningManager->HasRecoveredSigForId(llmqType, sigShare.id)) { @@ -702,12 +692,9 @@ void CSigSharesManager::ProcessSigShare(NodeId nodeId, const CSigShare& sigShare if (!quorumNodes.empty()) { // don't announce and wait for other nodes to request this share and directly send it to them // there is no way the other nodes know about this share as this is the one created on this node - // this will also indicate interest to the other nodes in sig shares for this quorum - for (auto& p : nodeStates) { - if (!quorumNodes.count(p.first) && !p.second.interestedIn.count(std::make_pair((Consensus::LLMQType)sigShare.llmqType, sigShare.quorumHash))) { - continue; - } - auto& session = p.second.GetOrCreateSessionFromShare(sigShare); + for (auto otherNodeId : quorumNodes) { + auto& nodeState = nodeStates[otherNodeId]; + auto& session = nodeState.GetOrCreateSessionFromShare(sigShare); session.quorum = quorum; session.requested.Set(sigShare.quorumMember, true); session.knows.Set(sigShare.quorumMember, true); @@ -942,7 +929,7 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_map, StaticSaltedHasher> quorumNodesPrepared; + std::unordered_map, std::unordered_set, StaticSaltedHasher> quorumNodesMap; this->sigSharesToAnnounce.ForEach([&](const SigShareKey& sigShareKey, bool) { auto& signHash = sigShareKey.first; @@ -952,30 +939,20 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_mapllmqType, sigShare->quorumHash); - if (quorumNodesPrepared.emplace(quorumKey).second) { - // make sure we announce to at least the nodes which we know through the inter-quorum-communication system + auto it = quorumNodesMap.find(quorumKey); + if (it == quorumNodesMap.end()) { auto nodeIds = g_connman->GetMasternodeQuorumNodes(quorumKey.first, quorumKey.second); - for (auto nodeId : nodeIds) { - auto& nodeState = nodeStates[nodeId]; - nodeState.interestedIn.emplace(quorumKey); - } + it = quorumNodesMap.emplace(std::piecewise_construct, std::forward_as_tuple(quorumKey), std::forward_as_tuple(nodeIds.begin(), nodeIds.end())).first; } - for (auto& p : nodeStates) { - auto nodeId = p.first; - auto& nodeState = p.second; + auto& quorumNodes = it->second; - if (nodeState.banned) { - continue; - } + for (auto& nodeId : quorumNodes) { + auto& nodeState = nodeStates[nodeId]; - if (!nodeState.interestedIn.count(quorumKey)) { - // node is not interested in this sig share - // we only consider nodes to be interested if they sent us valid sig share before - // the sig share that we sign by ourself circumvents the inv system and is directly sent to all quorum members - // which are known by the deterministic inter-quorum-communication system. This is also the sig share that - // will tell the other nodes that we are interested in future sig shares + if (nodeState.banned) { continue; } @@ -997,9 +974,6 @@ void CSigSharesManager::CollectSigSharesToAnnounce(std::unordered_mapsigSharesToAnnounce.Clear(); } diff --git a/src/llmq/quorums_signing_shares.h b/src/llmq/quorums_signing_shares.h index d17be73c82ada..58ca5554488ff 100644 --- a/src/llmq/quorums_signing_shares.h +++ b/src/llmq/quorums_signing_shares.h @@ -316,10 +316,6 @@ class CSigSharesNodeState SigShareMap pendingIncomingSigShares; SigShareMap requestedSigShares; - // elements are added whenever we receive a valid sig share from this node - // this triggers us to send inventory items to him as he seems to be interested in these - std::unordered_set, StaticSaltedHasher> interestedIn; - bool banned{false}; Session& GetOrCreateSessionFromShare(const CSigShare& sigShare); From 13a72b926c50223539028e6683a0e4c88befaaae Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 22 Mar 2019 13:56:12 +0100 Subject: [PATCH 5/5] Remove unused CConnman::GetMasternodeQuorumAddresses --- src/net.cpp | 10 ---------- src/net.h | 1 - 2 files changed, 11 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index b75e6a558615b..99c96974d746f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2749,16 +2749,6 @@ std::set CConnman::GetMasternodeQuorums(Consensus::LLMQType llmqType) return result; } -std::map CConnman::GetMasternodeQuorumAddresses(Consensus::LLMQType llmqType, const uint256& quorumHash) const -{ - LOCK(cs_vPendingMasternodes); - auto it = masternodeQuorumNodes.find(std::make_pair(llmqType, quorumHash)); - if (it == masternodeQuorumNodes.end()) { - return {}; - } - return it->second; -} - std::set CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const { LOCK2(cs_vNodes, cs_vPendingMasternodes); diff --git a/src/net.h b/src/net.h index a4b1473d48b29..d385829f5cbe0 100644 --- a/src/net.h +++ b/src/net.h @@ -361,7 +361,6 @@ class CConnman bool AddMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::map& addresses); bool HasMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash); std::set GetMasternodeQuorums(Consensus::LLMQType llmqType); - std::map GetMasternodeQuorumAddresses(Consensus::LLMQType llmqType, const uint256& quorumHash) const; // also returns QWATCH nodes std::set GetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash) const; void RemoveMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash);