diff --git a/src/coinjoin/coinjoin.cpp b/src/coinjoin/coinjoin.cpp index 3d92462986..8ab741e28f 100644 --- a/src/coinjoin/coinjoin.cpp +++ b/src/coinjoin/coinjoin.cpp @@ -47,12 +47,10 @@ uint256 CCoinJoinQueue::GetSignatureHash() const return SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION); } -bool CCoinJoinQueue::Sign() +bool CCoinJoinQueue::Sign(const CActiveMasternodeManager& mn_activeman) { - if (!fMasternodeMode) return false; - uint256 hash = GetSignatureHash(); - CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash, false)); + CBLSSignature sig = mn_activeman.Sign(hash, /*is_legacy=*/ false); if (!sig.IsValid()) { return false; } @@ -99,12 +97,10 @@ uint256 CCoinJoinBroadcastTx::GetSignatureHash() const return SerializeHash(*this, SER_GETHASH, PROTOCOL_VERSION); } -bool CCoinJoinBroadcastTx::Sign() +bool CCoinJoinBroadcastTx::Sign(const CActiveMasternodeManager& mn_activeman) { - if (!fMasternodeMode) return false; - uint256 hash = GetSignatureHash(); - CBLSSignature sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(hash, false)); + CBLSSignature sig = mn_activeman.Sign(hash, /*is_legacy=*/ false); if (!sig.IsValid()) { return false; } diff --git a/src/coinjoin/coinjoin.h b/src/coinjoin/coinjoin.h index 0fa7f0dcd5..f2214a329b 100644 --- a/src/coinjoin/coinjoin.h +++ b/src/coinjoin/coinjoin.h @@ -22,6 +22,7 @@ #include #include +class CActiveMasternodeManager; class CChainState; class CConnman; class CBLSPublicKey; @@ -213,7 +214,7 @@ public: * 3) we signed the message successfully, and * 4) we verified the message successfully */ - bool Sign(); + bool Sign(const CActiveMasternodeManager& mn_activeman); /// Check if we have a valid Masternode address [[nodiscard]] bool CheckSignature(const CBLSPublicKey& blsPubKey) const; @@ -284,7 +285,7 @@ public: [[nodiscard]] uint256 GetSignatureHash() const; - bool Sign(); + bool Sign(const CActiveMasternodeManager& mn_activeman); [[nodiscard]] bool CheckSignature(const CBLSPublicKey& blsPubKey) const; void SetConfirmedHeight(std::optional nConfirmedHeightIn) { assert(nConfirmedHeightIn == std::nullopt || *nConfirmedHeightIn > 0); nConfirmedHeight = nConfirmedHeightIn; } diff --git a/src/coinjoin/context.cpp b/src/coinjoin/context.cpp index 72437b1c46..2328ac3cea 100644 --- a/src/coinjoin/context.cpp +++ b/src/coinjoin/context.cpp @@ -14,13 +14,13 @@ #include CJContext::CJContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CTxMemPool& mempool, - const CMasternodeSync& mn_sync, bool relay_txes) : + const CActiveMasternodeManager* mn_activeman, const CMasternodeSync& mn_sync, bool relay_txes) : dstxman{std::make_unique()}, #ifdef ENABLE_WALLET walletman{std::make_unique(connman, dmnman, mempool, mn_sync, queueman)}, queueman {relay_txes ? std::make_unique(connman, *walletman, dmnman, mn_sync) : nullptr}, #endif // ENABLE_WALLET - server{std::make_unique(chainstate, connman, dmnman, *dstxman, mempool, mn_sync)} + server{std::make_unique(chainstate, connman, dmnman, *dstxman, mempool, mn_activeman, mn_sync)} {} CJContext::~CJContext() {} diff --git a/src/coinjoin/context.h b/src/coinjoin/context.h index 0f7f4fe0a0..856a41f5de 100644 --- a/src/coinjoin/context.h +++ b/src/coinjoin/context.h @@ -11,6 +11,7 @@ #include +class CActiveMasternodeManager; class CBlockPolicyEstimator; class CChainState; class CCoinJoinServer; @@ -29,7 +30,7 @@ struct CJContext { CJContext() = delete; CJContext(const CJContext&) = delete; CJContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CTxMemPool& mempool, - const CMasternodeSync& mn_sync, bool relay_txes); + const CActiveMasternodeManager* mn_activeman, const CMasternodeSync& mn_sync, bool relay_txes); ~CJContext(); const std::unique_ptr dstxman; diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index 1f40b1be88..c0ed66f4e4 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -43,6 +43,8 @@ PeerMsgRet CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_typ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) { + assert(m_mn_activeman); + if (IsSessionReady()) { // too many users in this session already, reject new ones LogPrint(BCLog::COINJOIN, "DSACCEPT -- queue is already full!\n"); @@ -56,7 +58,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) LogPrint(BCLog::COINJOIN, "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CoinJoin::DenominationToString(dsa.nDenom), dsa.txCollateral.ToString()); /* Continued */ auto mnList = m_dmnman.GetListAtChainTip(); - auto dmn = WITH_LOCK(activeMasternodeInfoCs, return mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint)); + auto dmn = WITH_LOCK(m_mn_activeman->cs, return mnList.GetValidMNByCollateral(m_mn_activeman->GetOutPoint())); if (!dmn) { PushStatus(peer, STATUS_REJECTED, ERR_MN_LIST); return; @@ -67,7 +69,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) TRY_LOCK(cs_vecqueue, lockRecv); if (!lockRecv) return; - auto mnOutpoint = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint); + auto mnOutpoint = WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint()); if (ranges::any_of(vecCoinJoinQueue, [&mnOutpoint](const auto& q){return q.masternodeOutpoint == mnOutpoint;})) { @@ -308,6 +310,8 @@ void CCoinJoinServer::CommitFinalTransaction() AssertLockNotHeld(cs_coinjoin); if (!fMasternodeMode) return; // check and relay final tx only on masternode + assert(m_mn_activeman); + CTransactionRef finalTransaction = WITH_LOCK(cs_coinjoin, return MakeTransactionRef(finalMutableTransaction)); uint256 hashTx = finalTransaction->GetHash(); @@ -331,10 +335,10 @@ void CCoinJoinServer::CommitFinalTransaction() // create and sign masternode dstx transaction if (!m_dstxman.GetDSTX(hashTx)) { CCoinJoinBroadcastTx dstxNew(finalTransaction, - WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), - WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash), + WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint()), + WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()), GetAdjustedTime()); - dstxNew.Sign(); + dstxNew.Sign(*m_mn_activeman); m_dstxman.AddDSTX(dstxNew); } @@ -495,16 +499,18 @@ void CCoinJoinServer::CheckForCompleteQueue() { if (!fMasternodeMode) return; + assert(m_mn_activeman); + if (nState == POOL_STATE_QUEUE && IsSessionReady()) { SetState(POOL_STATE_ACCEPTING_ENTRIES); CCoinJoinQueue dsq(nSessionDenom, - WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), - WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash), + WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint()), + WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()), GetAdjustedTime(), true); LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s) " /* Continued */ "with %d participants\n", dsq.ToString(), vecSessionCollaterals.size()); - dsq.Sign(); + dsq.Sign(*m_mn_activeman); dsq.Relay(connman); } } @@ -692,6 +698,8 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage& { if (!fMasternodeMode || nSessionID != 0) return false; + assert(m_mn_activeman); + // new session can only be started in idle mode if (nState != POOL_STATE_IDLE) { nMessageIDRet = ERR_MODE; @@ -713,11 +721,11 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage& if (!fUnitTest) { //broadcast that I'm accepting entries, only if it's the first entry through CCoinJoinQueue dsq(nSessionDenom, - WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.outpoint), - WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash), + WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetOutPoint()), + WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()), GetAdjustedTime(), false); LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString()); - dsq.Sign(); + dsq.Sign(*m_mn_activeman); dsq.Relay(connman); LOCK(cs_vecqueue); vecCoinJoinQueue.push_back(dsq); diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index d843ebb3a8..27d132961f 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -9,6 +9,7 @@ #include +class CActiveMasternodeManager; class CChainState; class CCoinJoinServer; class CDataStream; @@ -29,6 +30,7 @@ private: CDeterministicMNManager& m_dmnman; CDSTXManager& m_dstxman; CTxMemPool& mempool; + const CActiveMasternodeManager* m_mn_activeman; const CMasternodeSync& m_mn_sync; // Mixing uses collateral transactions to trust parties entering the pool @@ -85,12 +87,13 @@ private: public: explicit CCoinJoinServer(CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDSTXManager& dstxman, - CTxMemPool& mempool, const CMasternodeSync& mn_sync) : + CTxMemPool& mempool, const CActiveMasternodeManager* mn_activeman, const CMasternodeSync& mn_sync) : m_chainstate(chainstate), connman(_connman), m_dmnman(dmnman), m_dstxman(dstxman), mempool(mempool), + m_mn_activeman(mn_activeman), m_mn_sync(mn_sync), vecSessionCollaterals(), fUnitTest(false) diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 4ec90de570..67227af21c 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -21,40 +21,45 @@ void CMNAuth::PushMNAUTH(CNode& peer, CConnman& connman, const CBlockIndex* tip) { - LOCK(activeMasternodeInfoCs); - if (!fMasternodeMode || activeMasternodeInfo.proTxHash.IsNull()) { - return; - } - - uint256 signHash; - const auto receivedMNAuthChallenge = peer.GetReceivedMNAuthChallenge(); - if (receivedMNAuthChallenge.IsNull()) { - return; - } - // We include fInbound in signHash to forbid interchanging of challenges by a man in the middle (MITM). This way - // we protect ourselves against MITM in this form: - // node1 <- Eve -> node2 - // It does not protect against: - // node1 -> Eve -> node2 - // This is ok as we only use MNAUTH as a DoS protection and not for sensitive stuff - int nOurNodeVersion{PROTOCOL_VERSION}; - if (Params().NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) { - nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION); - } - const bool is_basic_scheme_active{DeploymentActiveAfter(tip, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)}; - const CBLSPublicKeyVersionWrapper pubKey(*activeMasternodeInfo.blsPubKeyOperator, !is_basic_scheme_active); - if (peer.nVersion < MNAUTH_NODE_VER_VERSION || nOurNodeVersion < MNAUTH_NODE_VER_VERSION) { - signHash = ::SerializeHash(std::make_tuple(pubKey, receivedMNAuthChallenge, peer.IsInboundConn())); - } else { - signHash = ::SerializeHash(std::make_tuple(pubKey, receivedMNAuthChallenge, peer.IsInboundConn(), nOurNodeVersion)); - } + if (!fMasternodeMode) return; CMNAuth mnauth; - mnauth.proRegTxHash = activeMasternodeInfo.proTxHash; - mnauth.sig = activeMasternodeInfo.blsKeyOperator->Sign(signHash); + uint256 signHash; + { + LOCK(::activeMasternodeManager->cs); + if (::activeMasternodeManager->GetProTxHash().IsNull()) { + return; + } + + const auto receivedMNAuthChallenge = peer.GetReceivedMNAuthChallenge(); + if (receivedMNAuthChallenge.IsNull()) { + return; + } + // We include fInbound in signHash to forbid interchanging of challenges by a man in the middle (MITM). This way + // we protect ourselves against MITM in this form: + // node1 <- Eve -> node2 + // It does not protect against: + // node1 -> Eve -> node2 + // This is ok as we only use MNAUTH as a DoS protection and not for sensitive stuff + int nOurNodeVersion{PROTOCOL_VERSION}; + if (Params().NetworkIDString() != CBaseChainParams::MAIN && gArgs.IsArgSet("-pushversion")) { + nOurNodeVersion = gArgs.GetArg("-pushversion", PROTOCOL_VERSION); + } + const bool is_basic_scheme_active{DeploymentActiveAfter(tip, Params().GetConsensus(), Consensus::DEPLOYMENT_V19)}; + auto pk = ::activeMasternodeManager->GetPubKey(); + const CBLSPublicKeyVersionWrapper pubKey(pk, !is_basic_scheme_active); + if (peer.nVersion < MNAUTH_NODE_VER_VERSION || nOurNodeVersion < MNAUTH_NODE_VER_VERSION) { + signHash = ::SerializeHash(std::make_tuple(pubKey, receivedMNAuthChallenge, peer.IsInboundConn())); + } else { + signHash = ::SerializeHash(std::make_tuple(pubKey, receivedMNAuthChallenge, peer.IsInboundConn(), nOurNodeVersion)); + } + + mnauth.proRegTxHash = ::activeMasternodeManager->GetProTxHash(); + } // ::activeMasternodeManager->cs + + mnauth.sig = ::activeMasternodeManager->Sign(signHash); LogPrint(BCLog::NET_NETCONN, "CMNAuth::%s -- Sending MNAUTH, peer=%d\n", __func__, peer.GetId()); - connman.PushMessage(&peer, CNetMsgMaker(peer.GetCommonVersion()).Make(NetMsgType::MNAUTH, mnauth)); } @@ -127,7 +132,9 @@ PeerMsgRet CMNAuth::ProcessMessage(CNode& peer, CConnman& connman, const CDeterm } } - const uint256 myProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash); + const uint256 myProTxHash = fMasternodeMode ? + WITH_LOCK(::activeMasternodeManager->cs, return ::activeMasternodeManager->GetProTxHash()) : + uint256(); connman.ForEachNode([&](CNode* pnode2) { if (peer.fDisconnect) { diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index 7aad8debff..923ef2bdec 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -692,14 +692,14 @@ std::optional CGovernanceManager::CreateGovernanceTrigg } { - LOCK(activeMasternodeInfoCs); - if (mn_payees.front()->proTxHash != activeMasternodeInfo.proTxHash) { + LOCK(::activeMasternodeManager->cs); + if (mn_payees.front()->proTxHash != ::activeMasternodeManager->GetProTxHash()) { LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s we are not the payee, skipping\n", __func__); return std::nullopt; } - gov_sb.SetMasternodeOutpoint(activeMasternodeInfo.outpoint); - gov_sb.Sign( *activeMasternodeInfo.blsKeyOperator); - } // activeMasternodeInfoCs + gov_sb.SetMasternodeOutpoint(::activeMasternodeManager->GetOutPoint()); + } // ::activeMasternodeManager->cs + gov_sb.Sign(*::activeMasternodeManager); if (std::string strError; !gov_sb.IsValidLocally(m_dmnman->GetListAtChainTip(), strError, true)) { LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s Created trigger is invalid:%s\n", __func__, strError); @@ -719,7 +719,8 @@ std::optional CGovernanceManager::CreateGovernanceTrigg void CGovernanceManager::VoteGovernanceTriggers(const std::optional& trigger_opt, CConnman& connman) { // only active masternodes can vote on triggers - if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) return; + if (!fMasternodeMode) return; + if (WITH_LOCK(::activeMasternodeManager->cs, return ::activeMasternodeManager->GetProTxHash().IsNull())) return; LOCK2(cs_main, cs); @@ -762,9 +763,9 @@ void CGovernanceManager::VoteGovernanceTriggers(const std::optionalcs, return ::activeMasternodeManager->GetOutPoint()), nHash, VOTE_SIGNAL_FUNDING, outcome); vote.SetTime(GetAdjustedTime()); - vote.Sign(WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator)); + vote.Sign(*::activeMasternodeManager); CGovernanceException exception; if (!ProcessVoteAndRelay(vote, exception, connman)) { diff --git a/src/governance/object.cpp b/src/governance/object.cpp index 4d108439aa..117af08466 100644 --- a/src/governance/object.cpp +++ b/src/governance/object.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -273,9 +274,9 @@ void CGovernanceObject::SetMasternodeOutpoint(const COutPoint& outpoint) m_obj.masternodeOutpoint = outpoint; } -bool CGovernanceObject::Sign(const CBLSSecretKey& key) +bool CGovernanceObject::Sign(const CActiveMasternodeManager& mn_activeman) { - CBLSSignature sig = key.Sign(GetSignatureHash(), false); + CBLSSignature sig = mn_activeman.Sign(GetSignatureHash(), false); if (!sig.IsValid()) { return false; } diff --git a/src/governance/object.h b/src/governance/object.h index c86ddb592b..e3879802c0 100644 --- a/src/governance/object.h +++ b/src/governance/object.h @@ -13,7 +13,7 @@ #include -class CBLSSecretKey; +class CActiveMasternodeManager; class CBLSPublicKey; class CDeterministicMNList; class CGovernanceManager; @@ -217,7 +217,7 @@ public: // Signature related functions void SetMasternodeOutpoint(const COutPoint& outpoint); - bool Sign(const CBLSSecretKey& key); + bool Sign(const CActiveMasternodeManager& mn_activeman); bool CheckSignature(const CBLSPublicKey& pubKey) const; uint256 GetSignatureHash() const; diff --git a/src/governance/vote.cpp b/src/governance/vote.cpp index fc3585f075..05f588c6a7 100644 --- a/src/governance/vote.cpp +++ b/src/governance/vote.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -221,9 +222,9 @@ bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const return true; } -bool CGovernanceVote::Sign(const CBLSSecretKey& key) +bool CGovernanceVote::Sign(const CActiveMasternodeManager& mn_activeman) { - CBLSSignature sig = key.Sign(GetSignatureHash(), false); + CBLSSignature sig = mn_activeman.Sign(GetSignatureHash(), false); if (!sig.IsValid()) { return false; } diff --git a/src/governance/vote.h b/src/governance/vote.h index 6c260a0899..2561a9c96a 100644 --- a/src/governance/vote.h +++ b/src/governance/vote.h @@ -8,11 +8,11 @@ #include #include -class CGovernanceVote; +class CActiveMasternodeManager; class CBLSPublicKey; -class CBLSSecretKey; class CConnman; class CDeterministicMNList; +class CGovernanceVote; class CKey; class CKeyID; @@ -101,7 +101,7 @@ public: bool Sign(const CKey& key, const CKeyID& keyID); bool CheckSignature(const CKeyID& keyID) const; - bool Sign(const CBLSSecretKey& key); + bool Sign(const CActiveMasternodeManager& mn_activeman); bool CheckSignature(const CBLSPublicKey& pubKey) const; bool IsValid(const CDeterministicMNList& tip_mn_list, bool useVotingKey) const; void Relay(CConnman& connman, const CDeterministicMNList& tip_mn_list) const; diff --git a/src/init.cpp b/src/init.cpp index 278a9aa33a..64ee07832e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -369,15 +369,9 @@ void PrepareShutdown(NodeContext& node) pdsNotificationInterface = nullptr; } if (fMasternodeMode) { - UnregisterValidationInterface(activeMasternodeManager.get()); - activeMasternodeManager.reset(); - } - - { - LOCK(activeMasternodeInfoCs); - // make sure to clean up BLS keys before global destructors are called (they have allocated from the secure memory pool) - activeMasternodeInfo.blsKeyOperator.reset(); - activeMasternodeInfo.blsPubKeyOperator.reset(); + UnregisterValidationInterface(node.mn_activeman); + node.mn_activeman = nullptr; + ::activeMasternodeManager.reset(); } node.chain_clients.clear(); @@ -1606,31 +1600,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc StartScriptCheckWorkerThreads(script_threads); } - assert(activeMasternodeInfo.blsKeyOperator == nullptr); - assert(activeMasternodeInfo.blsPubKeyOperator == nullptr); - fMasternodeMode = false; - std::string strMasterNodeBLSPrivKey = args.GetArg("-masternodeblsprivkey", ""); - if (!strMasterNodeBLSPrivKey.empty()) { - CBLSSecretKey keyOperator(ParseHex(strMasterNodeBLSPrivKey)); - if (!keyOperator.IsValid()) { - return InitError(_("Invalid masternodeblsprivkey. Please see documentation.")); - } - fMasternodeMode = true; - { - LOCK(activeMasternodeInfoCs); - activeMasternodeInfo.blsKeyOperator = std::make_unique(keyOperator); - activeMasternodeInfo.blsPubKeyOperator = std::make_unique(keyOperator.GetPublicKey()); - } - // We don't know the actual scheme at this point, print both - LogPrintf("MASTERNODE:\n blsPubKeyOperator legacy: %s\n blsPubKeyOperator basic: %s\n", - activeMasternodeInfo.blsPubKeyOperator->ToString(true), - activeMasternodeInfo.blsPubKeyOperator->ToString(false)); - } else { - LOCK(activeMasternodeInfoCs); - activeMasternodeInfo.blsKeyOperator = std::make_unique(); - activeMasternodeInfo.blsPubKeyOperator = std::make_unique(); - } - assert(!node.scheduler); node.scheduler = std::make_unique(); @@ -1875,10 +1844,20 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc ); RegisterValidationInterface(pdsNotificationInterface); - if (fMasternodeMode) { - // Create and register activeMasternodeManager, will init later in ThreadImport - activeMasternodeManager = std::make_unique(*node.connman, ::deterministicMNManager); - RegisterValidationInterface(activeMasternodeManager.get()); + fMasternodeMode = false; + std::string strMasterNodeBLSPrivKey = args.GetArg("-masternodeblsprivkey", ""); + if (!strMasterNodeBLSPrivKey.empty()) { + CBLSSecretKey keyOperator(ParseHex(strMasterNodeBLSPrivKey)); + if (!keyOperator.IsValid()) { + return InitError(_("Invalid masternodeblsprivkey. Please see documentation.")); + } + fMasternodeMode = true; + { + // Create and register activeMasternodeManager, will init later in ThreadImport + ::activeMasternodeManager = std::make_unique(keyOperator, *node.connman, ::deterministicMNManager); + node.mn_activeman = ::activeMasternodeManager.get(); + RegisterValidationInterface(node.mn_activeman); + } } // ********************************************************* Step 7a: Load sporks @@ -1975,7 +1954,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc node.llmq_ctx->Stop(); } node.llmq_ctx.reset(); - node.llmq_ctx.reset(new LLMQContext(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.evodb, *node.mnhf_manager, *node.sporkman, *node.mempool, node.peerman, false, fReset || fReindexChainState)); + node.llmq_ctx.reset(new LLMQContext(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.evodb, *node.mnhf_manager, *node.sporkman, *node.mempool, node.mn_activeman, node.peerman, false, fReset || fReindexChainState)); // Have to start it early to let VerifyDB check ChainLock signatures in coinbase node.llmq_ctx->Start(); @@ -2220,7 +2199,8 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc // ********************************************************* Step 7c: Setup CoinJoin - node.cj_ctx = std::make_unique(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.mempool, *node.mn_sync, !ignores_incoming_txs); + node.cj_ctx = std::make_unique(chainman.ActiveChainstate(), *node.connman, *node.dmnman, *node.mempool, node.mn_activeman, + *node.mn_sync, !ignores_incoming_txs); #ifdef ENABLE_WALLET node.coinjoin_loader = interfaces::MakeCoinJoinLoader(*node.cj_ctx->walletman); diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index 933cd58776..0b88365d56 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -20,7 +20,7 @@ #include LLMQContext::LLMQContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, - CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, + CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* mn_activeman, const std::unique_ptr& peerman, bool unit_tests, bool wipe) : bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, @@ -29,14 +29,14 @@ LLMQContext::LLMQContext(CChainState& chainstate, CConnman& connman, CDeterminis llmq::quorumBlockProcessor = std::make_unique(chainstate, connman, dmnman, evo_db); return llmq::quorumBlockProcessor.get(); }()}, - qdkgsman{std::make_unique(*bls_worker, chainstate, connman, dmnman, *dkg_debugman, *quorum_block_processor, sporkman, unit_tests, wipe)}, + qdkgsman{std::make_unique(*bls_worker, chainstate, connman, dmnman, *dkg_debugman, *quorum_block_processor, mn_activeman, sporkman, unit_tests, wipe)}, qman{[&]() -> llmq::CQuorumManager* const { assert(llmq::quorumManager == nullptr); - llmq::quorumManager = std::make_unique(*bls_worker, chainstate, connman, dmnman, *qdkgsman, evo_db, *quorum_block_processor, sporkman, ::masternodeSync); + llmq::quorumManager = std::make_unique(*bls_worker, chainstate, connman, dmnman, *qdkgsman, evo_db, *quorum_block_processor, mn_activeman, sporkman, ::masternodeSync); return llmq::quorumManager.get(); }()}, - sigman{std::make_unique(connman, *llmq::quorumManager, unit_tests, wipe)}, - shareman{std::make_unique(connman, *sigman, *llmq::quorumManager, sporkman, peerman)}, + sigman{std::make_unique(connman, mn_activeman, *llmq::quorumManager, unit_tests, wipe)}, + shareman{std::make_unique(connman, *sigman, mn_activeman, *llmq::quorumManager, sporkman, peerman)}, clhandler{[&]() -> llmq::CChainLocksHandler* const { assert(llmq::chainLocksHandler == nullptr); llmq::chainLocksHandler = std::make_unique(chainstate, connman, *::masternodeSync, *llmq::quorumManager, *sigman, *shareman, sporkman, mempool); @@ -77,7 +77,9 @@ void LLMQContext::Start() { assert(isman == llmq::quorumInstantSendManager.get()); bls_worker->Start(); - qdkgsman->StartThreads(); + if (fMasternodeMode) { + qdkgsman->StartThreads(); + } qman->Start(); shareman->RegisterAsRecoveredSigsListener(); shareman->StartWorkerThread(); @@ -100,6 +102,8 @@ void LLMQContext::Stop() { shareman->UnregisterAsRecoveredSigsListener(); sigman->StopWorkerThread(); qman->Stop(); - qdkgsman->StopThreads(); + if (fMasternodeMode) { + qdkgsman->StopThreads(); + } bls_worker->Stop(); } diff --git a/src/llmq/context.h b/src/llmq/context.h index 320ae0b3f5..d338a9e8b9 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -7,6 +7,7 @@ #include +class CActiveMasternodeManager; class CBLSWorker; class CChainState; class CConnman; @@ -34,7 +35,7 @@ struct LLMQContext { LLMQContext() = delete; LLMQContext(const LLMQContext&) = delete; LLMQContext(CChainState& chainstate, CConnman& connman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, - CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, + CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* mn_activeman, const std::unique_ptr& peerman, bool unit_tests, bool wipe); ~LLMQContext(); diff --git a/src/llmq/dkgsession.cpp b/src/llmq/dkgsession.cpp index 13a5a1df2e..b819a59347 100644 --- a/src/llmq/dkgsession.cpp +++ b/src/llmq/dkgsession.cpp @@ -199,7 +199,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages) logger.Batch("encrypted contributions. time=%d", t1.count()); - qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash())); + qc.sig = m_mn_activeman->Sign(qc.GetSignHash()); logger.Flush(); @@ -316,7 +316,7 @@ void CDKGSession::ReceiveMessage(const CDKGContribution& qc, bool& retBan) bool complain = false; CBLSSecretKey skContribution; - if (!qc.contributions->Decrypt(*myIdx, WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator), skContribution, PROTOCOL_VERSION)) { + if (!m_mn_activeman->Decrypt(*qc.contributions, *myIdx, skContribution, PROTOCOL_VERSION)) { logger.Batch("contribution from %s could not be decrypted", member->dmn->proTxHash.ToString()); complain = true; } else if (member->idx != myIdx && ShouldSimulateError(DKGError::type::COMPLAIN_LIE)) { @@ -517,7 +517,7 @@ void CDKGSession::SendComplaint(CDKGPendingMessages& pendingMessages) logger.Batch("sending complaint. badCount=%d, complaintCount=%d", badCount, complaintCount); - qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qc.GetSignHash())); + qc.sig = m_mn_activeman->Sign(qc.GetSignHash()); logger.Flush(); @@ -711,7 +711,7 @@ void CDKGSession::SendJustification(CDKGPendingMessages& pendingMessages, const return; } - qj.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(qj.GetSignHash())); + qj.sig = m_mn_activeman->Sign(qj.GetSignHash()); logger.Flush(); @@ -1003,7 +1003,7 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages) (*commitmentHash.begin())++; } - qc.sig = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.blsKeyOperator->Sign(commitmentHash)); + qc.sig = m_mn_activeman->Sign(commitmentHash); qc.quorumSig = skShare.Sign(commitmentHash); if (lieType == 3) { diff --git a/src/llmq/dkgsession.h b/src/llmq/dkgsession.h index c2f029edf7..35e54b9ac7 100644 --- a/src/llmq/dkgsession.h +++ b/src/llmq/dkgsession.h @@ -15,11 +15,13 @@ #include -class UniValue; +class CActiveMasternodeManager; class CInv; class CConnman; class CDeterministicMN; class CSporkManager; +class UniValue; + using CDeterministicMNCPtr = std::shared_ptr; namespace llmq @@ -273,6 +275,7 @@ private: CDeterministicMNManager& m_dmnman; CDKGSessionManager& dkgManager; CDKGDebugManager& dkgDebugManager; + const CActiveMasternodeManager* m_mn_activeman; const CSporkManager& m_sporkman; const CBlockIndex* m_quorum_base_block_index{nullptr}; @@ -314,8 +317,11 @@ private: std::set validCommitments GUARDED_BY(invCs); public: - CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CConnman& _connman, const CSporkManager& sporkman) : - params(_params), blsWorker(_blsWorker), cache(_blsWorker), m_dmnman(dmnman), dkgManager(_dkgManager), dkgDebugManager(_dkgDebugManager), m_sporkman(sporkman), connman(_connman) {} + CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, + CDKGSessionManager& _dkgManager, CDKGDebugManager& _dkgDebugManager, CConnman& _connman, + const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman) : + params(_params), blsWorker(_blsWorker), cache(_blsWorker), m_dmnman(dmnman), dkgManager(_dkgManager), + dkgDebugManager(_dkgDebugManager), m_mn_activeman(mn_activeman), m_sporkman(sporkman), connman(_connman) {} bool Init(gsl::not_null pQuorumBaseBlockIndex, Span mns, const uint256& _myProTxHash, int _quorumIndex); diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index 699239b916..3edf5446e8 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -26,7 +26,8 @@ namespace llmq CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CQuorumBlockProcessor& _quorumBlockProcessor, - const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex) : + const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params, + int _quorumIndex) : blsWorker(_blsWorker), m_chainstate(chainstate), connman(_connman), @@ -34,10 +35,11 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chai dkgDebugManager(_dkgDebugManager), dkgManager(_dkgManager), quorumBlockProcessor(_quorumBlockProcessor), + m_mn_activeman(mn_activeman), m_sporkman(sporkman), params(_params), quorumIndex(_quorumIndex), - curSession(std::make_unique(_params, _blsWorker, dmnman, _dkgManager, _dkgDebugManager, _connman, sporkman)), + curSession(std::make_unique(_params, _blsWorker, dmnman, _dkgManager, _dkgDebugManager, _connman, m_mn_activeman, sporkman)), pendingContributions((size_t)_params.size * 2, MSG_QUORUM_CONTRIB), // we allow size*2 messages as we need to make sure we see bad behavior (double messages) pendingComplaints((size_t)_params.size * 2, MSG_QUORUM_COMPLAINT), pendingJustifications((size_t)_params.size * 2, MSG_QUORUM_JUSTIFICATION), @@ -185,14 +187,14 @@ void CDKGSessionHandler::StopThread() bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex) { - curSession = std::make_unique(params, blsWorker, m_dmnman, dkgManager, dkgDebugManager, connman, m_sporkman); + curSession = std::make_unique(params, blsWorker, m_dmnman, dkgManager, dkgDebugManager, connman, m_mn_activeman, m_sporkman); if (!DeploymentDIP0003Enforced(pQuorumBaseBlockIndex->nHeight, Params().GetConsensus())) { return false; } auto mns = utils::GetAllQuorumMembers(params.type, m_dmnman, pQuorumBaseBlockIndex); - if (!curSession->Init(pQuorumBaseBlockIndex, mns, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash), quorumIndex)) { + if (!curSession->Init(pQuorumBaseBlockIndex, mns, WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()), quorumIndex)) { LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d] mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex, mns.size()); return false; } diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index 8a234dca8b..543bcbd338 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -14,6 +14,7 @@ #include #include +class CActiveMasternodeManager; class CBlockIndex; class CBLSWorker; class CChainState; @@ -125,6 +126,7 @@ private: CDKGDebugManager& dkgDebugManager; CDKGSessionManager& dkgManager; CQuorumBlockProcessor& quorumBlockProcessor; + const CActiveMasternodeManager* m_mn_activeman; const CSporkManager& m_sporkman; const Consensus::LLMQParams params; const int quorumIndex; @@ -146,7 +148,8 @@ private: public: CDKGSessionHandler(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDKGDebugManager& _dkgDebugManager, CDKGSessionManager& _dkgManager, CQuorumBlockProcessor& _quorumBlockProcessor, - const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex); + const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman, const Consensus::LLMQParams& _params, + int _quorumIndex); ~CDKGSessionHandler() = default; void UpdatedBlockTip(const CBlockIndex *pindexNew); diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index c541ddcc83..c4d1dce1f7 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -25,8 +25,8 @@ static const std::string DB_SKCONTRIB = "qdkg_S"; static const std::string DB_ENC_CONTRIB = "qdkg_E"; CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, - CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman, - bool unitTests, bool fWipe) : + CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* mn_activeman, + const CSporkManager& sporkman, bool unitTests, bool fWipe) : db(std::make_unique(unitTests ? "" : (GetDataDir() / "llmq/dkgdb"), 1 << 20, unitTests, fWipe)), blsWorker(_blsWorker), m_chainstate(chainstate), @@ -49,7 +49,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chai for (const auto i : irange::range(session_count)) { dkgSessionHandlers.emplace(std::piecewise_construct, std::forward_as_tuple(params.type, i), - std::forward_as_tuple(blsWorker, m_chainstate, connman, dmnman, dkgDebugManager, *this, quorumBlockProcessor, spork_manager, params, i)); + std::forward_as_tuple(blsWorker, m_chainstate, connman, dmnman, dkgDebugManager, *this, quorumBlockProcessor, mn_activeman, spork_manager, params, i)); } } } diff --git a/src/llmq/dkgsessionmgr.h b/src/llmq/dkgsessionmgr.h index b0ec1e39a7..c493a65940 100644 --- a/src/llmq/dkgsessionmgr.h +++ b/src/llmq/dkgsessionmgr.h @@ -14,6 +14,7 @@ #include #include +class CActiveMasternodeManager; class CBlockIndex; class CChainState; class CDBWrapper; @@ -66,8 +67,8 @@ private: public: CDKGSessionManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, - CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman, - bool unitTests, bool fWipe); + CDKGDebugManager& _dkgDebugManager, CQuorumBlockProcessor& _quorumBlockProcessor, const CActiveMasternodeManager* mn_activeman, + const CSporkManager& sporkman, bool unitTests, bool fWipe); ~CDKGSessionManager() = default; void StartThreads(); diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 103067aadc..8b6e7205ab 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -101,9 +101,9 @@ bool CQuorum::SetVerificationVector(const std::vector& quorumVecI return true; } -bool CQuorum::SetSecretKeyShare(const CBLSSecretKey& secretKeyShare) +bool CQuorum::SetSecretKeyShare(const CBLSSecretKey& secretKeyShare, const CActiveMasternodeManager& mn_activeman) { - if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(WITH_LOCK(activeMasternodeInfoCs, return GetMemberIndex(activeMasternodeInfo.proTxHash))))) { + if (!secretKeyShare.IsValid() || (secretKeyShare.GetPublicKey() != GetPubKeyShare(WITH_LOCK(mn_activeman.cs, return GetMemberIndex(mn_activeman.GetProTxHash()))))) { return false; } LOCK(cs); @@ -205,8 +205,10 @@ bool CQuorum::ReadContributions(CEvoDB& evoDb) return true; } -CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, - CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman, const std::unique_ptr& mn_sync) : +CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, + CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, + const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman, + const std::unique_ptr& mn_sync) : blsWorker(_blsWorker), m_chainstate(chainstate), connman(_connman), @@ -214,6 +216,7 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, dkgManager(_dkgManager), m_evoDb(_evoDb), quorumBlockProcessor(_quorumBlockProcessor), + m_mn_activeman(mn_activeman), m_sporkman(sporkman), m_mn_sync(mn_sync) { @@ -250,7 +253,12 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(const CBlockIndex* pIndex) const auto vecQuorums = ScanQuorums(params.type, pIndex, params.keepOldConnections); // First check if we are member of any quorum of this type - auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash); + const uint256 proTxHash = [this]() { + if (!fMasternodeMode) return uint256(); + assert(m_mn_activeman); + return WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()); + }(); + bool fWeAreQuorumTypeMember = ranges::any_of(vecQuorums, [&proTxHash](const auto& pQuorum) { return pQuorum->IsValidMember(proTxHash); }); @@ -341,7 +349,12 @@ void CQuorumManager::CheckQuorumConnections(const Consensus::LLMQParams& llmqPar LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, ToUnderlying(llmqParams.type), pindexNew->nHeight, curDkgHeight, curDkgBlock.ToString()); } - const auto myProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash); + const uint256 myProTxHash = [this]() { + if (!fMasternodeMode) return uint256(); + assert(m_mn_activeman); + return WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()); + }(); + bool isISType = llmqParams.type == Params().GetConsensus().llmqTypeDIP0024InstantSend; bool watchOtherISQuorums = isISType && !myProTxHash.IsNull() && @@ -640,6 +653,8 @@ CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, gsl::not_nul size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorumCPtr pQuorum, const CBlockIndex* pIndex) const { + assert(m_mn_activeman); + auto mns = m_dmnman.GetListForBlock(pIndex); std::vector vecProTxHashes; vecProTxHashes.reserve(mns.GetValidMNsCount()); @@ -649,10 +664,10 @@ size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorumCPtr pQuorum, c std::sort(vecProTxHashes.begin(), vecProTxHashes.end()); size_t nIndex{0}; { - LOCK(activeMasternodeInfoCs); + LOCK(m_mn_activeman->cs); for (const auto i : irange::range(vecProTxHashes.size())) { // cppcheck-suppress useStlAlgorithm - if (activeMasternodeInfo.proTxHash == vecProTxHashes[i]) { + if (m_mn_activeman->GetProTxHash() == vecProTxHashes[i]) { nIndex = i; break; } @@ -813,6 +828,7 @@ PeerMsgRet CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_t // Check if request has ENCRYPTED_CONTRIBUTIONS data if (request.GetDataMask() & CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS) { + assert(fMasternodeMode); if (WITH_LOCK(pQuorum->cs, return pQuorum->quorumVvec->size() != size_t(pQuorum->params.threshold))) { return errorHandler("No valid quorum verification vector available", 0); // Don't bump score because we asked for it @@ -828,15 +844,14 @@ PeerMsgRet CQuorumManager::ProcessMessage(CNode& pfrom, const std::string& msg_t std::vector vecSecretKeys; vecSecretKeys.resize(vecEncrypted.size()); - auto secret = WITH_LOCK(activeMasternodeInfoCs, return *activeMasternodeInfo.blsKeyOperator); for (const auto i : irange::range(vecEncrypted.size())) { - if (!vecEncrypted[i].Decrypt(memberIdx, secret, vecSecretKeys[i], PROTOCOL_VERSION)) { + if (!Assert(m_mn_activeman)->Decrypt(vecEncrypted[i], memberIdx, vecSecretKeys[i], PROTOCOL_VERSION)) { return errorHandler("Failed to decrypt"); } } CBLSSecretKey secretKeyShare = blsWorker.AggregateSecretKeys(vecSecretKeys); - if (!pQuorum->SetSecretKeyShare(secretKeyShare)) { + if (!pQuorum->SetSecretKeyShare(secretKeyShare, *m_mn_activeman)) { return errorHandler("Invalid secret key share received"); } } @@ -878,6 +893,8 @@ void CQuorumManager::StartCachePopulatorThread(const CQuorumCPtr pQuorum) const void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, const CBlockIndex* pIndex, uint16_t nDataMaskIn) const { + assert(m_mn_activeman); + if (pQuorum->fQuorumDataRecoveryThreadRunning) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Already running\n", __func__); return; @@ -911,7 +928,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co vecMemberHashes.reserve(pQuorum->qc->validMembers.size()); for (auto& member : pQuorum->members) { - if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash)) { + if (pQuorum->IsValidMember(member->proTxHash) && member->proTxHash != WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash())) { vecMemberHashes.push_back(member->proTxHash); } } @@ -960,7 +977,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co printLog("Connect"); } - auto proTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash); + auto proTxHash = WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()); connman.ForEachNode([&](CNode* pNode) { auto verifiedProRegTxHash = pNode->GetVerifiedProRegTxHash(); if (pCurrentMemberHash == nullptr || verifiedProRegTxHash != *pCurrentMemberHash) { diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 8084fbefee..9f3c139c9e 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -21,6 +21,7 @@ #include #include +class CActiveMasternodeManager; class CBlockIndex; class CChainState; class CConnman; @@ -192,7 +193,7 @@ public: void Init(CFinalCommitmentPtr _qc, const CBlockIndex* _pQuorumBaseBlockIndex, const uint256& _minedBlockHash, Span _members); bool SetVerificationVector(const std::vector& quorumVecIn); - bool SetSecretKeyShare(const CBLSSecretKey& secretKeyShare); + bool SetSecretKeyShare(const CBLSSecretKey& secretKeyShare, const CActiveMasternodeManager& mn_activeman); bool HasVerificationVector() const; bool IsMember(const uint256& proTxHash) const; @@ -223,6 +224,7 @@ private: CDKGSessionManager& dkgManager; CEvoDB& m_evoDb; CQuorumBlockProcessor& quorumBlockProcessor; + const CActiveMasternodeManager* m_mn_activeman; const CSporkManager& m_sporkman; const std::unique_ptr& m_mn_sync; @@ -237,8 +239,9 @@ private: mutable CThreadInterrupt quorumThreadInterrupt; public: - CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, - CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, const CSporkManager& sporkman, const std::unique_ptr& mn_sync); + CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate, CConnman& _connman, CDeterministicMNManager& dmnman, + CDKGSessionManager& _dkgManager, CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, + const CActiveMasternodeManager* mn_activeman, const CSporkManager& sporkman, const std::unique_ptr& mn_sync); ~CQuorumManager() { Stop(); }; void Start(); diff --git a/src/llmq/signing.cpp b/src/llmq/signing.cpp index f6f721fee1..f088895773 100644 --- a/src/llmq/signing.cpp +++ b/src/llmq/signing.cpp @@ -539,9 +539,9 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge) ////////////////// -CSigningManager::CSigningManager(CConnman& _connman, const CQuorumManager& _qman, +CSigningManager::CSigningManager(CConnman& _connman, const CActiveMasternodeManager* mn_activeman, const CQuorumManager& _qman, bool fMemory, bool fWipe) : - db(fMemory, fWipe), connman(_connman), qman(_qman) + db(fMemory, fWipe), connman(_connman), m_mn_activeman(mn_activeman), qman(_qman) { } @@ -895,9 +895,10 @@ void CSigningManager::UnregisterRecoveredSigsListener(CRecoveredSigsListener* l) bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigSharesManager& shareman, const uint256& id, const uint256& msgHash, const uint256& quorumHash, bool allowReSign) { - if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) { - return false; - } + if (!fMasternodeMode) return false; + + assert(m_mn_activeman); + if (WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash().IsNull())) return false; const CQuorumCPtr quorum = [&]() { if (quorumHash.IsNull()) { @@ -919,7 +920,7 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigShares return false; } - if (!WITH_LOCK(activeMasternodeInfoCs, return quorum->IsValidMember(activeMasternodeInfo.proTxHash))) { + if (!WITH_LOCK(m_mn_activeman->cs, return quorum->IsValidMember(m_mn_activeman->GetProTxHash()))) { return false; } diff --git a/src/llmq/signing.h b/src/llmq/signing.h index 1d4c0bd459..4a00bd248c 100644 --- a/src/llmq/signing.h +++ b/src/llmq/signing.h @@ -18,6 +18,7 @@ #include +class CActiveMasternodeManager; class CConnman; class CDataStream; class CDBBatch; @@ -162,6 +163,7 @@ private: CRecoveredSigsDb db; CConnman& connman; + const CActiveMasternodeManager* m_mn_activeman; const CQuorumManager& qman; std::atomic m_peerman{nullptr}; @@ -177,7 +179,7 @@ private: std::vector recoveredSigsListeners GUARDED_BY(cs); public: - CSigningManager(CConnman& _connman, const CQuorumManager& _qman, bool fMemory, bool fWipe); + CSigningManager(CConnman& _connman, const CActiveMasternodeManager* mn_activeman, const CQuorumManager& _qman, bool fMemory, bool fWipe); bool AlreadyHave(const CInv& inv) const; bool GetRecoveredSigForGetData(const uint256& hash, CRecoveredSig& ret) const; diff --git a/src/llmq/signing_shares.cpp b/src/llmq/signing_shares.cpp index 4032d38758..395e7d1723 100644 --- a/src/llmq/signing_shares.cpp +++ b/src/llmq/signing_shares.cpp @@ -218,9 +218,10 @@ void CSigSharesManager::InterruptWorkerThread() void CSigSharesManager::ProcessMessage(const CNode& pfrom, const CSporkManager& sporkman, const std::string& msg_type, CDataStream& vRecv) { // non-masternodes are not interested in sigshares - if (!fMasternodeMode || WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash.IsNull())) { - return; - } + if (!fMasternodeMode) return; + + assert(m_mn_activeman); + if (WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash().IsNull())) return; if (sporkman.IsSporkActive(SPORK_21_QUORUM_ALL_CONNECTED) && msg_type == NetMsgType::QSIGSHARE) { std::vector receivedSigShares; @@ -408,7 +409,7 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(const CNode& pfrom, const return true; } - if (bool ban{false}; !PreVerifyBatchedSigShares(qman, sessionInfo, batchedSigShares, ban)) { + if (bool ban{false}; !PreVerifyBatchedSigShares(*Assert(m_mn_activeman), qman, sessionInfo, batchedSigShares, ban)) { return !ban; } @@ -457,6 +458,8 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(const CNode& pfrom, const void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& sigShare) { + assert(m_mn_activeman); + auto quorum = qman.GetQuorum(sigShare.getLlmqType(), sigShare.getQuorumHash()); if (!quorum) { return; @@ -465,7 +468,7 @@ void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& s // quorum is too old return; } - if (!quorum->IsMember(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) { + if (!quorum->IsMember(WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()))) { // we're not a member so we can't verify it (we actually shouldn't have received it) return; } @@ -506,7 +509,8 @@ void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& s sigShare.GetSignHash().ToString(), sigShare.getId().ToString(), sigShare.getMsgHash().ToString(), sigShare.getQuorumMember(), fromId); } -bool CSigSharesManager::PreVerifyBatchedSigShares(const CQuorumManager& quorum_manager, const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan) +bool CSigSharesManager::PreVerifyBatchedSigShares(const CActiveMasternodeManager& mn_activeman, const CQuorumManager& quorum_manager, + const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan) { retBan = false; @@ -514,7 +518,7 @@ bool CSigSharesManager::PreVerifyBatchedSigShares(const CQuorumManager& quorum_m // quorum is too old return false; } - if (!session.quorum->IsMember(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) { + if (!session.quorum->IsMember(WITH_LOCK(mn_activeman.cs, return mn_activeman.GetProTxHash()))) { // we're not a member so we can't verify it (we actually shouldn't have received it) return false; } @@ -692,13 +696,14 @@ void CSigSharesManager::ProcessPendingSigShares(const std::vector& si // sig shares are already verified when entering this method void CSigSharesManager::ProcessSigShare(const CSigShare& sigShare, const CConnman& connman, const CQuorumCPtr& quorum) { - auto llmqType = quorum->params.type; + assert(m_mn_activeman); + auto llmqType = quorum->params.type; bool canTryRecovery = false; // prepare node set for direct-push in case this is our sig share std::set quorumNodes; - if (!IsAllMembersConnectedEnabled(llmqType, m_sporkman) && sigShare.getQuorumMember() == quorum->GetMemberIndex(WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash))) { + if (!IsAllMembersConnectedEnabled(llmqType, m_sporkman) && sigShare.getQuorumMember() == quorum->GetMemberIndex(WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()))) { quorumNodes = connman.GetMasternodeQuorumNodes(sigShare.getLlmqType(), sigShare.getQuorumHash()); } @@ -1488,8 +1493,10 @@ void CSigSharesManager::SignPendingSigShares() std::optional CSigSharesManager::CreateSigShare(const CQuorumCPtr& quorum, const uint256& id, const uint256& msgHash) const { + assert(m_mn_activeman); + cxxtimer::Timer t(true); - auto activeMasterNodeProTxHash = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash); + auto activeMasterNodeProTxHash = WITH_LOCK(m_mn_activeman->cs, return m_mn_activeman->GetProTxHash()); if (!quorum->IsValidMember(activeMasterNodeProTxHash)) { return std::nullopt; diff --git a/src/llmq/signing_shares.h b/src/llmq/signing_shares.h index 173c7d0395..d678e99d80 100644 --- a/src/llmq/signing_shares.h +++ b/src/llmq/signing_shares.h @@ -401,6 +401,7 @@ private: CConnman& connman; CSigningManager& sigman; + const CActiveMasternodeManager* m_mn_activeman; const CQuorumManager& qman; const CSporkManager& m_sporkman; @@ -410,8 +411,9 @@ private: std::atomic recoveredSigsCounter{0}; public: - explicit CSigSharesManager(CConnman& _connman, CSigningManager& _sigman, const CQuorumManager& _qman, const CSporkManager& sporkman, const std::unique_ptr& peerman) : - connman(_connman), sigman(_sigman), qman(_qman), m_sporkman(sporkman), m_peerman(peerman) + explicit CSigSharesManager(CConnman& _connman, CSigningManager& _sigman, const CActiveMasternodeManager* mn_activeman, + const CQuorumManager& _qman, const CSporkManager& sporkman, const std::unique_ptr& peerman) : + connman(_connman), sigman(_sigman), m_mn_activeman(mn_activeman), qman(_qman), m_sporkman(sporkman), m_peerman(peerman) { workInterrupt.reset(); }; @@ -443,7 +445,8 @@ private: void ProcessMessageSigShare(NodeId fromId, const CSigShare& sigShare); static bool VerifySigSharesInv(Consensus::LLMQType llmqType, const CSigSharesInv& inv); - static bool PreVerifyBatchedSigShares(const CQuorumManager& quorum_manager, const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan); + static bool PreVerifyBatchedSigShares(const CActiveMasternodeManager& mn_activeman, const CQuorumManager& quorum_manager, + const CSigSharesNodeState::SessionInfo& session, const CBatchedSigShares& batchedSigShares, bool& retBan); void CollectPendingSigSharesToVerify(size_t maxUniqueSessions, std::unordered_map>& retSigShares, diff --git a/src/masternode/node.cpp b/src/masternode/node.cpp index 5c246c2cb1..b822728dc1 100644 --- a/src/masternode/node.cpp +++ b/src/masternode/node.cpp @@ -4,24 +4,34 @@ #include -#include - +#include #include #include +#include #include #include #include +#include #include #include // Keep track of the active Masternode -RecursiveMutex activeMasternodeInfoCs; -CActiveMasternodeInfo activeMasternodeInfo GUARDED_BY(activeMasternodeInfoCs); std::unique_ptr activeMasternodeManager; +CActiveMasternodeManager::CActiveMasternodeManager(const CBLSSecretKey& sk, CConnman& connman, const std::unique_ptr& dmnman) : + m_info(sk, sk.GetPublicKey()), + m_connman{connman}, + m_dmnman{dmnman} +{ + assert(sk.IsValid()); /* We can assume pk is valid if sk is valid */ + LogPrintf("MASTERNODE:\n blsPubKeyOperator legacy: %s\n blsPubKeyOperator basic: %s\n", + m_info.blsPubKeyOperator.ToString(/*specificLegacyScheme=*/ true), + m_info.blsPubKeyOperator.ToString(/*specificLegacyScheme=*/ false)); +} + std::string CActiveMasternodeManager::GetStateString() const { - switch (state) { + switch (WITH_LOCK(cs, return m_state)) { case MASTERNODE_WAITING_FOR_PROTX: return "WAITING_FOR_PROTX"; case MASTERNODE_POSE_BANNED: @@ -43,7 +53,8 @@ std::string CActiveMasternodeManager::GetStateString() const std::string CActiveMasternodeManager::GetStatus() const { - switch (state) { + LOCK(cs); + switch (m_state) { case MASTERNODE_WAITING_FOR_PROTX: return "Waiting for ProTx to appear on-chain"; case MASTERNODE_POSE_BANNED: @@ -57,7 +68,7 @@ std::string CActiveMasternodeManager::GetStatus() const case MASTERNODE_READY: return "Ready"; case MASTERNODE_ERROR: - return "Error. " + strError; + return "Error. " + m_error; default: return "Unknown"; } @@ -65,7 +76,7 @@ std::string CActiveMasternodeManager::GetStatus() const void CActiveMasternodeManager::Init(const CBlockIndex* pindex) { - LOCK2(cs_main, activeMasternodeInfoCs); + LOCK(cs); if (!fMasternodeMode) return; @@ -74,20 +85,20 @@ void CActiveMasternodeManager::Init(const CBlockIndex* pindex) // Check that our local network configuration is correct if (!fListen && Params().RequireRoutableExternalIP()) { // listen option is probably overwritten by something else, no good - state = MASTERNODE_ERROR; - strError = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter."; - LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError); + m_state = MASTERNODE_ERROR; + m_error = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter."; + LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error); return; } - if (!GetLocalAddress(activeMasternodeInfo.service)) { - state = MASTERNODE_ERROR; + if (!GetLocalAddress(m_info.service)) { + m_state = MASTERNODE_ERROR; return; } CDeterministicMNList mnList = Assert(m_dmnman)->GetListForBlock(pindex); - CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(*activeMasternodeInfo.blsPubKeyOperator); + CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(m_info.blsPubKeyOperator); if (!dmn) { // MN not appeared on the chain yet return; @@ -95,87 +106,80 @@ void CActiveMasternodeManager::Init(const CBlockIndex* pindex) if (!mnList.IsMNValid(dmn->proTxHash)) { if (mnList.IsMNPoSeBanned(dmn->proTxHash)) { - state = MASTERNODE_POSE_BANNED; + m_state = MASTERNODE_POSE_BANNED; } else { - state = MASTERNODE_REMOVED; + m_state = MASTERNODE_REMOVED; } return; } LogPrintf("CActiveMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", dmn->proTxHash.ToString(), dmn->ToString()); - if (activeMasternodeInfo.service != dmn->pdmnState->addr) { - state = MASTERNODE_ERROR; - strError = "Local address does not match the address from ProTx"; - LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError); + if (m_info.service != dmn->pdmnState->addr) { + m_state = MASTERNODE_ERROR; + m_error = "Local address does not match the address from ProTx"; + LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error); return; } // Check socket connectivity - LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", activeMasternodeInfo.service.ToString()); - std::unique_ptr sock = CreateSock(activeMasternodeInfo.service); + LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", m_info.service.ToString()); + std::unique_ptr sock = CreateSock(m_info.service); if (!sock) { - state = MASTERNODE_ERROR; - strError = "Could not create socket to connect to " + activeMasternodeInfo.service.ToString(); - LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError); + m_state = MASTERNODE_ERROR; + m_error = "Could not create socket to connect to " + m_info.service.ToString(); + LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error); return; } - bool fConnected = ConnectSocketDirectly(activeMasternodeInfo.service, *sock, nConnectTimeout, true) && IsSelectableSocket(sock->Get()); + bool fConnected = ConnectSocketDirectly(m_info.service, *sock, nConnectTimeout, true) && IsSelectableSocket(sock->Get()); sock->Reset(); if (!fConnected && Params().RequireRoutableExternalIP()) { - state = MASTERNODE_ERROR; - strError = "Could not connect to " + activeMasternodeInfo.service.ToString(); - LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError); + m_state = MASTERNODE_ERROR; + m_error = "Could not connect to " + m_info.service.ToString(); + LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error); return; } - activeMasternodeInfo.proTxHash = dmn->proTxHash; - activeMasternodeInfo.outpoint = dmn->collateralOutpoint; - activeMasternodeInfo.legacy = dmn->pdmnState->nVersion == CProRegTx::LEGACY_BLS_VERSION; - state = MASTERNODE_READY; + m_info.proTxHash = dmn->proTxHash; + m_info.outpoint = dmn->collateralOutpoint; + m_info.legacy = dmn->pdmnState->nVersion == CProRegTx::LEGACY_BLS_VERSION; + m_state = MASTERNODE_READY; } void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) { - LOCK2(cs_main, activeMasternodeInfoCs); - if (!fMasternodeMode) return; if (!DeploymentDIP0003Enforced(pindexNew->nHeight, Params().GetConsensus())) return; - if (state == MASTERNODE_READY) { + const auto [cur_state, cur_protx_hash] = WITH_LOCK(cs, return std::make_pair(m_state, m_info.proTxHash)); + if (cur_state == MASTERNODE_READY) { auto oldMNList = Assert(m_dmnman)->GetListForBlock(pindexNew->pprev); auto newMNList = m_dmnman->GetListForBlock(pindexNew); - if (!newMNList.IsMNValid(activeMasternodeInfo.proTxHash)) { - // MN disappeared from MN list - state = MASTERNODE_REMOVED; - activeMasternodeInfo.proTxHash = uint256(); - activeMasternodeInfo.outpoint.SetNull(); + auto reset = [this, pindexNew] (masternode_state_t state) -> void { + LOCK(cs); + m_state = state; + m_info.proTxHash = uint256(); + m_info.outpoint.SetNull(); // MN might have reappeared in same block with a new ProTx Init(pindexNew); - return; + }; + + if (!newMNList.IsMNValid(cur_protx_hash)) { + // MN disappeared from MN list + return reset(MASTERNODE_REMOVED); } - auto oldDmn = oldMNList.GetMN(activeMasternodeInfo.proTxHash); - auto newDmn = newMNList.GetMN(activeMasternodeInfo.proTxHash); + auto oldDmn = oldMNList.GetMN(cur_protx_hash); + auto newDmn = newMNList.GetMN(cur_protx_hash); if (newDmn->pdmnState->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) { // MN operator key changed or revoked - state = MASTERNODE_OPERATOR_KEY_CHANGED; - activeMasternodeInfo.proTxHash = uint256(); - activeMasternodeInfo.outpoint.SetNull(); - // MN might have reappeared in same block with a new ProTx - Init(pindexNew); - return; + return reset(MASTERNODE_OPERATOR_KEY_CHANGED); } - if (newDmn->pdmnState->addr != oldDmn->pdmnState->addr) { // MN IP changed - state = MASTERNODE_PROTX_IP_CHANGED; - activeMasternodeInfo.proTxHash = uint256(); - activeMasternodeInfo.outpoint.SetNull(); - Init(pindexNew); - return; + return reset(MASTERNODE_PROTX_IP_CHANGED); } } else { // MN might have (re)appeared with a new ProTx or we've found some peers @@ -203,8 +207,8 @@ bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet) if (!fFoundLocal) { bool empty = true; // If we have some peers, let's try to find our local address from one of them - auto service = WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.service); - connman.ForEachNodeContinueIf(CConnman::AllNodes, [&](CNode* pnode) { + auto service = WITH_LOCK(cs, return m_info.service); + m_connman.ForEachNodeContinueIf(CConnman::AllNodes, [&](CNode* pnode) { empty = false; if (pnode->addr.IsIPv4()) fFoundLocal = GetLocal(service, &pnode->addr) && IsValidNetAddr(service); @@ -212,8 +216,9 @@ bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet) }); // nothing and no live connections, can't do anything for now if (empty) { - strError = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only."; - LogPrintf("CActiveMasternodeManager::GetLocalAddress -- ERROR: %s\n", strError); + LOCK(cs); + m_error = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only."; + LogPrintf("CActiveMasternodeManager::GetLocalAddress -- ERROR: %s\n", m_error); return false; } } @@ -227,3 +232,34 @@ bool CActiveMasternodeManager::IsValidNetAddr(const CService& addrIn) return !Params().RequireRoutableExternalIP() || (addrIn.IsIPv4() && IsReachable(addrIn) && addrIn.IsRoutable()); } + +template