From 525c3dcb2dbd75a53d921d5f688d834b4e6a9ac9 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 7 Jan 2026 14:13:16 +0700 Subject: [PATCH 1/9] refactor: drop left-over CActiveMasternodeManager from chain state and LLMQContext --- src/llmq/context.h | 1 - src/node/chainstate.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/llmq/context.h b/src/llmq/context.h index 9bf3983158cd..677d5b6a76c9 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -9,7 +9,6 @@ #include -class CActiveMasternodeManager; class CBLSWorker; class ChainstateManager; class CDeterministicMNManager; diff --git a/src/node/chainstate.h b/src/node/chainstate.h index 4bd42375f51f..f3bf3eb3a150 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -11,7 +11,6 @@ #include #include -class CActiveMasternodeManager; class CChainstateHelper; class CCreditPoolManager; class CDeterministicMNManager; From 0949a341338ce950c148cd3b093bd9a8dcb772b5 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 14 Jan 2026 00:31:58 +0700 Subject: [PATCH 2/9] refactor: move initialization of ehf manager from init.cpp to chainhelper --- src/active/context.cpp | 16 ++++++++-------- src/active/context.h | 14 +++++++------- src/evo/chainhelper.cpp | 8 +++++--- src/evo/chainhelper.h | 4 +++- src/init.cpp | 7 ++----- src/llmq/ehf_signals.cpp | 15 +++++++-------- src/llmq/ehf_signals.h | 6 ++---- src/node/chainstate.cpp | 24 +++++++++--------------- src/node/chainstate.h | 4 ---- src/node/context.h | 2 -- src/node/miner.cpp | 5 ++--- src/node/miner.h | 2 -- src/rpc/blockchain.cpp | 2 +- src/test/util/setup_common.cpp | 8 ++------ src/validation.cpp | 6 ++++++ src/validation.h | 3 +++ 16 files changed, 57 insertions(+), 69 deletions(-) diff --git a/src/active/context.cpp b/src/active/context.cpp index a844505be505..c5fd7c9f2a7c 100644 --- a/src/active/context.cpp +++ b/src/active/context.cpp @@ -25,13 +25,13 @@ ActiveContext::ActiveContext(CBLSWorker& bls_worker, ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, CGovernanceManager& govman, CMasternodeMetaMan& mn_metaman, - CMNHFManager& mnhfman, CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks, - CTxMemPool& mempool, chainlock::ChainlockHandler& clhandler, - llmq::CInstantSendManager& isman, llmq::CQuorumBlockProcessor& qblockman, - llmq::CQuorumManager& qman, llmq::CQuorumSnapshotManager& qsnapman, - llmq::CSigningManager& sigman, PeerManager& peerman, const CMasternodeSync& mn_sync, - const CBLSSecretKey& operator_sk, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch) : + CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks, CTxMemPool& mempool, + chainlock::ChainlockHandler& clhandler, llmq::CInstantSendManager& isman, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumManager& qman, + llmq::CQuorumSnapshotManager& qsnapman, llmq::CSigningManager& sigman, + PeerManager& peerman, const CMasternodeSync& mn_sync, const CBLSSecretKey& operator_sk, + const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params, + bool quorums_recovery, bool quorums_watch) : m_isman{isman}, m_qman{qman}, nodeman{std::make_unique(connman, dmnman, operator_sk)}, @@ -40,7 +40,7 @@ ActiveContext::ActiveContext(CBLSWorker& bls_worker, ChainstateManager& chainman shareman{std::make_unique(connman, chainman.ActiveChainstate(), sigman, peerman, *nodeman, qman, sporkman)}, gov_signer{std::make_unique(connman, dmnman, govman, *nodeman, chainman, mn_sync)}, - ehf_sighandler{std::make_unique(chainman, mnhfman, sigman, *shareman, qman)}, + ehf_sighandler{std::make_unique(chainman, sigman, *shareman, qman)}, qman_handler{std::make_unique(bls_worker, connman, dmnman, qman, qsnapman, *nodeman, chainman, mn_sync, sporkman, sync_map, quorums_recovery, quorums_watch)}, cl_signer{std::make_unique(chainman.ActiveChainstate(), chainlocks, clhandler, isman, diff --git a/src/active/context.h b/src/active/context.h index 445a6d829f8a..378009e80c0e 100644 --- a/src/active/context.h +++ b/src/active/context.h @@ -63,13 +63,13 @@ struct ActiveContext final : public CValidationInterface { ActiveContext& operator=(const ActiveContext&) = delete; explicit ActiveContext(CBLSWorker& bls_worker, ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, CGovernanceManager& govman, CMasternodeMetaMan& mn_metaman, - CMNHFManager& mnhfman, CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks, - CTxMemPool& mempool, chainlock::ChainlockHandler& clhandler, - llmq::CInstantSendManager& isman, llmq::CQuorumBlockProcessor& qblockman, - llmq::CQuorumManager& qman, llmq::CQuorumSnapshotManager& qsnapman, - llmq::CSigningManager& sigman, PeerManager& peerman, const CMasternodeSync& mn_sync, - const CBLSSecretKey& operator_sk, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch); + CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks, CTxMemPool& mempool, + chainlock::ChainlockHandler& clhandler, llmq::CInstantSendManager& isman, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumManager& qman, + llmq::CQuorumSnapshotManager& qsnapman, llmq::CSigningManager& sigman, PeerManager& peerman, + const CMasternodeSync& mn_sync, const CBLSSecretKey& operator_sk, + const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params, + bool quorums_recovery, bool quorums_watch); ~ActiveContext(); void Interrupt(); diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index d978e2492254..8da7aa49b771 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -7,21 +7,23 @@ #include #include +#include #include #include #include #include -CChainstateHelper::CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, - CMNHFManager& mnhfman, CGovernanceManager& govman, llmq::CInstantSendManager& isman, +CChainstateHelper::CChainstateHelper(CEvoDB& evodb, CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, + CGovernanceManager& govman, llmq::CInstantSendManager& isman, llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, const CMasternodeSync& mn_sync, const CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks, const llmq::CQuorumManager& qman) : isman{isman}, m_chainlocks{chainlocks}, + ehf_manager{std::make_unique(evodb, chainman)}, mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, - special_tx{std::make_unique(cpoolman, dmnman, mnhfman, qblockman, qsnapman, chainman, + special_tx{std::make_unique(cpoolman, dmnman, *ehf_manager, qblockman, qsnapman, chainman, consensus_params, chainlocks, qman)} {} diff --git a/src/evo/chainhelper.h b/src/evo/chainhelper.h index ab865f272a6a..4eaf1cfc1dad 100644 --- a/src/evo/chainhelper.h +++ b/src/evo/chainhelper.h @@ -10,6 +10,7 @@ class CCreditPoolManager; class CDeterministicMNManager; +class CEvoDB; class ChainstateManager; class CMNHFManager; class CMNPaymentsProcessor; @@ -43,7 +44,7 @@ class CChainstateHelper CChainstateHelper() = delete; CChainstateHelper(const CChainstateHelper&) = delete; CChainstateHelper& operator=(const CChainstateHelper&) = delete; - explicit CChainstateHelper(CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CMNHFManager& mnhfman, + explicit CChainstateHelper(CEvoDB& evodb, CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, CGovernanceManager& govman, llmq::CInstantSendManager& isman, llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, const Consensus::Params& consensus_params, @@ -63,6 +64,7 @@ class CChainstateHelper bool ShouldInstantSendRejectConflicts() const; public: + const std::unique_ptr ehf_manager; const std::unique_ptr mn_payments; const std::unique_ptr special_tx; }; diff --git a/src/init.cpp b/src/init.cpp index 5c9d37cdcb63..e50b97b3c346 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -89,7 +89,6 @@ #include #include #include -#include #include #include #include @@ -405,9 +404,8 @@ void PrepareShutdown(NodeContext& node) chainstate->ResetCoinsViews(); } } - DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.mnhf_manager, node.llmq_ctx, + DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.llmq_ctx, Assert(node.mempool.get())); - node.mnhf_manager.reset(); node.evodb.reset(); } for (const auto& client : node.chain_clients) { @@ -1999,7 +1997,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.cpoolman, node.dmnman, node.evodb, - node.mnhf_manager, node.llmq_ctx, Assert(node.mempool.get()), args.GetDataDirNet(), @@ -2201,7 +2198,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } // Will init later in ThreadImport node.active_ctx = std::make_unique(*node.llmq_ctx->bls_worker, chainman, *node.connman, *node.dmnman, *node.govman, *node.mn_metaman, - *node.mnhf_manager, *node.sporkman, *node.chainlocks, *node.mempool, *node.clhandler, *node.llmq_ctx->isman, + *node.sporkman, *node.chainlocks, *node.mempool, *node.clhandler, *node.llmq_ctx->isman, *node.llmq_ctx->quorum_block_processor, *node.llmq_ctx->qman, *node.llmq_ctx->qsnapman, *node.llmq_ctx->sigman, *node.peerman, *node.mn_sync, operator_sk, sync_map, dash_db_params, quorums_recovery, quorums_watch); RegisterValidationInterface(node.active_ctx.get()); diff --git a/src/llmq/ehf_signals.cpp b/src/llmq/ehf_signals.cpp index 804276b98452..9e6b1260d88b 100644 --- a/src/llmq/ehf_signals.cpp +++ b/src/llmq/ehf_signals.cpp @@ -7,20 +7,19 @@ #include #include #include -#include // g_txindex -#include -#include - #include +#include // g_txindex #include #include #include +#include +#include +#include namespace llmq { -CEHFSignalsHandler::CEHFSignalsHandler(ChainstateManager& chainman, CMNHFManager& mnhfman, CSigningManager& sigman, +CEHFSignalsHandler::CEHFSignalsHandler(ChainstateManager& chainman, CSigningManager& sigman, CSigSharesManager& shareman, const CQuorumManager& qman) : m_chainman(chainman), - mnhfman(mnhfman), sigman(sigman), shareman(shareman), qman(qman) @@ -37,7 +36,7 @@ void CEHFSignalsHandler::UpdatedBlockTip(const CBlockIndex* const pindexNew) { if (!DeploymentActiveAfter(pindexNew, Params().GetConsensus(), Consensus::DEPLOYMENT_V20)) return; - const auto ehfSignals = mnhfman.GetSignalsStage(pindexNew); + const auto ehfSignals = m_chainman.GetSignalsStage(pindexNew); for (const auto& deployment : Params().GetConsensus().vDeployments) { // Skip deployments that do not use dip0023 if (!deployment.useEHF) continue; @@ -93,7 +92,7 @@ MessageProcessingResult CEHFSignalsHandler::HandleNewRecoveredSig(const CRecover } MessageProcessingResult ret; - const auto ehfSignals = mnhfman.GetSignalsStage(WITH_LOCK(::cs_main, return m_chainman.ActiveTip())); + const auto ehfSignals = m_chainman.GetSignalsStage(WITH_LOCK(::cs_main, return m_chainman.ActiveTip())); MNHFTxPayload mnhfPayload; for (const auto& deployment : Params().GetConsensus().vDeployments) { // skip deployments that do not use dip0023 or that have already been mined diff --git a/src/llmq/ehf_signals.h b/src/llmq/ehf_signals.h index 190d584c8b1e..7f6688fd4eb9 100644 --- a/src/llmq/ehf_signals.h +++ b/src/llmq/ehf_signals.h @@ -12,7 +12,6 @@ class CBlockIndex; class ChainstateManager; -class CMNHFManager; namespace llmq { class CQuorumManager; @@ -23,7 +22,6 @@ class CEHFSignalsHandler : public CRecoveredSigsListener { private: ChainstateManager& m_chainman; - CMNHFManager& mnhfman; CSigningManager& sigman; CSigSharesManager& shareman; const CQuorumManager& qman; @@ -34,8 +32,8 @@ class CEHFSignalsHandler : public CRecoveredSigsListener mutable Mutex cs; std::set ids GUARDED_BY(cs); public: - explicit CEHFSignalsHandler(ChainstateManager& chainman, CMNHFManager& mnhfman, CSigningManager& sigman, - CSigSharesManager& shareman, const CQuorumManager& qman); + explicit CEHFSignalsHandler(ChainstateManager& chainman, CSigningManager& sigman, CSigSharesManager& shareman, + const CQuorumManager& qman); ~CEHFSignalsHandler(); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index d34cfbddc77e..b93f2fbbca07 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -45,7 +45,6 @@ std::optional LoadChainstate(bool fReset, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, - std::unique_ptr& mnhf_manager, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, @@ -75,9 +74,6 @@ std::optional LoadChainstate(bool fReset, evodb.reset(); evodb = std::make_unique(util::DbWrapperParams{.path = data_dir, .memory = dash_dbs_in_memory, .wipe = fReset || fReindexChainState}); - mnhf_manager.reset(); - mnhf_manager = std::make_unique(*evodb, chainman); - chainman.InitializeChainstate(mempool, *evodb, chain_helper); chainman.m_total_coinstip_cache = nCoinCacheUsage; chainman.m_total_coinsdb_cache = nCoinDBCache; @@ -89,7 +85,7 @@ std::optional LoadChainstate(bool fReset, pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset)); DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, chainlocks, chain_helper, cpoolman, - dmnman, evodb, mnhf_manager, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, + dmnman, evodb, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, /*llmq_dbs_wipe=*/fReset || fReindexChainState, bls_threads, max_recsigs_age, consensus_params); if (fReset) { @@ -198,7 +194,7 @@ std::optional LoadChainstate(bool fReset, } } - if (!mnhf_manager->ForceSignalDBUpdate()) { + if (!chain_helper->ehf_manager->ForceSignalDBUpdate()) { return ChainstateLoadingError::ERROR_UPGRADING_SIGNALS_DB; } @@ -220,7 +216,6 @@ void DashChainstateSetup(ChainstateManager& chainman, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, - std::unique_ptr& mnhf_manager, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, @@ -242,27 +237,26 @@ void DashChainstateSetup(ChainstateManager& chainman, util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, bls_threads, max_recsigs_age); mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); - // Enable CMNHFManager::{Process, Undo}Block - mnhf_manager->ConnectManagers(llmq_ctx->qman.get()); - chain_helper.reset(); - chain_helper = std::make_unique(*cpoolman, *dmnman, *mnhf_manager, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), + chain_helper = std::make_unique(*evodb, *cpoolman, *dmnman, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), *(llmq_ctx->qsnapman), chainman, consensus_params, mn_sync, sporkman, chainlocks, *(llmq_ctx->qman)); + + // TODO: drop ConnectManagers completely from here + // qman should not be needed for Process/Undo block because validation & processing are 2 different stages + // Enable CMNHFManager::{Process, Undo}Block + chain_helper->ehf_manager->ConnectManagers(llmq_ctx->qman.get()); + } void DashChainstateSetupClose(std::unique_ptr& chain_helper, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, - std::unique_ptr& mnhf_manager, std::unique_ptr& llmq_ctx, CTxMemPool* mempool) { chain_helper.reset(); - if (mnhf_manager) { - mnhf_manager->DisconnectManagers(); - } llmq_ctx.reset(); cpoolman.reset(); mempool->DisconnectManagers(); diff --git a/src/node/chainstate.h b/src/node/chainstate.h index f3bf3eb3a150..888951710753 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -19,7 +19,6 @@ class CGovernanceManager; class ChainstateManager; class CMasternodeMetaMan; class CMasternodeSync; -class CMNHFManager; class CSporkManager; class CTxMemPool; struct LLMQContext; @@ -89,7 +88,6 @@ std::optional LoadChainstate(bool fReset, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, - std::unique_ptr& mnhf_manager, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, @@ -121,7 +119,6 @@ void DashChainstateSetup(ChainstateManager& chainman, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, - std::unique_ptr& mnhf_manager, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, @@ -134,7 +131,6 @@ void DashChainstateSetup(ChainstateManager& chainman, void DashChainstateSetupClose(std::unique_ptr& chain_helper, std::unique_ptr& cpoolman, std::unique_ptr& dmnman, - std::unique_ptr& mnhf_manager, std::unique_ptr& llmq_ctx, CTxMemPool* mempool); diff --git a/src/node/context.h b/src/node/context.h index ba3c1ae0063b..44049555b885 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -30,7 +30,6 @@ class CNetFulfilledRequestManager; class CScheduler; class CSporkManager; class CTxMemPool; -class CMNHFManager; class NetGroupManager; class PeerManager; struct ActiveContext; @@ -97,7 +96,6 @@ struct NodeContext { std::unique_ptr govman; std::unique_ptr mn_metaman; std::unique_ptr mn_sync; - std::unique_ptr mnhf_manager; std::unique_ptr netfulfilledman; std::unique_ptr sporkman; std::unique_ptr chainlocks; diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 429db2d84743..ff4afb9f807f 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -30,8 +30,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -76,7 +76,6 @@ BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, m_chain_helper(chainstate.ChainHelper()), m_chainstate(chainstate), m_evoDb(*Assert(node.evodb)), - m_mnhfman(*Assert(node.mnhf_manager)), m_chainlocks(*Assert(node.chainlocks)), m_clhandler(*Assert(node.clhandler)), m_isman(*Assert(Assert(node.llmq_ctx)->isman)), @@ -475,7 +474,7 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele } // This map with signals is used only to find duplicates - std::unordered_map signals = m_mnhfman.GetSignalsStage(pindexPrev); + std::unordered_map signals = m_chain_helper.ehf_manager->GetSignalsStage(pindexPrev); // mapModifiedTx will store sorted packages after they are modified // because some of their txs are already in the block diff --git a/src/node/miner.h b/src/node/miner.h index 8b7f7e096177..50e35ae2deaa 100644 --- a/src/node/miner.h +++ b/src/node/miner.h @@ -25,7 +25,6 @@ class CChainstateHelper; class CConnman; class CCreditPoolManager; class CEvoDB; -class CMNHFManager; class CScript; struct LLMQContext; @@ -175,7 +174,6 @@ class BlockAssembler CChainstateHelper& m_chain_helper; CChainState& m_chainstate; CEvoDB& m_evoDb; - CMNHFManager& m_mnhfman; const chainlock::Chainlocks& m_chainlocks; chainlock::ChainlockHandler& m_clhandler; llmq::CInstantSendManager& m_isman; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index ab74d75431b9..f5517222f1ce 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1550,7 +1550,7 @@ RPCHelpMan getblockchaininfo() const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())}; const int height{tip.nHeight}; - const auto ehfSignals{CHECK_NONFATAL(node.mnhf_manager)->GetSignalsStage(&tip)}; + const auto ehfSignals{chainman.GetSignalsStage(&tip)}; UniValue obj(UniValue::VOBJ); if (args.IsArgSet("-devnet")) { diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 2d98de87a1bd..d2344042e0ee 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -146,14 +145,14 @@ void DashChainstateSetup(ChainstateManager& chainman, const Consensus::Params& consensus_params) { DashChainstateSetup(chainman, *Assert(node.govman.get()), *Assert(node.mn_metaman.get()), *Assert(node.mn_sync.get()), - *Assert(node.sporkman.get()), *Assert(node.chainlocks), node.chain_helper, node.cpoolman, node.dmnman, node.evodb, node.mnhf_manager, + *Assert(node.sporkman.get()), *Assert(node.chainlocks), node.chain_helper, node.cpoolman, node.dmnman, node.evodb, node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), llmq_dbs_in_memory, llmq_dbs_wipe, llmq::DEFAULT_BLSCHECK_THREADS, llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE, consensus_params); } void DashChainstateSetupClose(NodeContext& node) { - DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.mnhf_manager, node.llmq_ctx, + DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.llmq_ctx, Assert(node.mempool.get())); } @@ -287,7 +286,6 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve m_node.chainman = std::make_unique(chainparams); m_node.chainman->m_blockman.m_block_tree_db = std::make_unique(m_cache_sizes.block_tree_db, true); - m_node.mnhf_manager = std::make_unique(*m_node.evodb, *m_node.chainman); m_node.mn_sync = std::make_unique(std::make_unique(*m_node.connman, *m_node.netfulfilledman)); m_node.govman = std::make_unique(*m_node.mn_metaman, *m_node.chainman, m_node.dmnman, *m_node.mn_sync); @@ -307,7 +305,6 @@ ChainTestingSetup::~ChainTestingSetup() GetMainSignals().UnregisterBackgroundSignalScheduler(); m_node.govman.reset(); m_node.mn_sync.reset(); - m_node.mnhf_manager.reset(); m_node.chainman.reset(); m_node.mempool.reset(); m_node.fee_estimator.reset(); @@ -333,7 +330,6 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vectorGetDataDirNet(), diff --git a/src/validation.cpp b/src/validation.cpp index f13113ba36dc..846ded93bdf3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -6066,6 +6067,11 @@ bool ChainstateManager::IsQuorumTypeEnabled(const Consensus::LLMQType llmqType, assert(false); } +std::unordered_map ChainstateManager::GetSignalsStage(const CBlockIndex* const pindexPrev) +{ + return m_active_chainstate->ChainHelper().ehf_manager->GetSignalsStage(pindexPrev); +} + void ChainstateManager::MaybeRebalanceCaches() { AssertLockHeld(::cs_main); diff --git a/src/validation.h b/src/validation.h index 56bedba032ab..dc3f4785b2d3 100644 --- a/src/validation.h +++ b/src/validation.h @@ -1080,6 +1080,9 @@ class ChainstateManager std::optional optDIP0024IsActive = std::nullopt, std::optional optHaveDIP0024Quorums = std::nullopt) const; + // TODO: move it inside ActiveChainstate (active_chainsate is CChainState) + std::unordered_map GetSignalsStage(const CBlockIndex* const pindexPrev); + ~ChainstateManager(); }; From 24ee98efedcb7be52306fb24d7529199a84cc2c1 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 14 Jan 2026 01:39:06 +0700 Subject: [PATCH 3/9] refactor: re-connect ehf manager to fix new circular dependencies --- src/evo/chainhelper.cpp | 4 ++++ src/evo/chainhelper.h | 4 ++++ src/llmq/ehf_signals.cpp | 6 ++++-- src/rpc/blockchain.cpp | 3 ++- src/validation.cpp | 6 ------ src/validation.h | 3 --- test/lint/lint-circular-dependencies.py | 2 +- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index 8da7aa49b771..31fa3f556482 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -63,3 +63,7 @@ bool CChainstateHelper::RemoveConflictingISLockByTx(const CTransaction& tx) bool CChainstateHelper::ShouldInstantSendRejectConflicts() const { return isman.RejectConflictingBlocks(); } +std::unordered_map CChainstateHelper::GetSignalsStage(const CBlockIndex* const pindexPrev) +{ + return ehf_manager->GetSignalsStage(pindexPrev); +} diff --git a/src/evo/chainhelper.h b/src/evo/chainhelper.h index 4eaf1cfc1dad..526834a18e36 100644 --- a/src/evo/chainhelper.h +++ b/src/evo/chainhelper.h @@ -7,7 +7,9 @@ #include #include +#include +class CBlockIndex; class CCreditPoolManager; class CDeterministicMNManager; class CEvoDB; @@ -63,6 +65,8 @@ class CChainstateHelper bool RemoveConflictingISLockByTx(const CTransaction& tx); bool ShouldInstantSendRejectConflicts() const; + std::unordered_map GetSignalsStage(const CBlockIndex* const pindexPrev); + public: const std::unique_ptr ehf_manager; const std::unique_ptr mn_payments; diff --git a/src/llmq/ehf_signals.cpp b/src/llmq/ehf_signals.cpp index 9e6b1260d88b..4dc31566e0bd 100644 --- a/src/llmq/ehf_signals.cpp +++ b/src/llmq/ehf_signals.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include // g_txindex #include @@ -36,7 +37,7 @@ void CEHFSignalsHandler::UpdatedBlockTip(const CBlockIndex* const pindexNew) { if (!DeploymentActiveAfter(pindexNew, Params().GetConsensus(), Consensus::DEPLOYMENT_V20)) return; - const auto ehfSignals = m_chainman.GetSignalsStage(pindexNew); + const auto ehfSignals = m_chainman.ActiveChainstate().ChainHelper().ehf_manager->GetSignalsStage(pindexNew); for (const auto& deployment : Params().GetConsensus().vDeployments) { // Skip deployments that do not use dip0023 if (!deployment.useEHF) continue; @@ -92,7 +93,8 @@ MessageProcessingResult CEHFSignalsHandler::HandleNewRecoveredSig(const CRecover } MessageProcessingResult ret; - const auto ehfSignals = m_chainman.GetSignalsStage(WITH_LOCK(::cs_main, return m_chainman.ActiveTip())); + const auto ehfSignals = m_chainman.ActiveChainstate().ChainHelper().ehf_manager->GetSignalsStage( + WITH_LOCK(::cs_main, return m_chainman.ActiveTip())); MNHFTxPayload mnhfPayload; for (const auto& deployment : Params().GetConsensus().vDeployments) { // skip deployments that do not use dip0023 or that have already been mined diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f5517222f1ce..1728c067629e 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -1550,7 +1551,7 @@ RPCHelpMan getblockchaininfo() const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())}; const int height{tip.nHeight}; - const auto ehfSignals{chainman.GetSignalsStage(&tip)}; + const auto ehfSignals{active_chainstate.ChainHelper().GetSignalsStage(&tip)}; UniValue obj(UniValue::VOBJ); if (args.IsArgSet("-devnet")) { diff --git a/src/validation.cpp b/src/validation.cpp index 846ded93bdf3..f13113ba36dc 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include @@ -6067,11 +6066,6 @@ bool ChainstateManager::IsQuorumTypeEnabled(const Consensus::LLMQType llmqType, assert(false); } -std::unordered_map ChainstateManager::GetSignalsStage(const CBlockIndex* const pindexPrev) -{ - return m_active_chainstate->ChainHelper().ehf_manager->GetSignalsStage(pindexPrev); -} - void ChainstateManager::MaybeRebalanceCaches() { AssertLockHeld(::cs_main); diff --git a/src/validation.h b/src/validation.h index dc3f4785b2d3..56bedba032ab 100644 --- a/src/validation.h +++ b/src/validation.h @@ -1080,9 +1080,6 @@ class ChainstateManager std::optional optDIP0024IsActive = std::nullopt, std::optional optHaveDIP0024Quorums = std::nullopt) const; - // TODO: move it inside ActiveChainstate (active_chainsate is CChainState) - std::unordered_map GetSignalsStage(const CBlockIndex* const pindexPrev); - ~ChainstateManager(); }; diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py index e159d5ac7fb7..062824fe8d33 100755 --- a/test/lint/lint-circular-dependencies.py +++ b/test/lint/lint-circular-dependencies.py @@ -34,7 +34,7 @@ "consensus/tx_verify -> evo/assetlocktx -> llmq/commitment -> validation -> consensus/tx_verify", "consensus/tx_verify -> evo/assetlocktx -> llmq/commitment -> validation -> txmempool -> consensus/tx_verify", "evo/assetlocktx -> llmq/commitment -> validation -> txmempool -> evo/assetlocktx", - "evo/chainhelper -> evo/specialtxman -> validation -> evo/chainhelper", + "evo/chainhelper -> evo/mnhftx -> validation -> evo/chainhelper", "evo/deterministicmns -> validation -> evo/deterministicmns", "evo/deterministicmns -> validation -> txmempool -> evo/deterministicmns", "evo/netinfo -> evo/providertx -> evo/netinfo", From 0bb7f5380127d1c3105a419a96281825dd471196 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 14 Jan 2026 01:59:22 +0700 Subject: [PATCH 4/9] refactor: drop atomic from evo/mnhftx --- src/evo/chainhelper.cpp | 2 +- src/evo/mnhftx.cpp | 25 +++++-------------------- src/evo/mnhftx.h | 26 ++------------------------ src/node/chainstate.cpp | 6 ------ 4 files changed, 8 insertions(+), 51 deletions(-) diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index 31fa3f556482..52ebb62e672d 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -21,7 +21,7 @@ CChainstateHelper::CChainstateHelper(CEvoDB& evodb, CCreditPoolManager& cpoolman const chainlock::Chainlocks& chainlocks, const llmq::CQuorumManager& qman) : isman{isman}, m_chainlocks{chainlocks}, - ehf_manager{std::make_unique(evodb, chainman)}, + ehf_manager{std::make_unique(evodb, chainman, qman)}, mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, special_tx{std::make_unique(cpoolman, dmnman, *ehf_manager, qblockman, qsnapman, chainman, consensus_params, chainlocks, qman)} diff --git a/src/evo/mnhftx.cpp b/src/evo/mnhftx.cpp index 728869a54392..d83fa4951dbf 100644 --- a/src/evo/mnhftx.cpp +++ b/src/evo/mnhftx.cpp @@ -43,9 +43,10 @@ CMutableTransaction MNHFTxPayload::PrepareTx() const return tx; } -CMNHFManager::CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman) : +CMNHFManager::CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman, const llmq::CQuorumManager& qman) : m_evoDb(evoDb), - m_chainman{chainman} + m_chainman{chainman}, + m_qman{qman} { assert(globalInstance == nullptr); globalInstance = this; @@ -202,11 +203,9 @@ static bool extractSignals(const ChainstateManager& chainman, const llmq::CQuoru std::optional CMNHFManager::ProcessBlock(const CBlock& block, const CBlockIndex* const pindex, bool fJustCheck, BlockValidationState& state) { - auto qman = Assert(m_qman.load(std::memory_order_acquire)); - try { std::vector new_signals; - if (!extractSignals(m_chainman, *qman, block, pindex, new_signals, state)) { + if (!extractSignals(m_chainman, m_qman, block, pindex, new_signals, state)) { // state is set inside extractSignals return std::nullopt; } @@ -253,11 +252,9 @@ std::optional CMNHFManager::ProcessBlock(const CBlock& bl bool CMNHFManager::UndoBlock(const CBlock& block, const CBlockIndex* const pindex) { - auto qman = Assert(m_qman.load(std::memory_order_acquire)); - std::vector excluded_signals; BlockValidationState state; - if (!extractSignals(m_chainman, *qman, block, pindex, excluded_signals, state)) { + if (!extractSignals(m_chainman, m_qman, block, pindex, excluded_signals, state)) { LogPrintf("CMNHFManager::%s: failed to extract signals\n", __func__); return false; } @@ -370,18 +367,6 @@ void CMNHFManager::AddSignal(const CBlockIndex* const pindex, int bit) AddToCache(signals, pindex); } -void CMNHFManager::ConnectManagers(gsl::not_null qman) -{ - // Do not allow double-initialization - assert(m_qman.load(std::memory_order_acquire) == nullptr); - m_qman.store(qman, std::memory_order_release); -} - -void CMNHFManager::DisconnectManagers() -{ - m_qman.store(nullptr, std::memory_order_release); -} - bool CMNHFManager::ForceSignalDBUpdate() { // force ehf signals db update diff --git a/src/evo/mnhftx.h b/src/evo/mnhftx.h index 9dd68db4b110..4bf17a633a96 100644 --- a/src/evo/mnhftx.h +++ b/src/evo/mnhftx.h @@ -16,7 +16,6 @@ #include #include -#include #include class BlockValidationState; @@ -91,7 +90,7 @@ class CMNHFManager : public AbstractEHFManager private: CEvoDB& m_evoDb; const ChainstateManager& m_chainman; - std::atomic m_qman{nullptr}; + const llmq::CQuorumManager& m_qman; static constexpr size_t MNHFCacheSize = 1000; Mutex cs_cache; @@ -102,15 +101,12 @@ class CMNHFManager : public AbstractEHFManager CMNHFManager() = delete; CMNHFManager(const CMNHFManager&) = delete; CMNHFManager& operator=(const CMNHFManager&) = delete; - explicit CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman); + explicit CMNHFManager(CEvoDB& evoDb, const ChainstateManager& chainman, const llmq::CQuorumManager& qman); ~CMNHFManager(); /** * Every new block should be processed when Tip() is updated by calling of CMNHFManager::ProcessBlock. * This function actually does only validate EHF transaction for this block and update internal caches/evodb state - * - * @pre Caller must ensure that LLMQContext has been initialized and the llmq::CQuorumManager pointer has been - * set by calling ConnectManagers() for this CMNHFManager instance */ std::optional ProcessBlock(const CBlock& block, const CBlockIndex* const pindex, bool fJustCheck, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(!cs_cache); @@ -119,9 +115,6 @@ class CMNHFManager : public AbstractEHFManager * Every undo block should be processed when Tip() is updated by calling of CMNHFManager::UndoBlock * This function actually does nothing at the moment, because status of ancestor block is already known. * Although it should be still called to do some sanity checks - * - * @pre Caller must ensure that LLMQContext has been initialized and the llmq::CQuorumManager pointer has been - * set by calling ConnectManagers() for this CMNHFManager instance */ bool UndoBlock(const CBlock& block, const CBlockIndex* const pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs_cache); @@ -133,21 +126,6 @@ class CMNHFManager : public AbstractEHFManager */ void AddSignal(const CBlockIndex* const pindex, int bit) EXCLUSIVE_LOCKS_REQUIRED(!cs_cache); - /** - * Set llmq::CQuorumManager pointer. - * - * Separated from constructor to allow LLMQContext to use CMNHFManager in read-only capacity. - * Required to mutate state. - */ - void ConnectManagers(gsl::not_null qman); - - /** - * Reset llmq::CQuorumManager pointer. - * - * @pre Must be called before LLMQContext (containing llmq::CQuorumManager) is destroyed. - */ - void DisconnectManagers(); - bool ForceSignalDBUpdate() EXCLUSIVE_LOCKS_REQUIRED(::cs_main, !cs_cache); private: diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index b93f2fbbca07..e1f8b3263553 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -241,12 +241,6 @@ void DashChainstateSetup(ChainstateManager& chainman, chain_helper = std::make_unique(*evodb, *cpoolman, *dmnman, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), *(llmq_ctx->qsnapman), chainman, consensus_params, mn_sync, sporkman, chainlocks, *(llmq_ctx->qman)); - - // TODO: drop ConnectManagers completely from here - // qman should not be needed for Process/Undo block because validation & processing are 2 different stages - // Enable CMNHFManager::{Process, Undo}Block - chain_helper->ehf_manager->ConnectManagers(llmq_ctx->qman.get()); - } void DashChainstateSetupClose(std::unique_ptr& chain_helper, From 97095880109e819256678026b74c1765572c1aba Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 14 Jan 2026 02:30:56 +0700 Subject: [PATCH 5/9] refactor: move CCreditPool inside chain-state helper --- src/evo/chainhelper.cpp | 18 ++++++++++-------- src/evo/chainhelper.h | 13 +++++++------ src/init.cpp | 3 +-- src/node/chainstate.cpp | 12 ++---------- src/node/chainstate.h | 4 ---- src/node/context.h | 2 -- src/node/miner.cpp | 5 ++--- src/node/miner.h | 2 -- src/rpc/rawtransaction.cpp | 9 +++++---- src/test/util/setup_common.cpp | 6 ++---- test/lint/lint-circular-dependencies.py | 2 +- 11 files changed, 30 insertions(+), 46 deletions(-) diff --git a/src/evo/chainhelper.cpp b/src/evo/chainhelper.cpp index 52ebb62e672d..511d08549587 100644 --- a/src/evo/chainhelper.cpp +++ b/src/evo/chainhelper.cpp @@ -7,24 +7,26 @@ #include #include +#include #include #include #include #include #include -CChainstateHelper::CChainstateHelper(CEvoDB& evodb, CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, - CGovernanceManager& govman, llmq::CInstantSendManager& isman, - llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, - const ChainstateManager& chainman, const Consensus::Params& consensus_params, - const CMasternodeSync& mn_sync, const CSporkManager& sporkman, - const chainlock::Chainlocks& chainlocks, const llmq::CQuorumManager& qman) : +CChainstateHelper::CChainstateHelper(CEvoDB& evodb, CDeterministicMNManager& dmnman, CGovernanceManager& govman, + llmq::CInstantSendManager& isman, llmq::CQuorumBlockProcessor& qblockman, + llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, + const Consensus::Params& consensus_params, const CMasternodeSync& mn_sync, + const CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks, + const llmq::CQuorumManager& qman) : isman{isman}, m_chainlocks{chainlocks}, ehf_manager{std::make_unique(evodb, chainman, qman)}, + credit_pool_manager{std::make_unique(evodb, chainman)}, mn_payments{std::make_unique(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)}, - special_tx{std::make_unique(cpoolman, dmnman, *ehf_manager, qblockman, qsnapman, chainman, - consensus_params, chainlocks, qman)} + special_tx{std::make_unique(*credit_pool_manager, dmnman, *ehf_manager, qblockman, qsnapman, + chainman, consensus_params, chainlocks, qman)} {} CChainstateHelper::~CChainstateHelper() = default; diff --git a/src/evo/chainhelper.h b/src/evo/chainhelper.h index 526834a18e36..5b5478d077a7 100644 --- a/src/evo/chainhelper.h +++ b/src/evo/chainhelper.h @@ -46,12 +46,12 @@ class CChainstateHelper CChainstateHelper() = delete; CChainstateHelper(const CChainstateHelper&) = delete; CChainstateHelper& operator=(const CChainstateHelper&) = delete; - explicit CChainstateHelper(CEvoDB& evodb, CCreditPoolManager& cpoolman, CDeterministicMNManager& dmnman, - CGovernanceManager& govman, llmq::CInstantSendManager& isman, - llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumSnapshotManager& qsnapman, - const ChainstateManager& chainman, const Consensus::Params& consensus_params, - const CMasternodeSync& mn_sync, const CSporkManager& sporkman, - const chainlock::Chainlocks& chainlocks, const llmq::CQuorumManager& qman); + explicit CChainstateHelper(CEvoDB& evodb, CDeterministicMNManager& dmnman, CGovernanceManager& govman, + llmq::CInstantSendManager& isman, llmq::CQuorumBlockProcessor& qblockman, + llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, + const Consensus::Params& consensus_params, const CMasternodeSync& mn_sync, + const CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks, + const llmq::CQuorumManager& qman); ~CChainstateHelper(); /** Passthrough functions to chainlock::Chainlocks*/ @@ -69,6 +69,7 @@ class CChainstateHelper public: const std::unique_ptr ehf_manager; + const std::unique_ptr credit_pool_manager; const std::unique_ptr mn_payments; const std::unique_ptr special_tx; }; diff --git a/src/init.cpp b/src/init.cpp index e50b97b3c346..65eced4e0e87 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -404,7 +404,7 @@ void PrepareShutdown(NodeContext& node) chainstate->ResetCoinsViews(); } } - DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.llmq_ctx, + DashChainstateSetupClose(node.chain_helper, node.dmnman, node.llmq_ctx, Assert(node.mempool.get())); node.evodb.reset(); } @@ -1994,7 +1994,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) *node.sporkman, *node.chainlocks, node.chain_helper, - node.cpoolman, node.dmnman, node.evodb, node.llmq_ctx, diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index e1f8b3263553..ea747ab9d28c 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -42,7 +41,6 @@ std::optional LoadChainstate(bool fReset, CSporkManager& sporkman, chainlock::Chainlocks& chainlocks, std::unique_ptr& chain_helper, - std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& llmq_ctx, @@ -84,7 +82,7 @@ std::optional LoadChainstate(bool fReset, pblocktree.reset(); pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset)); - DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, chainlocks, chain_helper, cpoolman, + DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, chainlocks, chain_helper, dmnman, evodb, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, /*llmq_dbs_wipe=*/fReset || fReindexChainState, bls_threads, max_recsigs_age, consensus_params); @@ -213,7 +211,6 @@ void DashChainstateSetup(ChainstateManager& chainman, CSporkManager& sporkman, chainlock::Chainlocks& chainlocks, std::unique_ptr& chain_helper, - std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& llmq_ctx, @@ -229,22 +226,18 @@ void DashChainstateSetup(ChainstateManager& chainman, dmnman.reset(); dmnman = std::make_unique(*evodb, mn_metaman); - cpoolman.reset(); - cpoolman = std::make_unique(*evodb, chainman); - llmq_ctx.reset(); llmq_ctx = std::make_unique(*dmnman, *evodb, sporkman, chainlocks, *mempool, chainman, mn_sync, util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, bls_threads, max_recsigs_age); mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); chain_helper.reset(); - chain_helper = std::make_unique(*evodb, *cpoolman, *dmnman, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), + chain_helper = std::make_unique(*evodb, *dmnman, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), *(llmq_ctx->qsnapman), chainman, consensus_params, mn_sync, sporkman, chainlocks, *(llmq_ctx->qman)); } void DashChainstateSetupClose(std::unique_ptr& chain_helper, - std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool) @@ -252,7 +245,6 @@ void DashChainstateSetupClose(std::unique_ptr& chain_helper, { chain_helper.reset(); llmq_ctx.reset(); - cpoolman.reset(); mempool->DisconnectManagers(); dmnman.reset(); } diff --git a/src/node/chainstate.h b/src/node/chainstate.h index 888951710753..d04fc82c224c 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -12,7 +12,6 @@ #include class CChainstateHelper; -class CCreditPoolManager; class CDeterministicMNManager; class CEvoDB; class CGovernanceManager; @@ -85,7 +84,6 @@ std::optional LoadChainstate(bool fReset, CSporkManager& sporkman, chainlock::Chainlocks& chainlocks, std::unique_ptr& chain_helper, - std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& llmq_ctx, @@ -116,7 +114,6 @@ void DashChainstateSetup(ChainstateManager& chainman, CSporkManager& sporkman, chainlock::Chainlocks& chainlocks, std::unique_ptr& chain_helper, - std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& evodb, std::unique_ptr& llmq_ctx, @@ -129,7 +126,6 @@ void DashChainstateSetup(ChainstateManager& chainman, const Consensus::Params& consensus_params); void DashChainstateSetupClose(std::unique_ptr& chain_helper, - std::unique_ptr& cpoolman, std::unique_ptr& dmnman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool); diff --git a/src/node/context.h b/src/node/context.h index 44049555b885..1d579276bd77 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -16,7 +16,6 @@ class CActiveMasternodeManager; class AddrMan; class CBlockPolicyEstimator; class CConnman; -class CCreditPoolManager; class CDeterministicMNManager; class CDSTXManager; class CChainstateHelper; @@ -87,7 +86,6 @@ struct NodeContext { std::unique_ptr scheduler; std::function rpc_interruption_point = [] {}; //! Dash managers - std::unique_ptr cpoolman; std::unique_ptr cj_walletman; std::unique_ptr dstxman; std::unique_ptr evodb; diff --git a/src/node/miner.cpp b/src/node/miner.cpp index ff4afb9f807f..e5ee48a78293 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -72,7 +72,6 @@ BlockAssembler::Options::Options() BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, const CTxMemPool* mempool, const CChainParams& params, const Options& options) : m_blockman(chainstate.m_blockman), - m_cpoolman(*Assert(node.cpoolman)), m_chain_helper(chainstate.ChainHelper()), m_chainstate(chainstate), m_evoDb(*Assert(node.evodb)), @@ -307,7 +306,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc LogPrintf("CreateNewBlock() h[%d] CbTx failed to find best CL. Inserting null CL\n", nHeight); } BlockValidationState state; - const auto creditPoolDiff = GetCreditPoolDiffForBlock(m_cpoolman, m_blockman, m_qman, *pblock, pindexPrev, chainparams.GetConsensus(), blockSubsidy, state); + const auto creditPoolDiff = GetCreditPoolDiffForBlock(*m_chain_helper.credit_pool_manager, m_blockman, m_qman, *pblock, pindexPrev, chainparams.GetConsensus(), blockSubsidy, state); if (creditPoolDiff == std::nullopt) { throw std::runtime_error(strprintf("%s: GetCreditPoolDiffForBlock failed: %s", __func__, state.ToString())); } @@ -469,7 +468,7 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele // duplicates of indexes. There's used `BlockSubsidy` equaled to 0 std::optional creditPoolDiff; if (DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_V20)) { - CCreditPool creditPool = m_cpoolman.GetCreditPool(pindexPrev); + CCreditPool creditPool = m_chain_helper.credit_pool_manager->GetCreditPool(pindexPrev); creditPoolDiff.emplace(std::move(creditPool), pindexPrev, chainparams.GetConsensus(), 0); } diff --git a/src/node/miner.h b/src/node/miner.h index 50e35ae2deaa..f16bb8ef5d94 100644 --- a/src/node/miner.h +++ b/src/node/miner.h @@ -23,7 +23,6 @@ class CBlockIndex; class CChainParams; class CChainstateHelper; class CConnman; -class CCreditPoolManager; class CEvoDB; class CScript; struct LLMQContext; @@ -170,7 +169,6 @@ class BlockAssembler int64_t m_lock_time_cutoff; BlockManager& m_blockman; - CCreditPoolManager& m_cpoolman; CChainstateHelper& m_chain_helper; CChainState& m_chainstate; CEvoDB& m_evoDb; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 554f4bd3d53e..9bf7462eafdd 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -639,7 +640,7 @@ static RPCHelpMan getassetunlockstatuses() const CTxMemPool& mempool = EnsureMemPool(node); CHECK_NONFATAL(node.chainlocks); const ChainstateManager& chainman = EnsureChainman(node); - + CCreditPoolManager& cpoolman = *chainman.ActiveChainstate().ChainHelper().credit_pool_manager; UniValue result_arr(UniValue::VARR); const UniValue str_indexes = request.params[0].get_array(); if (str_indexes.size() > 100) { @@ -665,7 +666,7 @@ static RPCHelpMan getassetunlockstatuses() if (nSpecificCoreHeight.value() < 0 || nSpecificCoreHeight.value() > chainman.ActiveChain().Height()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); } - poolCL = std::make_optional(CHECK_NONFATAL(node.cpoolman)->GetCreditPool(chainman.ActiveChain()[nSpecificCoreHeight.value()])); + poolCL = std::make_optional(cpoolman.GetCreditPool(chainman.ActiveChain()[nSpecificCoreHeight.value()])); } else { const auto pBlockIndexBestCL = [&]() -> const CBlockIndex* { @@ -684,12 +685,12 @@ static RPCHelpMan getassetunlockstatuses() // We need in 2 credit pools: at tip of chain and on best CL to know if tx is mined or chainlocked // Sometimes that's two different blocks, sometimes not and we need to initialize 2nd creditPoolManager poolCL = pBlockIndexBestCL ? - std::make_optional(node.cpoolman->GetCreditPool(pBlockIndexBestCL)) : + std::make_optional(cpoolman.GetCreditPool(pBlockIndexBestCL)) : std::nullopt; poolOnTip = [&]() -> std::optional { if (pTipBlockIndex != pBlockIndexBestCL) { - return std::make_optional(node.cpoolman->GetCreditPool(pTipBlockIndex)); + return std::make_optional(cpoolman.GetCreditPool(pTipBlockIndex)); } return std::nullopt; }(); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index d2344042e0ee..2c37b5b7ba56 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include @@ -145,14 +144,14 @@ void DashChainstateSetup(ChainstateManager& chainman, const Consensus::Params& consensus_params) { DashChainstateSetup(chainman, *Assert(node.govman.get()), *Assert(node.mn_metaman.get()), *Assert(node.mn_sync.get()), - *Assert(node.sporkman.get()), *Assert(node.chainlocks), node.chain_helper, node.cpoolman, node.dmnman, node.evodb, + *Assert(node.sporkman.get()), *Assert(node.chainlocks), node.chain_helper, node.dmnman, node.evodb, node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), llmq_dbs_in_memory, llmq_dbs_wipe, llmq::DEFAULT_BLSCHECK_THREADS, llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE, consensus_params); } void DashChainstateSetupClose(NodeContext& node) { - DashChainstateSetupClose(node.chain_helper, node.cpoolman, node.dmnman, node.llmq_ctx, + DashChainstateSetupClose(node.chain_helper, node.dmnman, node.llmq_ctx, Assert(node.mempool.get())); } @@ -327,7 +326,6 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector evo/assetlocktx -> llmq/commitment -> validation -> consensus/tx_verify", "consensus/tx_verify -> evo/assetlocktx -> llmq/commitment -> validation -> txmempool -> consensus/tx_verify", "evo/assetlocktx -> llmq/commitment -> validation -> txmempool -> evo/assetlocktx", - "evo/chainhelper -> evo/mnhftx -> validation -> evo/chainhelper", + "evo/chainhelper -> evo/creditpool -> validation -> evo/chainhelper", "evo/deterministicmns -> validation -> evo/deterministicmns", "evo/deterministicmns -> validation -> txmempool -> evo/deterministicmns", "evo/netinfo -> evo/providertx -> evo/netinfo", From e8692096b639a8c7ece41c3d893df2e585b3e6fe Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 14 Jan 2026 15:15:07 +0700 Subject: [PATCH 6/9] chore: add TODO to drop circular dependency of mnhftx and validation.h --- src/evo/mnhftx.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/evo/mnhftx.h b/src/evo/mnhftx.h index 4bf17a633a96..d9b1c8e90c5a 100644 --- a/src/evo/mnhftx.h +++ b/src/evo/mnhftx.h @@ -89,6 +89,11 @@ class CMNHFManager : public AbstractEHFManager { private: CEvoDB& m_evoDb; + // TODO: move its functionallity of ProcessBlock, UndoBlock to specialtxman; + // it will help to drop dependency on m_chainman, m_qman here (and validation.h) + // Secondly, store in database active EHF signals not for each block; + // but quite opposite: keep only hash of block where signal is added. + // TODO: implement migration to a new format const ChainstateManager& m_chainman; const llmq::CQuorumManager& m_qman; From ce1c7dee19dd2950356f4a8b7c158486753f82ba Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 14 Jan 2026 15:20:46 +0700 Subject: [PATCH 7/9] refactor: unwrap CEvoDB from unique_ptr when calling DashChainstateSetup --- src/node/chainstate.cpp | 10 +++++----- src/node/chainstate.h | 2 +- src/test/util/setup_common.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index ea747ab9d28c..aee964546334 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -83,7 +83,7 @@ std::optional LoadChainstate(bool fReset, pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset)); DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, chainlocks, chain_helper, - dmnman, evodb, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, + dmnman, *evodb, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, /*llmq_dbs_wipe=*/fReset || fReindexChainState, bls_threads, max_recsigs_age, consensus_params); if (fReset) { @@ -212,7 +212,7 @@ void DashChainstateSetup(ChainstateManager& chainman, chainlock::Chainlocks& chainlocks, std::unique_ptr& chain_helper, std::unique_ptr& dmnman, - std::unique_ptr& evodb, + CEvoDB& evodb, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, @@ -224,15 +224,15 @@ void DashChainstateSetup(ChainstateManager& chainman, { // Same logic as pblocktree dmnman.reset(); - dmnman = std::make_unique(*evodb, mn_metaman); + dmnman = std::make_unique(evodb, mn_metaman); llmq_ctx.reset(); - llmq_ctx = std::make_unique(*dmnman, *evodb, sporkman, chainlocks, *mempool, chainman, mn_sync, + llmq_ctx = std::make_unique(*dmnman, evodb, sporkman, chainlocks, *mempool, chainman, mn_sync, util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, bls_threads, max_recsigs_age); mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); chain_helper.reset(); - chain_helper = std::make_unique(*evodb, *dmnman, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), + chain_helper = std::make_unique(evodb, *dmnman, govman, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), *(llmq_ctx->qsnapman), chainman, consensus_params, mn_sync, sporkman, chainlocks, *(llmq_ctx->qman)); } diff --git a/src/node/chainstate.h b/src/node/chainstate.h index d04fc82c224c..66b78067cc1d 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -115,7 +115,7 @@ void DashChainstateSetup(ChainstateManager& chainman, chainlock::Chainlocks& chainlocks, std::unique_ptr& chain_helper, std::unique_ptr& dmnman, - std::unique_ptr& evodb, + CEvoDB& evodb, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 2c37b5b7ba56..3e8aba981831 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -144,7 +144,7 @@ void DashChainstateSetup(ChainstateManager& chainman, const Consensus::Params& consensus_params) { DashChainstateSetup(chainman, *Assert(node.govman.get()), *Assert(node.mn_metaman.get()), *Assert(node.mn_sync.get()), - *Assert(node.sporkman.get()), *Assert(node.chainlocks), node.chain_helper, node.dmnman, node.evodb, + *Assert(node.sporkman.get()), *Assert(node.chainlocks), node.chain_helper, node.dmnman, *node.evodb, node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), llmq_dbs_in_memory, llmq_dbs_wipe, llmq::DEFAULT_BLSCHECK_THREADS, llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE, consensus_params); } From 46302beeefe8fe441d5991adf5c329e19935b285 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 14 Jan 2026 15:40:38 +0700 Subject: [PATCH 8/9] refactor: code move only; validation of protx transactions are moved from detemrinisticmns to specialtxman --- src/evo/deterministicmns.cpp | 468 ----------------------- src/evo/deterministicmns.h | 14 - src/evo/specialtxman.cpp | 486 +++++++++++++++++++++++- src/evo/specialtxman.h | 12 + src/test/evo_deterministicmns_tests.cpp | 1 + test/lint/lint-circular-dependencies.py | 6 +- 6 files changed, 493 insertions(+), 494 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index aa97f67de072..ac89530dc6ee 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -24,7 +23,6 @@ #include #include