diff --git a/src/Makefile.am b/src/Makefile.am index 009f91437a96..f2246d57c0c0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -262,6 +262,8 @@ BITCOIN_CORE_H = \ logging.h \ logging/timer.h \ mapport.h \ + masternode/active/context.h \ + masternode/active/notificationinterface.h \ masternode/node.h \ masternode/meta.h \ masternode/payments.h \ @@ -520,6 +522,8 @@ libbitcoin_node_a_SOURCES = \ llmq/snapshot.cpp \ llmq/utils.cpp \ mapport.cpp \ + masternode/active/context.cpp \ + masternode/active/notificationinterface.cpp \ masternode/node.cpp \ masternode/meta.cpp \ masternode/payments.cpp \ diff --git a/src/chainlock/chainlock.cpp b/src/chainlock/chainlock.cpp index 15e235dea093..8026e2e88765 100644 --- a/src/chainlock/chainlock.cpp +++ b/src/chainlock/chainlock.cpp @@ -44,8 +44,7 @@ bool AreChainLocksEnabled(const CSporkManager& sporkman) } CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman, - CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool, - const CMasternodeSync& mn_sync, bool is_masternode) : + CSporkManager& sporkman, CTxMemPool& _mempool, const CMasternodeSync& mn_sync) : m_chainstate{chainstate}, qman{_qman}, spork_manager{sporkman}, @@ -53,10 +52,7 @@ CChainLocksHandler::CChainLocksHandler(CChainState& chainstate, CQuorumManager& m_mn_sync{mn_sync}, scheduler{std::make_unique()}, scheduler_thread{ - std::make_unique(std::thread(util::TraceThread, "cl-schdlr", [&] { scheduler->serviceQueue(); }))}, - m_signer{is_masternode - ? std::make_unique(chainstate, *this, _sigman, _shareman, sporkman, mn_sync) - : nullptr} + std::make_unique(std::thread(util::TraceThread, "cl-schdlr", [&] { scheduler->serviceQueue(); }))} { } diff --git a/src/chainlock/chainlock.h b/src/chainlock/chainlock.h index e7060537df4c..297f0ef3168b 100644 --- a/src/chainlock/chainlock.h +++ b/src/chainlock/chainlock.h @@ -33,7 +33,6 @@ namespace llmq { class CInstantSendManager; class CQuorumManager; class CSigningManager; -class CSigSharesManager; enum class VerifyRecSigStatus; class CChainLocksHandler final : public chainlock::ChainLockSignerParent @@ -47,7 +46,7 @@ class CChainLocksHandler final : public chainlock::ChainLockSignerParent std::unique_ptr scheduler; std::unique_ptr scheduler_thread; - std::unique_ptr m_signer{nullptr}; + chainlock::ChainLockSigner* m_signer{nullptr}; mutable Mutex cs; std::atomic tryLockChainTipScheduled{false}; @@ -68,10 +67,17 @@ class CChainLocksHandler final : public chainlock::ChainLockSignerParent public: explicit CChainLocksHandler(CChainState& chainstate, CQuorumManager& _qman, CSigningManager& _sigman, - CSigSharesManager& _shareman, CSporkManager& sporkman, CTxMemPool& _mempool, - const CMasternodeSync& mn_sync, bool is_masternode); + CSporkManager& sporkman, CTxMemPool& _mempool, const CMasternodeSync& mn_sync); ~CChainLocksHandler(); + void ConnectSigner(gsl::not_null signer) + { + // Prohibit double initialization + assert(m_signer == nullptr); + m_signer = signer; + } + void DisconnectSigner() { m_signer = nullptr; } + void Start(const llmq::CInstantSendManager& isman); void Stop(); diff --git a/src/coinjoin/context.cpp b/src/coinjoin/context.cpp index ced47cdf2374..52884e802b0e 100644 --- a/src/coinjoin/context.cpp +++ b/src/coinjoin/context.cpp @@ -7,13 +7,11 @@ #ifdef ENABLE_WALLET #include #endif // ENABLE_WALLET -#include +#include -CJContext::CJContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, - CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, - const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - const llmq::CInstantSendManager& isman, std::unique_ptr& peerman, bool relay_txes) : - dstxman{std::make_unique()}, +CJContext::CJContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, + CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, + const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, bool relay_txes) : #ifdef ENABLE_WALLET walletman{std::make_unique(chainman, dmnman, mn_metaman, mempool, mn_sync, isman, queueman, /*is_masternode=*/mn_activeman != nullptr)}, @@ -21,8 +19,7 @@ CJContext::CJContext(ChainstateManager& chainman, CConnman& connman, CDeterminis /*is_masternode=*/mn_activeman != nullptr) : nullptr}, #endif // ENABLE_WALLET - server{std::make_unique(chainman, connman, dmnman, *dstxman, mn_metaman, mempool, mn_activeman, - mn_sync, isman, peerman)} + dstxman{std::make_unique()} {} CJContext::~CJContext() {} diff --git a/src/coinjoin/context.h b/src/coinjoin/context.h index bc31718cff59..eb924f345772 100644 --- a/src/coinjoin/context.h +++ b/src/coinjoin/context.h @@ -12,16 +12,12 @@ #include class CActiveMasternodeManager; -class CBlockPolicyEstimator; -class CCoinJoinServer; -class CConnman; class CDeterministicMNManager; class CDSTXManager; class ChainstateManager; class CMasternodeMetaMan; class CMasternodeSync; class CTxMemPool; -class PeerManager; namespace llmq { class CInstantSendManager; }; @@ -34,19 +30,17 @@ class CoinJoinWalletManager; struct CJContext { CJContext() = delete; CJContext(const CJContext&) = delete; - CJContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, - CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman, - std::unique_ptr& peerman, bool relay_txes); + CJContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, + CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, + const llmq::CInstantSendManager& isman, bool relay_txes); ~CJContext(); - const std::unique_ptr dstxman; #ifdef ENABLE_WALLET // The main object for accessing mixing const std::unique_ptr walletman; const std::unique_ptr queueman; #endif // ENABLE_WALLET - const std::unique_ptr server; + const std::unique_ptr dstxman; }; #endif // BITCOIN_COINJOIN_CONTEXT_H diff --git a/src/coinjoin/server.cpp b/src/coinjoin/server.cpp index ad068dc59db1..23c8f5e09a86 100644 --- a/src/coinjoin/server.cpp +++ b/src/coinjoin/server.cpp @@ -25,7 +25,6 @@ MessageProcessingResult CCoinJoinServer::ProcessMessage(CNode& peer, std::string_view msg_type, CDataStream& vRecv) { - if (!m_mn_activeman) return {}; if (!m_mn_sync.IsBlockchainSynced()) return {}; if (msg_type == NetMsgType::DSACCEPT) { @@ -42,7 +41,6 @@ MessageProcessingResult CCoinJoinServer::ProcessMessage(CNode& peer, std::string void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) { - assert(m_mn_activeman); assert(m_mn_metaman.IsValid()); if (IsSessionReady()) { @@ -58,7 +56,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 = mnList.GetValidMNByCollateral(m_mn_activeman->GetOutPoint()); + auto dmn = mnList.GetValidMNByCollateral(m_mn_activeman.GetOutPoint()); if (!dmn) { PushStatus(peer, STATUS_REJECTED, ERR_MN_LIST); return; @@ -69,7 +67,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv) TRY_LOCK(cs_vecqueue, lockRecv); if (!lockRecv) return; - auto mnOutpoint = m_mn_activeman->GetOutPoint(); + auto mnOutpoint = m_mn_activeman.GetOutPoint(); if (ranges::any_of(vecCoinJoinQueue, [&mnOutpoint](const auto& q){return q.masternodeOutpoint == mnOutpoint;})) { @@ -183,7 +181,7 @@ MessageProcessingResult CCoinJoinServer::ProcessDSQUEUE(NodeId from, CDataStream TRY_LOCK(cs_vecqueue, lockRecv); if (!lockRecv) return ret; vecCoinJoinQueue.push_back(dsq); - m_peerman->RelayDSQ(dsq); + m_peerman.RelayDSQ(dsq); } return ret; } @@ -254,8 +252,6 @@ void CCoinJoinServer::SetNull() // void CCoinJoinServer::CheckPool() { - if (!m_mn_activeman) return; - if (int entries = GetEntriesCount(); entries != 0) LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CheckPool -- entries count %lu\n", entries); // If we have an entry for each collateral, then create final tx @@ -317,7 +313,6 @@ void CCoinJoinServer::CreateFinalTransaction() void CCoinJoinServer::CommitFinalTransaction() { AssertLockNotHeld(cs_coinjoin); - if (!m_mn_activeman) return; // check and relay final tx only on masternode CTransactionRef finalTransaction = WITH_LOCK(cs_coinjoin, return MakeTransactionRef(finalMutableTransaction)); uint256 hashTx = finalTransaction->GetHash(); @@ -341,18 +336,16 @@ void CCoinJoinServer::CommitFinalTransaction() // create and sign masternode dstx transaction if (!m_dstxman.GetDSTX(hashTx)) { - CCoinJoinBroadcastTx dstxNew(finalTransaction, - m_mn_activeman->GetOutPoint(), - m_mn_activeman->GetProTxHash(), - GetAdjustedTime()); - dstxNew.Sign(*m_mn_activeman); + CCoinJoinBroadcastTx dstxNew(finalTransaction, m_mn_activeman.GetOutPoint(), m_mn_activeman.GetProTxHash(), + GetAdjustedTime()); + dstxNew.Sign(m_mn_activeman); m_dstxman.AddDSTX(dstxNew); } LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CommitFinalTransaction -- TRANSMITTING DSTX\n"); CInv inv(MSG_DSTX, hashTx); - Assert(m_peerman)->RelayInv(inv); + m_peerman.RelayInv(inv); // Tell the clients it was successful RelayCompletedTransaction(MSG_SUCCESS); @@ -380,7 +373,6 @@ void CCoinJoinServer::CommitFinalTransaction() void CCoinJoinServer::ChargeFees() const { AssertLockNotHeld(cs_coinjoin); - if (!m_mn_activeman) return; //we don't need to charge collateral for every offence. if (GetRand(/*nMax=*/100) > 33) return; @@ -448,8 +440,6 @@ void CCoinJoinServer::ChargeFees() const */ void CCoinJoinServer::ChargeRandomFees() const { - if (!m_mn_activeman) return; - for (const auto& txCollateral : vecSessionCollaterals) { if (GetRand(/*nMax=*/100) > 10) return; LogPrint(BCLog::COINJOIN, "CCoinJoinServer::ChargeRandomFees -- charging random fees, txCollateral=%s", txCollateral->ToString()); /* Continued */ @@ -463,15 +453,13 @@ void CCoinJoinServer::ConsumeCollateral(const CTransactionRef& txref) const if (!ATMPIfSaneFee(m_chainman, txref)) { LogPrint(BCLog::COINJOIN, "%s -- ATMPIfSaneFee failed\n", __func__); } else { - Assert(m_peerman)->RelayTransaction(txref->GetHash()); + m_peerman.RelayTransaction(txref->GetHash()); LogPrint(BCLog::COINJOIN, "%s -- Collateral was consumed\n", __func__); } } bool CCoinJoinServer::HasTimedOut() const { - if (!m_mn_activeman) return false; - if (nState == POOL_STATE_IDLE) return false; int nTimeout = (nState == POOL_STATE_SIGNING) ? COINJOIN_SIGNING_TIMEOUT : COINJOIN_QUEUE_TIMEOUT; @@ -484,8 +472,6 @@ bool CCoinJoinServer::HasTimedOut() const // void CCoinJoinServer::CheckTimeout() { - if (!m_mn_activeman) return; - CheckQueue(); // Too early to do anything @@ -504,19 +490,15 @@ void CCoinJoinServer::CheckTimeout() */ void CCoinJoinServer::CheckForCompleteQueue() { - if (!m_mn_activeman) return; - if (nState == POOL_STATE_QUEUE && IsSessionReady()) { SetState(POOL_STATE_ACCEPTING_ENTRIES); - CCoinJoinQueue dsq(nSessionDenom, - m_mn_activeman->GetOutPoint(), - m_mn_activeman->GetProTxHash(), - GetAdjustedTime(), true); + CCoinJoinQueue dsq(nSessionDenom, m_mn_activeman.GetOutPoint(), 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(*m_mn_activeman); - m_peerman->RelayDSQ(dsq); + dsq.Sign(m_mn_activeman); + m_peerman.RelayDSQ(dsq); WITH_LOCK(cs_vecqueue, vecCoinJoinQueue.push_back(dsq)); } } @@ -572,7 +554,6 @@ bool CCoinJoinServer::IsInputScriptSigValid(const CTxIn& txin) const bool CCoinJoinServer::AddEntry(const CCoinJoinEntry& entry, PoolMessage& nMessageIDRet) { AssertLockNotHeld(cs_coinjoin); - if (!m_mn_activeman) return false; if (size_t(GetEntriesCount()) >= vecSessionCollaterals.size()) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR: entries is full!\n", __func__); @@ -682,8 +663,6 @@ bool CCoinJoinServer::IsSignaturesComplete() const bool CCoinJoinServer::IsAcceptableDSA(const CCoinJoinAccept& dsa, PoolMessage& nMessageIDRet) const { - if (!m_mn_activeman) return false; - // is denom even something legit? if (!CoinJoin::IsValidDenomination(dsa.nDenom)) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- denom not valid!\n", __func__); @@ -703,7 +682,7 @@ bool CCoinJoinServer::IsAcceptableDSA(const CCoinJoinAccept& dsa, PoolMessage& n bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage& nMessageIDRet) { - if (!m_mn_activeman || nSessionID != 0) return false; + if (nSessionID != 0) return false; // new session can only be started in idle mode if (nState != POOL_STATE_IDLE) { @@ -725,13 +704,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, - m_mn_activeman->GetOutPoint(), - m_mn_activeman->GetProTxHash(), - GetAdjustedTime(), false); + CCoinJoinQueue dsq(nSessionDenom, m_mn_activeman.GetOutPoint(), m_mn_activeman.GetProTxHash(), + GetAdjustedTime(), false); LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString()); - dsq.Sign(*m_mn_activeman); - m_peerman->RelayDSQ(dsq); + dsq.Sign(m_mn_activeman); + m_peerman.RelayDSQ(dsq); LOCK(cs_vecqueue); vecCoinJoinQueue.push_back(dsq); } @@ -745,7 +722,7 @@ bool CCoinJoinServer::CreateNewSession(const CCoinJoinAccept& dsa, PoolMessage& bool CCoinJoinServer::AddUserToExistingSession(const CCoinJoinAccept& dsa, PoolMessage& nMessageIDRet) { - if (!m_mn_activeman || nSessionID == 0 || IsSessionReady()) return false; + if (nSessionID == 0 || IsSessionReady()) return false; if (!IsAcceptableDSA(dsa, nMessageIDRet)) { return false; @@ -881,8 +858,6 @@ void CCoinJoinServer::RelayCompletedTransaction(PoolMessage nMessageID) void CCoinJoinServer::SetState(PoolState nStateNew) { - if (!m_mn_activeman) return; - if (nStateNew == POOL_STATE_ERROR) { LogPrint(BCLog::COINJOIN, "CCoinJoinServer::SetState -- Can't set state to ERROR as a Masternode. \n"); return; @@ -895,7 +870,6 @@ void CCoinJoinServer::SetState(PoolState nStateNew) void CCoinJoinServer::DoMaintenance() { - if (!m_mn_activeman) return; // only run on masternodes if (!m_mn_sync.IsBlockchainSynced()) return; if (ShutdownRequested()) return; diff --git a/src/coinjoin/server.h b/src/coinjoin/server.h index eee182fb9230..31099a6ac384 100644 --- a/src/coinjoin/server.h +++ b/src/coinjoin/server.h @@ -35,10 +35,10 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager CDSTXManager& m_dstxman; CMasternodeMetaMan& m_mn_metaman; CTxMemPool& mempool; - const CActiveMasternodeManager* const m_mn_activeman; + PeerManager& m_peerman; + const CActiveMasternodeManager& m_mn_activeman; const CMasternodeSync& m_mn_sync; const llmq::CInstantSendManager& m_isman; - std::unique_ptr& m_peerman; // Mixing uses collateral transactions to trust parties entering the pool // to behave honestly. If they don't it takes their money. @@ -95,18 +95,18 @@ class CCoinJoinServer : public CCoinJoinBaseSession, public CCoinJoinBaseManager public: explicit CCoinJoinServer(ChainstateManager& chainman, CConnman& _connman, CDeterministicMNManager& dmnman, CDSTXManager& dstxman, CMasternodeMetaMan& mn_metaman, CTxMemPool& mempool, - const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, - const llmq::CInstantSendManager& isman, std::unique_ptr& peerman) : + PeerManager& peerman, const CActiveMasternodeManager& mn_activeman, + const CMasternodeSync& mn_sync, const llmq::CInstantSendManager& isman) : m_chainman(chainman), connman(_connman), m_dmnman(dmnman), m_dstxman(dstxman), m_mn_metaman(mn_metaman), mempool(mempool), + m_peerman(peerman), m_mn_activeman(mn_activeman), m_mn_sync(mn_sync), m_isman{isman}, - m_peerman(peerman), vecSessionCollaterals(), fUnitTest(false) {} diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 1b6d80b68737..95066be54658 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -92,7 +92,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con m_llmq_ctx->qman->UpdatedBlockTip(pindexNew, m_connman, fInitialDownload); m_llmq_ctx->qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload); - m_llmq_ctx->ehfSignalsHandler->UpdatedBlockTip(pindexNew, /* is_masternode = */ m_mn_activeman != nullptr); if (m_govman.IsValid()) { m_govman.UpdatedBlockTip(pindexNew, m_connman, m_peerman, m_mn_activeman); diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index 16a32e033367..d56c87952e99 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -1360,7 +1360,7 @@ int CGovernanceManager::RequestGovernanceObjectVotes(const std::vector& // Don't try to sync any data from outbound non-relay "masternode" connections. // Inbound connection this early is most likely a "masternode" connection // initiated from another node, so skip it too. - if (!pnode->CanRelay() || (fMasternodeMode && pnode->IsInboundConn())) continue; + if (!pnode->CanRelay() || (connman.IsActiveMasternode() && pnode->IsInboundConn())) continue; // stop early to prevent setAskFor overflow { LOCK(::cs_main); diff --git a/src/init.cpp b/src/init.cpp index 6a96d6dd4a9c..8b870c4c24a4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -91,6 +91,8 @@ #include #include #include +#include +#include #include #include #include @@ -319,8 +321,14 @@ void PrepareShutdown(NodeContext& node) // CValidationInterface callbacks, flush them... GetMainSignals().FlushBackgroundCallbacks(); + if (g_active_notification_interface) { + UnregisterValidationInterface(g_active_notification_interface.get()); + g_active_notification_interface.reset(); + } + // After all scheduled tasks have been flushed, destroy pointers // and reset all to nullptr. + node.active_ctx.reset(); node.mn_sync.reset(); node.sporkman.reset(); node.govman.reset(); @@ -374,10 +382,7 @@ void PrepareShutdown(NodeContext& node) g_ds_notification_interface.reset(); } - if (node.mn_activeman) { - UnregisterValidationInterface(node.mn_activeman.get()); - node.mn_activeman.reset(); - } + node.mn_activeman.reset(); node.chain_clients.clear(); @@ -1692,19 +1697,14 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } } - 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 mn_activeman, will init later in ThreadImport - node.mn_activeman = std::make_unique(keyOperator, *node.connman, node.dmnman); - RegisterValidationInterface(node.mn_activeman.get()); - } + // Create and register mn_activeman, will init later in ThreadImport + node.mn_activeman = std::make_unique(keyOperator, *node.connman, node.dmnman); } // Check port numbers @@ -2149,7 +2149,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), chainman, *node.mempool, *node.mn_metaman, *node.mn_sync, *node.govman, *node.sporkman, node.mn_activeman.get(), node.dmnman, - node.cj_ctx, node.llmq_ctx, ignores_incoming_txs); + node.active_ctx, node.cj_ctx, node.llmq_ctx, ignores_incoming_txs); RegisterValidationInterface(node.peerman.get()); g_ds_notification_interface = std::make_unique( @@ -2159,11 +2159,22 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // ********************************************************* Step 7c: Setup CoinJoin - node.cj_ctx = std::make_unique(chainman, *node.connman, *node.dmnman, *node.mn_metaman, *node.mempool, - node.mn_activeman.get(), *node.mn_sync, *node.llmq_ctx->isman, node.peerman, + node.cj_ctx = std::make_unique(chainman, *node.dmnman, *node.mn_metaman, *node.mempool, + node.mn_activeman.get(), *node.mn_sync, *node.llmq_ctx->isman, !ignores_incoming_txs); - // ********************************************************* Step 7d: Setup other Dash services + // ********************************************************* Step 7d: Setup masternode mode + assert(!node.active_ctx); + assert(!g_active_notification_interface); + if (node.mn_activeman) { + node.active_ctx = std::make_unique(chainman, *node.connman, *node.dmnman, *node.cj_ctx->dstxman, *node.mn_metaman, *node.mnhf_manager, + *node.llmq_ctx, *node.sporkman, *node.mempool, *node.peerman, *node.mn_activeman, + *node.mn_sync); + g_active_notification_interface = std::make_unique(*node.active_ctx, *node.mn_activeman); + RegisterValidationInterface(g_active_notification_interface.get()); + } + + // ********************************************************* Step 7e: Setup other Dash services bool fLoadCacheFiles = !(fReindex || fReindexChainState) && (chainman.ActiveChain().Tip() != nullptr); @@ -2272,7 +2283,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } if (node.mn_activeman) { - node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*node.cj_ctx->server)), std::chrono::seconds{1}); + node.scheduler->scheduleEvery(std::bind(&CCoinJoinServer::DoMaintenance, std::ref(*node.active_ctx->cj_server)), std::chrono::seconds{1}); node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1}); #ifdef ENABLE_WALLET } else if (!ignores_incoming_txs) { @@ -2428,6 +2439,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) connOptions.nMaxOutboundLimit = *opt_max_upload; connOptions.m_peer_connect_timeout = peer_connect_timeout; connOptions.socketEventsMode = ::g_socket_events_mode; + connOptions.m_active_masternode = node.mn_activeman != nullptr; // Port to bind to if `-bind=addr` is provided without a `:port` suffix. const uint16_t default_bind_port = diff --git a/src/instantsend/instantsend.cpp b/src/instantsend/instantsend.cpp index 2435ae3690d8..c4a2c498f027 100644 --- a/src/instantsend/instantsend.cpp +++ b/src/instantsend/instantsend.cpp @@ -50,9 +50,8 @@ std::unordered_set GetIdsFromLockable(const std::ve } // anonymous namespace CInstantSendManager::CInstantSendManager(CChainLocksHandler& _clhandler, CChainState& chainstate, CQuorumManager& _qman, - CSigningManager& _sigman, CSigSharesManager& _shareman, - CSporkManager& sporkman, CTxMemPool& _mempool, const CMasternodeSync& mn_sync, - bool is_masternode, bool unitTests, bool fWipe) : + CSigningManager& _sigman, CSporkManager& sporkman, CTxMemPool& _mempool, + const CMasternodeSync& mn_sync, bool unitTests, bool fWipe) : db{unitTests, fWipe}, clhandler{_clhandler}, m_chainstate{chainstate}, @@ -60,10 +59,7 @@ CInstantSendManager::CInstantSendManager(CChainLocksHandler& _clhandler, CChainS sigman{_sigman}, spork_manager{sporkman}, mempool{_mempool}, - m_mn_sync{mn_sync}, - m_signer{is_masternode ? std::make_unique(chainstate, _clhandler, *this, _sigman, - _shareman, _qman, sporkman, _mempool, mn_sync) - : nullptr} + m_mn_sync{mn_sync} { workInterrupt.reset(); } diff --git a/src/instantsend/instantsend.h b/src/instantsend/instantsend.h index 6a045952eee2..cefcbee04677 100644 --- a/src/instantsend/instantsend.h +++ b/src/instantsend/instantsend.h @@ -39,7 +39,6 @@ namespace llmq { class CChainLocksHandler; class CQuorumManager; class CSigningManager; -class CSigSharesManager; class CInstantSendManager final : public instantsend::InstantSendSignerParent { @@ -54,7 +53,7 @@ class CInstantSendManager final : public instantsend::InstantSendSignerParent CTxMemPool& mempool; const CMasternodeSync& m_mn_sync; - std::unique_ptr m_signer{nullptr}; + instantsend::InstantSendSigner* m_signer{nullptr}; std::thread workThread; CThreadInterrupt workInterrupt; @@ -85,11 +84,18 @@ class CInstantSendManager final : public instantsend::InstantSendSignerParent public: explicit CInstantSendManager(CChainLocksHandler& _clhandler, CChainState& chainstate, CQuorumManager& _qman, - CSigningManager& _sigman, CSigSharesManager& _shareman, CSporkManager& sporkman, - CTxMemPool& _mempool, const CMasternodeSync& mn_sync, bool is_masternode, - bool unitTests, bool fWipe); + CSigningManager& _sigman, CSporkManager& sporkman, CTxMemPool& _mempool, + const CMasternodeSync& mn_sync, bool unitTests, bool fWipe); ~CInstantSendManager(); + void ConnectSigner(gsl::not_null signer) + { + // Prohibit double initialization + assert(m_signer == nullptr); + m_signer = signer; + } + void DisconnectSigner() { m_signer = nullptr; } + void Start(PeerManager& peerman); void Stop(); void InterruptWorkerThread() { workInterrupt(); }; diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index e2a60f21420b..75e98f40bbfb 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -35,11 +34,10 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d unit_tests, wipe)}, sigman{std::make_unique(mn_activeman, chainman.ActiveChainstate(), *qman, unit_tests, wipe)}, shareman{std::make_unique(*sigman, mn_activeman, *qman, sporkman)}, - clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, *sigman, *shareman, - sporkman, mempool, mn_sync, is_masternode)}, - isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *qman, *sigman, *shareman, - sporkman, mempool, mn_sync, is_masternode, unit_tests, wipe)}, - ehfSignalsHandler{std::make_unique(chainman, mnhfman, *sigman, *shareman, *qman)} + clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, *sigman, sporkman, mempool, + mn_sync)}, + isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *qman, *sigman, sporkman, + mempool, mn_sync, unit_tests, wipe)} { // Have to start it early to let VerifyDB check ChainLock signatures in coinbase bls_worker->Start(); diff --git a/src/llmq/context.h b/src/llmq/context.h index b6586bb01186..d27b2a7a8137 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -24,7 +24,6 @@ namespace llmq { class CChainLocksHandler; class CDKGDebugManager; class CDKGSessionManager; -class CEHFSignalsHandler; class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; @@ -70,7 +69,6 @@ struct LLMQContext { const std::unique_ptr shareman; const std::unique_ptr clhandler; const std::unique_ptr isman; - const std::unique_ptr ehfSignalsHandler; }; #endif // BITCOIN_LLMQ_CONTEXT_H diff --git a/src/llmq/ehf_signals.cpp b/src/llmq/ehf_signals.cpp index 91eb293ace9c..b4689e2d4a3e 100644 --- a/src/llmq/ehf_signals.cpp +++ b/src/llmq/ehf_signals.cpp @@ -15,8 +15,6 @@ #include namespace llmq { - - CEHFSignalsHandler::CEHFSignalsHandler(ChainstateManager& chainman, CMNHFManager& mnhfman, CSigningManager& sigman, CSigSharesManager& shareman, const CQuorumManager& qman) : m_chainman(chainman), @@ -28,20 +26,15 @@ CEHFSignalsHandler::CEHFSignalsHandler(ChainstateManager& chainman, CMNHFManager sigman.RegisterRecoveredSigsListener(this); } - CEHFSignalsHandler::~CEHFSignalsHandler() { sigman.UnregisterRecoveredSigsListener(this); } -void CEHFSignalsHandler::UpdatedBlockTip(const CBlockIndex* const pindexNew, bool is_masternode) +void CEHFSignalsHandler::UpdatedBlockTip(const CBlockIndex* const pindexNew) { if (!DeploymentActiveAfter(pindexNew, Params().GetConsensus(), Consensus::DEPLOYMENT_V20)) return; - if (!is_masternode) { - return; - } - const auto ehfSignals = mnhfman.GetSignalsStage(pindexNew); for (const auto& deployment : Params().GetConsensus().vDeployments) { // Skip deployments that do not use dip0023 diff --git a/src/llmq/ehf_signals.h b/src/llmq/ehf_signals.h index b8598fa4a2d0..33283f6dbca8 100644 --- a/src/llmq/ehf_signals.h +++ b/src/llmq/ehf_signals.h @@ -13,8 +13,7 @@ class CBlockIndex; class ChainstateManager; class CMNHFManager; -namespace llmq -{ +namespace llmq { class CQuorumManager; class CSigSharesManager; class CSigningManager; @@ -39,20 +38,17 @@ class CEHFSignalsHandler : public CRecoveredSigsListener ~CEHFSignalsHandler(); - /** * Since Tip is updated it could be a time to generate EHF Signal */ - void UpdatedBlockTip(const CBlockIndex* const pindexNew, bool is_masternode) EXCLUSIVE_LOCKS_REQUIRED(!cs); + void UpdatedBlockTip(const CBlockIndex* const pindexNew) EXCLUSIVE_LOCKS_REQUIRED(!cs); [[nodiscard]] MessageProcessingResult HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) override EXCLUSIVE_LOCKS_REQUIRED(!cs); private: void trySignEHFSignal(int bit, const CBlockIndex* const pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs); - }; - } // namespace llmq #endif // BITCOIN_LLMQ_EHF_SIGNALS_H diff --git a/src/masternode/active/context.cpp b/src/masternode/active/context.cpp new file mode 100644 index 000000000000..3fdfa75bad39 --- /dev/null +++ b/src/masternode/active/context.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +ActiveContext::ActiveContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, + CDSTXManager& dstxman, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, + LLMQContext& llmq_ctx, CSporkManager& sporkman, CTxMemPool& mempool, PeerManager& peerman, + const CActiveMasternodeManager& mn_activeman, const CMasternodeSync& mn_sync) : + m_llmq_ctx{llmq_ctx}, + cl_signer{std::make_unique(chainman.ActiveChainstate(), *llmq_ctx.clhandler, + *llmq_ctx.sigman, *llmq_ctx.shareman, sporkman, mn_sync)}, + is_signer{std::make_unique(chainman.ActiveChainstate(), *llmq_ctx.clhandler, + *llmq_ctx.isman, *llmq_ctx.sigman, *llmq_ctx.shareman, + *llmq_ctx.qman, sporkman, mempool, mn_sync)}, + cj_server{std::make_unique(chainman, connman, dmnman, dstxman, mn_metaman, mempool, peerman, + mn_activeman, mn_sync, *llmq_ctx.isman)}, + ehf_sighandler{std::make_unique(chainman, mnhfman, *llmq_ctx.sigman, *llmq_ctx.shareman, + *llmq_ctx.qman)} +{ + m_llmq_ctx.clhandler->ConnectSigner(cl_signer.get()); + m_llmq_ctx.isman->ConnectSigner(is_signer.get()); +} + +ActiveContext::~ActiveContext() +{ + m_llmq_ctx.clhandler->DisconnectSigner(); + m_llmq_ctx.isman->DisconnectSigner(); +} diff --git a/src/masternode/active/context.h b/src/masternode/active/context.h new file mode 100644 index 000000000000..7dd04a507b47 --- /dev/null +++ b/src/masternode/active/context.h @@ -0,0 +1,63 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_MASTERNODE_ACTIVE_CONTEXT_H +#define BITCOIN_MASTERNODE_ACTIVE_CONTEXT_H + +#include + +class CActiveMasternodeManager; +class ChainstateManager; +class CCoinJoinServer; +class CConnman; +class CDeterministicMNManager; +class CDSTXManager; +class CMasternodeMetaMan; +class CMasternodeSync; +class CMNHFManager; +class CSporkManager; +class CTxMemPool; +class PeerManager; +struct LLMQContext; +namespace chainlock { +class ChainLockSigner; +} // namespace chainlock +namespace instantsend { +class InstantSendSigner; +} // namespace instantsend +namespace llmq { +class CEHFSignalsHandler; +} // namespace llmq + +struct ActiveContext { +private: + // TODO: Switch to references to members when migration is finished + LLMQContext& m_llmq_ctx; + + /* + * Entities that are registered with LLMQContext members are not accessible + * and are managed with (Dis)connectSigner() in the (c/d)tor instead + */ + const std::unique_ptr cl_signer; + const std::unique_ptr is_signer; + +public: + ActiveContext() = delete; + ActiveContext(const ActiveContext&) = delete; + ActiveContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, + CDSTXManager& dstxman, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, LLMQContext& llmq_ctx, + CSporkManager& sporkman, CTxMemPool& mempool, PeerManager& peerman, + const CActiveMasternodeManager& mn_activeman, const CMasternodeSync& mn_sync); + ~ActiveContext(); + + /* + * Entities that are only utilized when masternode mode is enabled + * and are accessible in their own right + * TODO: Move CActiveMasternodeManager here when dependents have been migrated + */ + const std::unique_ptr cj_server; + const std::unique_ptr ehf_sighandler; +}; + +#endif // BITCOIN_MASTERNODE_ACTIVE_CONTEXT_H diff --git a/src/masternode/active/notificationinterface.cpp b/src/masternode/active/notificationinterface.cpp new file mode 100644 index 000000000000..215458a9e9dd --- /dev/null +++ b/src/masternode/active/notificationinterface.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +ActiveNotificationInterface::ActiveNotificationInterface(ActiveContext& active_ctx, CActiveMasternodeManager& mn_activeman) : + m_active_ctx{active_ctx}, + m_mn_activeman{mn_activeman} +{ +} + +void ActiveNotificationInterface::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, + bool fInitialDownload) +{ + if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones + return; + + m_mn_activeman.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); + m_active_ctx.ehf_sighandler->UpdatedBlockTip(pindexNew); +} + +std::unique_ptr g_active_notification_interface; diff --git a/src/masternode/active/notificationinterface.h b/src/masternode/active/notificationinterface.h new file mode 100644 index 000000000000..ecb3f9fa962c --- /dev/null +++ b/src/masternode/active/notificationinterface.h @@ -0,0 +1,32 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_MASTERNODE_ACTIVE_NOTIFICATIONINTERFACE_H +#define BITCOIN_MASTERNODE_ACTIVE_NOTIFICATIONINTERFACE_H + +#include + +class CActiveMasternodeManager; +struct ActiveContext; + +class ActiveNotificationInterface final : public CValidationInterface +{ +public: + ActiveNotificationInterface() = delete; + ActiveNotificationInterface(const ActiveNotificationInterface&) = delete; + explicit ActiveNotificationInterface(ActiveContext& active_ctx, CActiveMasternodeManager& mn_activeman); + virtual ~ActiveNotificationInterface() = default; + +protected: + // CValidationInterface + void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override; + +private: + ActiveContext& m_active_ctx; + CActiveMasternodeManager& m_mn_activeman; +}; + +extern std::unique_ptr g_active_notification_interface; + +#endif // BITCOIN_MASTERNODE_ACTIVE_NOTIFICATIONINTERFACE_H diff --git a/src/masternode/node.h b/src/masternode/node.h index f1a54ed2cc70..931233c42f72 100644 --- a/src/masternode/node.h +++ b/src/masternode/node.h @@ -27,7 +27,7 @@ struct CActiveMasternodeInfo { blsKeyOperator(blsKeyOperator), blsPubKeyOperator(blsPubKeyOperator) {}; }; -class CActiveMasternodeManager final : public CValidationInterface +class CActiveMasternodeManager { public: enum class MasternodeState { @@ -52,7 +52,7 @@ class CActiveMasternodeManager final : public CValidationInterface public: explicit CActiveMasternodeManager(const CBLSSecretKey& sk, CConnman& connman, const std::unique_ptr& dmnman); - void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override + void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) EXCLUSIVE_LOCKS_REQUIRED(!cs); void Init(const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs) { LOCK(cs); InitInternal(pindex); }; diff --git a/src/masternode/sync.cpp b/src/masternode/sync.cpp index fca0f0cde5cf..b9bebb07cb64 100644 --- a/src/masternode/sync.cpp +++ b/src/masternode/sync.cpp @@ -124,7 +124,7 @@ void CMasternodeSync::ProcessTick(const PeerManager& peerman, const CGovernanceM // reset the sync process if the last call to this function was more than 60 minutes ago (client was in sleep mode) static int64_t nTimeLastProcess = GetTime(); - if (!Params().IsMockableChain() && GetTime() - nTimeLastProcess > 60 * 60 && !fMasternodeMode) { + if (!Params().IsMockableChain() && GetTime() - nTimeLastProcess > 60 * 60 && !connman.IsActiveMasternode()) { LogPrintf("CMasternodeSync::ProcessTick -- WARNING: no actions for too long, restarting sync...\n"); Reset(true); nTimeLastProcess = GetTime(); @@ -157,7 +157,7 @@ void CMasternodeSync::ProcessTick(const PeerManager& peerman, const CGovernanceM // Don't try to sync any data from outbound non-relay "masternode" connections. // Inbound connection this early is most likely a "masternode" connection // initiated from another node, so skip it too. - if (!pnode->CanRelay() || (fMasternodeMode && pnode->IsInboundConn())) continue; + if (!pnode->CanRelay() || (connman.IsActiveMasternode() && pnode->IsInboundConn())) continue; { if ((pnode->HasPermission(NetPermissionFlags::NoBan) || pnode->IsManualConn()) && !m_netfulfilledman.HasFulfilledRequest(pnode->addr, strAllow)) { diff --git a/src/net.cpp b/src/net.cpp index fb56676f3d2e..a5ac046186f2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1801,7 +1801,7 @@ bool CConnman::AttemptToEvictConnection() if (node->fDisconnect) continue; - if (fMasternodeMode) { + if (m_active_masternode) { // This handles eviction protected nodes. Nodes are always protected for a short time after the connection // was accepted. This short time is meant for the VERSION/VERACK exchange and the possible MNAUTH that might // follow when the incoming connection is from another masternode. When a message other than MNAUTH @@ -1971,7 +1971,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr&& sock, } // don't accept incoming connections until blockchain is synced - if (fMasternodeMode && !mn_sync.IsBlockchainSynced()) { + if (m_active_masternode && !mn_sync.IsBlockchainSynced()) { LogPrint(BCLog::NET_NETCONN, "AcceptConnection -- blockchain is not synced yet, skipping inbound connection attempt\n"); return; } diff --git a/src/net.h b/src/net.h index 957aff1b4fd3..5568fac1ab82 100644 --- a/src/net.h +++ b/src/net.h @@ -1194,6 +1194,7 @@ friend class CNode; std::vector m_added_nodes; SocketEventsMode socketEventsMode = SocketEventsMode::Select; bool m_i2p_accept_incoming; + bool m_active_masternode = false; }; void Init(const Options& connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_total_bytes_sent_mutex) @@ -1231,6 +1232,7 @@ friend class CNode; } socketEventsMode = connOptions.socketEventsMode; m_onion_binds = connOptions.onion_binds; + m_active_masternode = connOptions.m_active_masternode; } CConnman(uint64_t seed0, uint64_t seed1, AddrMan& addrman, const NetGroupManager& netgroupman, @@ -1255,6 +1257,7 @@ friend class CNode; void SetNetworkActive(bool active, CMasternodeSync* const mn_sync); bool GetMasternodeThreadActive() const { return m_masternode_thread_active; }; void SetMasternodeThreadActive(bool active) { m_masternode_thread_active = active; }; + bool IsActiveMasternode() const { return m_active_masternode; } SocketEventsMode GetSocketEventsMode() const { return socketEventsMode; } enum class MasternodeConn { @@ -1840,6 +1843,9 @@ friend class CNode; */ std::unique_ptr m_i2p_sam_session; + /** Flag for activating masternode mode */ + bool m_active_masternode{false}; + SocketEventsMode socketEventsMode; std::unique_ptr m_edge_trig_events{nullptr}; std::unique_ptr m_wakeup_pipe{nullptr}; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index fb6f2238470c..33f3b1dd4278 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -51,6 +51,7 @@ #include #include +#include #include #include #ifdef ENABLE_WALLET @@ -595,6 +596,7 @@ class PeerManagerImpl final : public PeerManager CGovernanceManager& govman, CSporkManager& sporkman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, + const std::unique_ptr& active_ctx, const std::unique_ptr& cj_ctx, const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); @@ -776,6 +778,7 @@ class PeerManagerImpl final : public PeerManager CTxMemPool& m_mempool; std::unique_ptr m_txreconciliation; const std::unique_ptr& m_dmnman; + const std::unique_ptr& m_active_ctx; const std::unique_ptr& m_cj_ctx; const std::unique_ptr& m_llmq_ctx; CMasternodeMetaMan& m_mn_metaman; @@ -1948,10 +1951,11 @@ std::unique_ptr PeerManager::make(const CChainParams& chainparams, CGovernanceManager& govman, CSporkManager& sporkman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, + const std::unique_ptr& active_ctx, const std::unique_ptr& cj_ctx, const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) { - return std::make_unique(chainparams, connman, addrman, banman, chainman, pool, mn_metaman, mn_sync, govman, sporkman, mn_activeman, dmnman, cj_ctx, llmq_ctx, ignore_incoming_txs); + return std::make_unique(chainparams, connman, addrman, banman, chainman, pool, mn_metaman, mn_sync, govman, sporkman, mn_activeman, dmnman, active_ctx, cj_ctx, llmq_ctx, ignore_incoming_txs); } PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman, BanMan* banman, @@ -1960,6 +1964,7 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn CGovernanceManager& govman, CSporkManager& sporkman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, + const std::unique_ptr& active_ctx, const std::unique_ptr& cj_ctx, const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) @@ -1970,6 +1975,7 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn m_chainman(chainman), m_mempool(pool), m_dmnman(dmnman), + m_active_ctx(active_ctx), m_cj_ctx(cj_ctx), m_llmq_ctx(llmq_ctx), m_mn_metaman(mn_metaman), @@ -2260,9 +2266,9 @@ bool PeerManagerImpl::AlreadyHave(const CInv& inv) return m_llmq_ctx->isman->AlreadyHave(inv); case MSG_DSQ: #ifdef ENABLE_WALLET - return m_cj_ctx->server->HasQueue(inv.hash) || m_cj_ctx->queueman->HasQueue(inv.hash); + return m_cj_ctx->queueman->HasQueue(inv.hash) || (m_active_ctx && m_active_ctx->cj_server->HasQueue(inv.hash)); #else - return m_cj_ctx->server->HasQueue(inv.hash); + return m_active_ctx && m_active_ctx->cj_server->HasQueue(inv.hash); #endif } @@ -2867,7 +2873,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic } } if (!push && inv.type == MSG_DSQ) { - auto opt_dsq = m_cj_ctx->server->GetQueueFromHash(inv.hash); + auto opt_dsq = m_active_ctx ? m_active_ctx->cj_server->GetQueueFromHash(inv.hash) : std::nullopt; #ifdef ENABLE_WALLET if (!opt_dsq.has_value()) { opt_dsq = m_cj_ctx->queueman->GetQueueFromHash(inv.hash); @@ -5249,7 +5255,9 @@ void PeerManagerImpl::ProcessMessage( clientman->ProcessMessage(pfrom, m_chainman.ActiveChainstate(), m_connman, m_mempool, msg_type, vRecv); }); #endif // ENABLE_WALLET - PostProcessMessage(m_cj_ctx->server->ProcessMessage(pfrom, msg_type, vRecv), pfrom.GetId()); + if (m_active_ctx) { + PostProcessMessage(m_active_ctx->cj_server->ProcessMessage(pfrom, msg_type, vRecv), pfrom.GetId()); + } PostProcessMessage(m_sporkman.ProcessMessage(pfrom, m_connman, msg_type, vRecv), pfrom.GetId()); m_mn_sync.ProcessMessage(pfrom, msg_type, vRecv); PostProcessMessage(m_govman.ProcessMessage(pfrom, m_connman, *this, msg_type, vRecv), pfrom.GetId()); diff --git a/src/net_processing.h b/src/net_processing.h index 99356f8aa2a9..8e0b9e8f8692 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -25,6 +25,7 @@ class CGovernanceManager; class CInv; class CSporkManager; class CTransaction; +struct ActiveContext; struct CJContext; struct LLMQContext; @@ -60,6 +61,7 @@ class PeerManager : public CValidationInterface, public NetEventsInterface CGovernanceManager& govman, CSporkManager& sporkman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, + const std::unique_ptr& active_ctx, const std::unique_ptr& cj_ctx, const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); virtual ~PeerManager() { } diff --git a/src/node/context.cpp b/src/node/context.cpp index 87ead0700582..22296e423a92 100644 --- a/src/node/context.cpp +++ b/src/node/context.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/src/node/context.h b/src/node/context.h index 3ce539df983a..fc04830e72d6 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -31,6 +31,7 @@ class CTxMemPool; class CMNHFManager; class NetGroupManager; class PeerManager; +struct ActiveContext; struct CJContext; struct LLMQContext; @@ -76,19 +77,21 @@ struct NodeContext { std::unique_ptr coinjoin_loader{nullptr}; std::unique_ptr scheduler; std::function rpc_interruption_point = [] {}; - //! Dash + //! Dash managers std::unique_ptr mn_activeman; std::unique_ptr cpoolman; std::unique_ptr evodb; std::unique_ptr chain_helper; std::unique_ptr dmnman; std::unique_ptr govman; - std::unique_ptr cj_ctx; std::unique_ptr mn_metaman; std::unique_ptr mn_sync; std::unique_ptr mnhf_manager; std::unique_ptr netfulfilledman; std::unique_ptr sporkman; + //! Dash contexts + std::unique_ptr active_ctx; + std::unique_ptr cj_ctx; std::unique_ptr llmq_ctx; //! Declare default constructor and destructor that are not inline, so code diff --git a/src/rpc/coinjoin.cpp b/src/rpc/coinjoin.cpp index 539972428e7d..c7d29f65204c 100644 --- a/src/rpc/coinjoin.cpp +++ b/src/rpc/coinjoin.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -466,7 +467,7 @@ static RPCHelpMan getcoinjoininfo() const NodeContext& node = EnsureAnyNodeContext(request.context); if (node.mn_activeman) { - node.cj_ctx->server->GetJsonInfo(obj); + node.active_ctx->cj_server->GetJsonInfo(obj); return obj; } diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 8761dc406eeb..06c92a1434c5 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -20,6 +20,8 @@ #include #include +#include + #include #include @@ -146,10 +148,10 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) NodeId id{0}; const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman); - auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, /*banman=*/nullptr, *m_node.chainman, *m_node.mempool, *m_node.mn_metaman, *m_node.mn_sync, - *m_node.govman, *m_node.sporkman, /* mn_activeman = */ nullptr, m_node.dmnman, - m_node.cj_ctx, m_node.llmq_ctx, /* ignore_incoming_txs = */ false); + *m_node.govman, *m_node.sporkman, /*mn_activeman=*/ nullptr, m_node.dmnman, + /*active_ctx=*/nullptr, m_node.cj_ctx, m_node.llmq_ctx, /*ignore_incoming_txs=*/false); constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS; CConnman::Options options; @@ -250,10 +252,10 @@ BOOST_AUTO_TEST_CASE(block_relay_only_eviction) NodeId id{0}; const CChainParams& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman); - auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, + auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, /*banman=*/nullptr, *m_node.chainman, *m_node.mempool, *m_node.mn_metaman, *m_node.mn_sync, - *m_node.govman, *m_node.sporkman, /* mn_activeman = */ nullptr, m_node.dmnman, - m_node.cj_ctx, m_node.llmq_ctx, /* ignore_incoming_txs = */ false); + *m_node.govman, *m_node.sporkman, /*mn_activeman=*/ nullptr, m_node.dmnman, + /*active_ctx=*/nullptr, m_node.cj_ctx, m_node.llmq_ctx, /*ignore_incoming_txs=*/false); constexpr int max_outbound_block_relay{MAX_BLOCK_RELAY_ONLY_CONNECTIONS}; constexpr int64_t MINIMUM_CONNECT_TIME{30}; @@ -319,8 +321,8 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman); auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.chainman, *m_node.mempool, *m_node.mn_metaman, *m_node.mn_sync, - *m_node.govman, *m_node.sporkman, /* mn_activeman = */ nullptr, m_node.dmnman, - m_node.cj_ctx, m_node.llmq_ctx, /* ignore_incoming_txs = */ false); + *m_node.govman, *m_node.sporkman, /*mn_activeman=*/nullptr, m_node.dmnman, + /*active_ctx=*/nullptr, m_node.cj_ctx, m_node.llmq_ctx, /*ignore_incoming_txs=*/false); CNetAddr tor_netaddr; BOOST_REQUIRE( @@ -424,8 +426,8 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman); auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(), *m_node.chainman, *m_node.mempool, *m_node.mn_metaman, *m_node.mn_sync, - *m_node.govman, *m_node.sporkman, /* mn_activeman = */ nullptr, m_node.dmnman, - m_node.cj_ctx, m_node.llmq_ctx, /* ignore_incoming_txs = */ false); + *m_node.govman, *m_node.sporkman, /*mn_activeman=*/nullptr, m_node.dmnman, + /*active_ctx=*/nullptr, m_node.cj_ctx, m_node.llmq_ctx, /*ignore_incoming_txs=*/false); banman->ClearBanned(); int64_t nStartTime = GetTime(); diff --git a/src/test/net_peer_connection_tests.cpp b/src/test/net_peer_connection_tests.cpp index 1273babb6d34..ac8e307f463c 100644 --- a/src/test/net_peer_connection_tests.cpp +++ b/src/test/net_peer_connection_tests.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -85,8 +87,8 @@ BOOST_AUTO_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection) auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman); auto peerman = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.chainman, *m_node.mempool, *m_node.mn_metaman, *m_node.mn_sync, - *m_node.govman, *m_node.sporkman, /* mn_activeman = */ nullptr, m_node.dmnman, - m_node.cj_ctx, m_node.llmq_ctx, /* ignore_incoming_txs = */ false); + *m_node.govman, *m_node.sporkman, /*mn_activeman=*/nullptr, m_node.dmnman, + /*active_ctx=*/nullptr, m_node.cj_ctx, m_node.llmq_ctx, /*ignore_incoming_txs=*/false); NodeId id{0}; std::vector nodes; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 6c8d35946412..5ff670fab0c9 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -333,8 +334,8 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME); m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman, m_node.banman.get(), *m_node.chainman, *m_node.mempool, *m_node.mn_metaman, *m_node.mn_sync, - *m_node.govman, *m_node.sporkman, /* mn_activeman = */ nullptr, m_node.dmnman, - m_node.cj_ctx, m_node.llmq_ctx, /* ignore_incoming_txs = */ false); + *m_node.govman, *m_node.sporkman, /*mn_activeman=*/nullptr, m_node.dmnman, + /*active_ctx=*/nullptr, m_node.cj_ctx, m_node.llmq_ctx, /*ignore_incoming_txs=*/false); { CConnman::Options options; options.m_msgproc = m_node.peerman.get(); @@ -342,8 +343,8 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vectorInit(options); } - m_node.cj_ctx = std::make_unique(*m_node.chainman, *m_node.connman, *m_node.dmnman, *m_node.mn_metaman, *m_node.mempool, - /*mn_activeman=*/nullptr, *m_node.mn_sync, *m_node.llmq_ctx->isman, m_node.peerman, + m_node.cj_ctx = std::make_unique(*m_node.chainman, *m_node.dmnman, *m_node.mn_metaman, *m_node.mempool, + /*mn_activeman=*/nullptr, *m_node.mn_sync, *m_node.llmq_ctx->isman, /*relay_txes=*/true); #ifdef ENABLE_WALLET diff --git a/src/util/system.cpp b/src/util/system.cpp index caf7972e6fe2..d294d202a8c9 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -80,7 +80,6 @@ const int64_t nStartupTime = GetTime(); //Dash only features -bool fMasternodeMode = false; const std::string gCoinJoinName = "CoinJoin"; /** diff --git a/src/util/system.h b/src/util/system.h index 12e14892a3db..b8c8309bdde7 100644 --- a/src/util/system.h +++ b/src/util/system.h @@ -36,7 +36,6 @@ //Dash only features -extern bool fMasternodeMode; extern int nWalletBackups; extern const std::string gCoinJoinName; diff --git a/src/wallet/coinjoin.cpp b/src/wallet/coinjoin.cpp index bf7c39ed6f20..5731e0ab6691 100644 --- a/src/wallet/coinjoin.cpp +++ b/src/wallet/coinjoin.cpp @@ -13,7 +13,6 @@ #include #include -#include namespace wallet { void CWallet::InitCJSaltFromDb() @@ -181,7 +180,6 @@ std::vector CWallet::SelectCoinsGroupedByAddresses(bool fSkipD if (fAnonymizable) { // ignore collaterals if (CoinJoin::IsCollateralAmount(wtx.tx->vout[i].nValue)) continue; - if (fMasternodeMode && dmn_types::IsCollateralAmount(wtx.tx->vout[i].nValue)) continue; // ignore outputs that are 10 times smaller then the smallest denomination // otherwise they will just lead to higher fee / lower priority if (wtx.tx->vout[i].nValue <= nSmallestDenom / 10) continue; diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py index e1573c17d6d0..4934b002e1a9 100755 --- a/test/lint/lint-circular-dependencies.py +++ b/test/lint/lint-circular-dependencies.py @@ -26,35 +26,42 @@ "chainlock/chainlock -> instantsend/instantsend -> chainlock/chainlock", "chainlock/chainlock -> instantsend/instantsend -> instantsend/signing -> chainlock/chainlock", "chainlock/chainlock -> instantsend/instantsend -> net_processing -> chainlock/chainlock", + "chainlock/chainlock -> instantsend/instantsend -> net_processing -> masternode/active/context -> chainlock/chainlock", "chainlock/chainlock -> validation -> chainlock/chainlock", "chainlock/chainlock -> validation -> evo/chainhelper -> chainlock/chainlock", + "chainlock/signing -> instantsend/instantsend -> net_processing -> masternode/active/context -> chainlock/signing", "coinjoin/client -> net_processing -> coinjoin/client", "coinjoin/client -> net_processing -> coinjoin/context -> coinjoin/client", - "coinjoin/context -> coinjoin/server -> net_processing -> coinjoin/context", + "coinjoin/coinjoin -> instantsend/instantsend -> net_processing -> coinjoin/context -> coinjoin/coinjoin", "coinjoin/server -> net_processing -> coinjoin/server", - "common/bloom -> evo/assetlocktx -> llmq/quorums -> net -> common/bloom", + "coinjoin/server -> net_processing -> masternode/active/context -> coinjoin/server", "common/bloom -> evo/assetlocktx -> llmq/commitment -> evo/deterministicmns -> evo/simplifiedmns -> merkleblock -> common/bloom", - "evo/assetlocktx -> llmq/commitment -> validation -> txmempool -> evo/assetlocktx", + "common/bloom -> evo/assetlocktx -> llmq/quorums -> net -> common/bloom", "consensus/tx_verify -> evo/assetlocktx -> llmq/commitment -> validation -> consensus/tx_verify", "consensus/tx_verify -> evo/assetlocktx -> llmq/commitment -> validation -> txmempool -> consensus/tx_verify", + "core_io -> evo/mnhftx -> llmq/signing -> net_processing -> evo/smldiff -> core_io", + "evo/assetlocktx -> llmq/commitment -> validation -> txmempool -> evo/assetlocktx", "evo/chainhelper -> evo/specialtxman -> validation -> evo/chainhelper", "evo/deterministicmns -> index/txindex -> validation -> evo/deterministicmns", "evo/deterministicmns -> index/txindex -> validation -> txmempool -> evo/deterministicmns", "evo/netinfo -> evo/providertx -> evo/netinfo", "evo/smldiff -> llmq/blockprocessor -> llmq/utils -> llmq/snapshot -> evo/smldiff", - "core_io -> evo/mnhftx -> llmq/signing -> net_processing -> evo/smldiff -> core_io", "evo/specialtxman -> validation -> evo/specialtxman", "governance/governance -> governance/object -> governance/governance", "governance/governance -> masternode/sync -> governance/governance", "governance/governance -> net_processing -> governance/governance", "instantsend/instantsend -> net_processing -> instantsend/instantsend", "instantsend/instantsend -> net_processing -> llmq/context -> instantsend/instantsend", + "instantsend/instantsend -> net_processing -> masternode/active/context -> instantsend/instantsend", "instantsend/instantsend -> txmempool -> instantsend/instantsend", + "instantsend/signing -> llmq/signing -> net_processing -> masternode/active/context -> instantsend/signing", "llmq/blockprocessor -> llmq/utils -> llmq/snapshot -> llmq/blockprocessor", "llmq/commitment -> llmq/utils -> llmq/snapshot -> llmq/commitment", "llmq/context -> llmq/signing -> net_processing -> llmq/context", + "llmq/context -> llmq/signing -> net_processing -> masternode/active/context -> llmq/context", "llmq/dkgsession -> llmq/dkgsessionmgr -> llmq/dkgsessionhandler -> llmq/dkgsession", "llmq/dkgsessionhandler -> net_processing -> llmq/dkgsessionmgr -> llmq/dkgsessionhandler", + "llmq/ehf_signals -> llmq/signing -> net_processing -> masternode/active/context -> llmq/ehf_signals", "llmq/signing -> llmq/signing_shares -> llmq/signing", "llmq/signing -> net_processing -> llmq/signing", "llmq/signing_shares -> net_processing -> llmq/signing_shares", diff --git a/test/util/data/non-backported.txt b/test/util/data/non-backported.txt index adff5ebb6869..eaa118ca8fca 100644 --- a/test/util/data/non-backported.txt +++ b/test/util/data/non-backported.txt @@ -22,6 +22,8 @@ src/llmq/*.cpp src/llmq/*.h src/masternode/*.cpp src/masternode/*.h +src/masternode/active/*.cpp +src/masternode/active/*.h src/messagesigner.* src/netfulfilledman.* src/qt/governancelist.*