Line data Source code
1 : // Copyright (c) 2014-2025 The Dash Core developers 2 : // Distributed under the MIT/X11 software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #include <masternode/utils.h> 6 : 7 : #include <coinjoin/walletman.h> 8 : #include <evo/deterministicmns.h> 9 : #include <masternode/sync.h> 10 : 11 : #include <net.h> 12 : #include <shutdown.h> 13 : 14 : #include <algorithm> 15 : 16 5374 : void CMasternodeUtils::DoMaintenance(CConnman& connman, CDeterministicMNManager& dmnman, const CMasternodeSync& mn_sync, 17 : CJWalletManager* const cj_walletman) 18 : { 19 5374 : if (!mn_sync.IsBlockchainSynced()) return; 20 5172 : if (ShutdownRequested()) return; 21 : 22 : // Don't disconnect masternode connections when we have less then the desired amount of outbound nodes 23 5153 : int nonMasternodeCount = 0; 24 21400 : connman.ForEachNode(CConnman::AllNodes, [&](const CNode* pnode) { 25 32494 : if ((!pnode->IsInboundConn() && 26 7578 : !pnode->IsFeelerConn() && 27 7578 : !pnode->IsManualConn() && 28 3616 : !pnode->m_masternode_connection && 29 14 : !pnode->m_masternode_probe_connection) 30 16247 : || 31 : // treat unverified MNs as non-MNs here 32 16233 : pnode->GetVerifiedProRegTxHash().IsNull()) { 33 5813 : nonMasternodeCount++; 34 5813 : } 35 16247 : }); 36 5153 : if (nonMasternodeCount < int(connman.GetMaxOutboundNodeCount())) { 37 5080 : return; 38 : } 39 : 40 73 : auto mixing_masternodes = cj_walletman ? cj_walletman->getMixingMasternodes() : std::vector<CDeterministicMNCPtr>{}; 41 878 : connman.ForEachNode(CConnman::AllNodes, [&](CNode* pnode) { 42 805 : if (pnode->m_masternode_probe_connection) { 43 : // we're not disconnecting masternode probes for at least PROBE_WAIT_INTERVAL seconds 44 0 : if (GetTime<std::chrono::seconds>() - pnode->m_connected < PROBE_WAIT_INTERVAL) return; 45 0 : } else { 46 : // we're only disconnecting m_masternode_connection connections 47 805 : if (!pnode->m_masternode_connection) return; 48 0 : if (!pnode->GetVerifiedProRegTxHash().IsNull()) { 49 0 : const auto tip_mn_list = dmnman.GetListAtChainTip(); 50 : // keep _verified_ LLMQ connections 51 0 : if (connman.IsMasternodeQuorumNode(pnode, tip_mn_list)) { 52 0 : return; 53 : } 54 : // keep _verified_ LLMQ relay connections 55 0 : if (connman.IsMasternodeQuorumRelayMember(pnode->GetVerifiedProRegTxHash())) { 56 0 : return; 57 : } 58 : // keep _verified_ inbound connections 59 0 : if (pnode->IsInboundConn()) { 60 0 : return; 61 : } 62 0 : } else if (GetTime<std::chrono::seconds>() - pnode->m_connected < PROBE_WAIT_INTERVAL) { 63 : // non-verified, give it some time to verify itself 64 0 : return; 65 0 : } else if (pnode->qwatch) { 66 : // keep watching nodes 67 0 : return; 68 : } 69 : } 70 : 71 0 : bool fFound = std::ranges::any_of(mixing_masternodes, [&pnode](const auto& dmn) { 72 0 : return pnode->addr == dmn->pdmnState->netInfo->GetPrimary(); 73 0 : }); 74 0 : if (fFound) return; // do NOT disconnect mixing masternodes 75 0 : if (fLogIPs) { 76 0 : LogPrint(BCLog::NET_NETCONN, "Closing Masternode connection: peer=%d, addr=%s\n", pnode->GetId(), 77 : pnode->addr.ToStringAddrPort()); 78 0 : } else { 79 0 : LogPrint(BCLog::NET_NETCONN, "Closing Masternode connection: peer=%d\n", pnode->GetId()); 80 : } 81 0 : pnode->fDisconnect = true; 82 805 : }); 83 5374 : }