diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 66f87790e8..0251ff0eb8 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -168,6 +168,11 @@ CDeterministicMNCPtr CDeterministicMNList::GetValidMNByCollateral(const COutPoin return dmn; } +CDeterministicMNCPtr CDeterministicMNList::GetValidMNByService(const CService& service) const +{ + return GetUniquePropertyMN(service); +} + static int CompareByLastPaid_GetHeight(const CDeterministicMN& dmn) { int height = dmn.pdmnState->nLastPaidHeight; diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 43461eb8f7..4e6e2dd587 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -306,6 +306,7 @@ public: CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey& pubKey); CDeterministicMNCPtr GetMNByCollateral(const COutPoint& collateralOutpoint) const; CDeterministicMNCPtr GetValidMNByCollateral(const COutPoint& collateralOutpoint) const; + CDeterministicMNCPtr GetValidMNByService(const CService& service) const; CDeterministicMNCPtr GetMNPayee() const; /** diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index a26e38053f..8dc8b17134 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -190,21 +190,29 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const } if (!g_connman->HasMasternodeQuorumNodes(llmqType, quorum->qc.quorumHash)) { - std::map connections; + std::set connections; if (quorum->IsMember(myProTxHash)) { connections = CLLMQUtils::GetQuorumConnections(llmqType, quorum->qc.quorumHash, myProTxHash); } else { auto cindexes = CLLMQUtils::CalcDeterministicWatchConnections(llmqType, quorum->qc.quorumHash, quorum->members.size(), 1); for (auto idx : cindexes) { - connections.emplace(quorum->members[idx]->pdmnState->addr, quorum->members[idx]->proTxHash); + connections.emplace(quorum->members[idx]->proTxHash); } } if (!connections.empty()) { - std::string debugMsg = strprintf("CQuorumManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, quorum->qc.quorumHash.ToString()); - for (auto& c : connections) { - debugMsg += strprintf(" %s\n", c.first.ToString(false)); + if (LogAcceptCategory("llmq")) { + auto mnList = deterministicMNManager->GetListAtChainTip(); + std::string debugMsg = strprintf("CQuorumManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, quorum->qc.quorumHash.ToString()); + for (auto& c : connections) { + auto dmn = mnList.GetValidMN(c); + if (!dmn) { + debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString()); + } else { + debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString(false)); + } + } + LogPrint("llmq", debugMsg); } - LogPrint("llmq", debugMsg); g_connman->AddMasternodeQuorumNodes(llmqType, quorum->qc.quorumHash, connections); } } diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index 4cd69f4b70..d20c258629 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -468,21 +468,29 @@ void CDKGSessionHandler::HandleDKGRound() }); if (curSession->AreWeMember() || GetBoolArg("-watchquorums", DEFAULT_WATCH_QUORUMS)) { - std::map connections; + std::set connections; if (curSession->AreWeMember()) { connections = CLLMQUtils::GetQuorumConnections(params.type, curQuorumHash, curSession->myProTxHash); } else { auto cindexes = CLLMQUtils::CalcDeterministicWatchConnections(params.type, curQuorumHash, curSession->members.size(), 1); for (auto idx : cindexes) { - connections.emplace(curSession->members[idx]->dmn->pdmnState->addr, curSession->members[idx]->dmn->proTxHash); + connections.emplace(curSession->members[idx]->dmn->proTxHash); } } if (!connections.empty()) { - std::string debugMsg = strprintf("CDKGSessionManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, curSession->quorumHash.ToString()); - for (const auto& c : connections) { - debugMsg += strprintf(" %s\n", c.first.ToString(false)); + if (LogAcceptCategory("llmq-dkg")) { + std::string debugMsg = strprintf("CDKGSessionManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, curSession->quorumHash.ToString()); + auto mnList = deterministicMNManager->GetListAtChainTip(); + for (const auto& c : connections) { + auto dmn = mnList.GetValidMN(c); + if (!dmn) { + debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString()); + } else { + debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString(false)); + } + } + LogPrint("llmq-dkg", debugMsg); } - LogPrint("llmq-dkg", debugMsg); g_connman->AddMasternodeQuorumNodes(params.type, curQuorumHash, connections); } } diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index 5d1de8791d..338b01bf54 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -41,12 +41,12 @@ uint256 CLLMQUtils::BuildSignHash(Consensus::LLMQType llmqType, const uint256& q return h.GetHash(); } -std::map CLLMQUtils::GetQuorumConnections(Consensus::LLMQType llmqType, const uint256& blockHash, const uint256& forMember) +std::set CLLMQUtils::GetQuorumConnections(Consensus::LLMQType llmqType, const uint256& blockHash, const uint256& forMember) { auto& params = Params().GetConsensus().llmqs.at(llmqType); auto mns = GetAllQuorumMembers(llmqType, blockHash); - std::map result; + std::set result; for (size_t i = 0; i < mns.size(); i++) { auto& dmn = mns[i]; if (dmn->proTxHash == forMember) { @@ -62,7 +62,7 @@ std::map CLLMQUtils::GetQuorumConnections(Consensus::LLMQType if (otherDmn == dmn) { continue; } - result.emplace(otherDmn->pdmnState->addr, otherDmn->proTxHash); + result.emplace(otherDmn->proTxHash); gap <<= 1; k++; } diff --git a/src/llmq/quorums_utils.h b/src/llmq/quorums_utils.h index a53afdc874..a8c5ba7924 100644 --- a/src/llmq/quorums_utils.h +++ b/src/llmq/quorums_utils.h @@ -31,7 +31,7 @@ public: return BuildSignHash((Consensus::LLMQType)s.llmqType, s.quorumHash, s.id, s.msgHash); } - static std::map GetQuorumConnections(Consensus::LLMQType llmqType, const uint256& blockHash, const uint256& forMember); + static std::set GetQuorumConnections(Consensus::LLMQType llmqType, const uint256& blockHash, const uint256& forMember); static std::set CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, const uint256& blockHash, size_t memberCount, size_t connectionCount); static bool IsQuorumActive(Consensus::LLMQType llmqType, const uint256& quorumHash); diff --git a/src/net.cpp b/src/net.cpp index 99c96974d7..be2643dac2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2056,6 +2056,8 @@ void CConnman::ThreadOpenMasternodeConnections() } }); + auto mnList = deterministicMNManager->GetListAtChainTip(); + CSemaphoreGrant grant(*semMasternodeOutbound); if (interruptNet) return; @@ -2068,20 +2070,23 @@ void CConnman::ThreadOpenMasternodeConnections() std::vector pending; for (const auto& group : masternodeQuorumNodes) { - for (const auto& p : group.second) { - auto& addr = p.first; - auto& proRegTxHash = p.second; - if (!connectedNodes.count(addr) && !IsMasternodeOrDisconnectRequested(addr) && !connectedProRegTxHashes.count(proRegTxHash)) { - pending.emplace_back(addr); + for (const auto& proRegTxHash : group.second) { + auto dmn = mnList.GetValidMN(proRegTxHash); + if (!dmn) { + continue; + } + const auto& addr2 = dmn->pdmnState->addr; + if (!connectedNodes.count(addr2) && !IsMasternodeOrDisconnectRequested(addr2) && !connectedProRegTxHashes.count(proRegTxHash)) { + pending.emplace_back(addr2); } } } if (!vPendingMasternodes.empty()) { - auto addr = vPendingMasternodes.front(); + auto addr2 = vPendingMasternodes.front(); vPendingMasternodes.erase(vPendingMasternodes.begin()); - if (!connectedNodes.count(addr) && !IsMasternodeOrDisconnectRequested(addr)) { - pending.emplace_back(addr); + if (!connectedNodes.count(addr2) && !IsMasternodeOrDisconnectRequested(addr2)) { + pending.emplace_back(addr2); } } @@ -2719,14 +2724,14 @@ bool CConnman::AddPendingMasternode(const CService& service) return true; } -bool CConnman::AddMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::map& addresses) +bool CConnman::AddMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set& proTxHashes) { LOCK(cs_vPendingMasternodes); auto it = masternodeQuorumNodes.find(std::make_pair(llmqType, quorumHash)); if (it != masternodeQuorumNodes.end()) { return false; } - masternodeQuorumNodes.emplace(std::make_pair(llmqType, quorumHash), addresses); + masternodeQuorumNodes.emplace(std::make_pair(llmqType, quorumHash), proTxHashes); return true; } @@ -2756,18 +2761,14 @@ std::set CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType if (it == masternodeQuorumNodes.end()) { return {}; } - std::set proRegTxHashes; - for (auto& p : it->second) { - proRegTxHashes.emplace(p.second); - } + const auto& proRegTxHashes = it->second; std::set nodes; for (const auto pnode : vNodes) { if (pnode->fDisconnect) { continue; } - if (!pnode->qwatch && !it->second.count(pnode->addr) && - (pnode->verifiedProRegTxHash.IsNull() || !proRegTxHashes.count(pnode->verifiedProRegTxHash))) { + if (!pnode->qwatch && (pnode->verifiedProRegTxHash.IsNull() || !proRegTxHashes.count(pnode->verifiedProRegTxHash))) { continue; } nodes.emplace(pnode->id); @@ -2783,13 +2784,27 @@ void CConnman::RemoveMasternodeQuorumNodes(Consensus::LLMQType llmqType, const u bool CConnman::IsMasternodeQuorumNode(const CNode* pnode) { + // Let's see if this is an outgoing connection to an address that is known to be a masternode + // We however only need to know this if the node did not authenticate itself as a MN yet + uint256 assumedProTxHash; + if (pnode->verifiedProRegTxHash.IsNull() && !pnode->fInbound) { + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto dmn = mnList.GetValidMNByService(pnode->addr); + if (dmn == nullptr) { + // This is definitely not a masternode + return false; + } + assumedProTxHash = dmn->proTxHash; + } + LOCK(cs_vPendingMasternodes); for (const auto& p : masternodeQuorumNodes) { - for (const auto& p2 : p.second) { - if (p2.first == (CService)pnode->addr) { + if (!pnode->verifiedProRegTxHash.IsNull()) { + if (p.second.count(pnode->verifiedProRegTxHash)) { return true; } - if (!pnode->verifiedProRegTxHash.IsNull() && p2.second == pnode->verifiedProRegTxHash) { + } else if (!assumedProTxHash.IsNull()) { + if (p.second.count(assumedProTxHash)) { return true; } } @@ -3247,20 +3262,6 @@ bool CConnman::ForNode(NodeId id, std::function cond, return found != nullptr && cond(found) && func(found); } -void CConnman::ForEachQuorumMember(Consensus::LLMQType llmqType, const uint256& quorumHash, std::function func) const -{ - LOCK2(cs_vNodes, cs_vPendingMasternodes); - auto it = masternodeQuorumNodes.find(std::make_pair(llmqType, quorumHash)); - if (it == masternodeQuorumNodes.end()) { - return; - } - for (auto&& pnode : vNodes) { - if(it->second.count(pnode->addr)) { - func(pnode); - } - } -} - bool CConnman::IsMasternodeOrDisconnectRequested(const CService& addr) { return ForNode(addr, AllNodes, [](CNode* pnode){ return pnode->fMasternode || pnode->fDisconnect; diff --git a/src/net.h b/src/net.h index d385829f5c..c383d0bc2a 100644 --- a/src/net.h +++ b/src/net.h @@ -306,8 +306,6 @@ public: ForEachNodeThen(FullyConnectedOnly, pre, post); } - void ForEachQuorumMember(Consensus::LLMQType llmqType, const uint256& quorumHash, std::function func) const; - std::vector CopyNodeVector(std::function cond); std::vector CopyNodeVector(); void ReleaseNodeVector(const std::vector& vecNodes); @@ -358,7 +356,7 @@ public: std::vector GetAddedNodeInfo(); bool AddPendingMasternode(const CService& addr); - bool AddMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::map& addresses); + bool AddMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set& proTxHashes); bool HasMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash); std::set GetMasternodeQuorums(Consensus::LLMQType llmqType); // also returns QWATCH nodes @@ -494,7 +492,7 @@ private: std::vector vAddedNodes; CCriticalSection cs_vAddedNodes; std::vector vPendingMasternodes; - std::map, std::map> masternodeQuorumNodes; // protected by cs_vPendingMasternodes + std::map, std::set> masternodeQuorumNodes; // protected by cs_vPendingMasternodes mutable CCriticalSection cs_vPendingMasternodes; std::vector vNodes; std::list vNodesDisconnected;