From 7f32d39df590e8dbc0a93e0945fb644cfecbe799 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Wed, 10 Dec 2025 11:37:25 +0530 Subject: [PATCH 01/12] refactor: drop `IsWatchQuorumsEnabled()` dash-chainstate may not have ArgsManager, we should try and resolve the expected value before moving to chainstate logic. --- src/init.cpp | 3 +++ src/llmq/context.cpp | 8 ++++---- src/llmq/context.h | 2 +- src/llmq/dkgsessionhandler.cpp | 5 +++-- src/llmq/dkgsessionhandler.h | 4 +++- src/llmq/dkgsessionmgr.cpp | 11 ++++++----- src/llmq/dkgsessionmgr.h | 3 ++- src/llmq/options.cpp | 6 ------ src/llmq/options.h | 3 --- src/llmq/quorums.cpp | 20 ++++++++++---------- src/llmq/quorums.h | 16 +++++++++++----- src/llmq/utils.cpp | 6 +++--- src/llmq/utils.h | 2 +- src/net_processing.cpp | 2 +- src/node/chainstate.cpp | 7 +++++-- src/node/chainstate.h | 2 ++ src/test/util/setup_common.cpp | 6 ++++-- 17 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 0008b0459a5a..dc895d47a551 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1956,6 +1956,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) fReindex = args.GetBoolArg("-reindex", false); bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false); + const bool quorums_watch = args.GetBoolArg("-watchquorums", llmq::DEFAULT_WATCH_QUORUMS); + // cache size calculations CacheSizes cache_sizes = CalculateCacheSizes(args, g_enabled_filter_types.size()); @@ -2030,6 +2032,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) /*block_tree_db_in_memory=*/false, /*coins_db_in_memory=*/false, /*dash_dbs_in_memory=*/false, + quorums_watch, /*shutdown_requested=*/ShutdownRequested, /*coins_error_cb=*/[]() { uiInterface.ThreadSafeMessageBox( diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index 2789b46e8aa7..577063b40c3e 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -18,7 +18,7 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params) : + const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_watch) : bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, qsnapman{std::make_unique(evo_db)}, @@ -26,9 +26,9 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db, *qsnapman)}, qdkgsman{std::make_unique(*bls_worker, dmnman, *dkg_debugman, mn_metaman, *quorum_block_processor, *qsnapman, mn_activeman, chainman, - sporkman, db_params)}, - qman{std::make_unique(*bls_worker, dmnman, *qdkgsman, evo_db, *quorum_block_processor, - *qsnapman, mn_activeman, chainman, mn_sync, sporkman, db_params)}, + sporkman, db_params, quorums_watch)}, + qman{std::make_unique(*bls_worker, dmnman, *qdkgsman, evo_db, *quorum_block_processor, *qsnapman, + mn_activeman, chainman, mn_sync, sporkman, db_params, quorums_watch)}, sigman{std::make_unique(*qman, db_params)}, clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, sporkman, mempool, mn_sync)}, isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *sigman, sporkman, diff --git a/src/llmq/context.h b/src/llmq/context.h index 42441e899e70..d2261dcfec5c 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -41,7 +41,7 @@ struct LLMQContext { explicit LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params); + const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_watch); ~LLMQContext(); void Interrupt(); diff --git a/src/llmq/dkgsessionhandler.cpp b/src/llmq/dkgsessionhandler.cpp index 0d7612036f2a..48ba7d2b7f73 100644 --- a/src/llmq/dkgsessionhandler.cpp +++ b/src/llmq/dkgsessionhandler.cpp @@ -29,7 +29,7 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CDeterministicMNM CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, const CSporkManager& sporkman, - const Consensus::LLMQParams& _params, int _quorumIndex) : + const Consensus::LLMQParams& _params, bool quorums_watch, int _quorumIndex) : blsWorker{_blsWorker}, m_dmnman{dmnman}, dkgDebugManager{_dkgDebugManager}, @@ -41,6 +41,7 @@ CDKGSessionHandler::CDKGSessionHandler(CBLSWorker& _blsWorker, CDeterministicMNM m_chainman{chainman}, m_sporkman{sporkman}, params{_params}, + m_quorums_watch{quorums_watch}, quorumIndex{_quorumIndex}, curSession{std::make_unique(nullptr, _params, _blsWorker, dmnman, _dkgManager, _dkgDebugManager, m_mn_metaman, m_qsnapman, m_mn_activeman, m_chainman, m_sporkman)}, @@ -566,7 +567,7 @@ void CDKGSessionHandler::HandleDKGRound(CConnman& connman, PeerManager& peerman) const auto tip_mn_list = m_dmnman.GetListAtChainTip(); utils::EnsureQuorumConnections(params, connman, m_dmnman, m_qsnapman, m_chainman, m_sporkman, tip_mn_list, pQuorumBaseBlockIndex, curSession->myProTxHash, - /* is_masternode = */ m_mn_activeman != nullptr); + /*is_masternode=*/m_mn_activeman != nullptr, m_quorums_watch); if (curSession->AreWeMember()) { utils::AddQuorumProbeConnections(params, connman, m_dmnman, m_mn_metaman, m_qsnapman, m_chainman, m_sporkman, tip_mn_list, pQuorumBaseBlockIndex, curSession->myProTxHash); diff --git a/src/llmq/dkgsessionhandler.h b/src/llmq/dkgsessionhandler.h index 98c3ddeef1e6..0a14642c4ea8 100644 --- a/src/llmq/dkgsessionhandler.h +++ b/src/llmq/dkgsessionhandler.h @@ -144,6 +144,7 @@ class CDKGSessionHandler const ChainstateManager& m_chainman; const CSporkManager& m_sporkman; const Consensus::LLMQParams params; + const bool m_quorums_watch{false}; const int quorumIndex; std::atomic currentHeight {-1}; @@ -166,7 +167,8 @@ class CDKGSessionHandler CDKGSessionManager& _dkgManager, CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, - const CSporkManager& sporkman, const Consensus::LLMQParams& _params, int _quorumIndex); + const CSporkManager& sporkman, const Consensus::LLMQParams& _params, bool quorums_watch, + int _quorumIndex); ~CDKGSessionHandler(); void UpdatedBlockTip(const CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(!cs_phase_qhash); diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index 998515cd5a48..2c70e1aa21f3 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -34,7 +34,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CDeterministicMNM CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, const CSporkManager& sporkman, - const util::DbWrapperParams& db_params) : + const util::DbWrapperParams& db_params, bool quorums_watch) : db{util::MakeDbWrapper({db_params.path / "llmq" / "dkgdb", db_params.memory, db_params.wipe, /*cache_size=*/1 << 20})}, blsWorker{_blsWorker}, m_dmnman{dmnman}, @@ -42,9 +42,10 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CDeterministicMNM quorumBlockProcessor{_quorumBlockProcessor}, m_qsnapman{qsnapman}, m_chainman{chainman}, - spork_manager{sporkman} + spork_manager{sporkman}, + m_quorums_watch{quorums_watch} { - if (mn_activeman == nullptr && !IsWatchQuorumsEnabled()) { + if (mn_activeman == nullptr && !m_quorums_watch) { // Regular nodes do not care about any DKG internals, bail out return; } @@ -56,7 +57,7 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CDeterministicMNM dkgSessionHandlers.emplace(std::piecewise_construct, std::forward_as_tuple(params.type, i), std::forward_as_tuple(blsWorker, m_dmnman, dkgDebugManager, *this, mn_metaman, quorumBlockProcessor, m_qsnapman, mn_activeman, m_chainman, - spork_manager, params, i)); + spork_manager, params, m_quorums_watch, i)); } } } @@ -119,7 +120,7 @@ MessageProcessingResult CDKGSessionManager::ProcessMessage(CNode& pfrom, bool is return {}; } - if ((!is_masternode && !IsWatchQuorumsEnabled())) { + if (!is_masternode && !m_quorums_watch) { // regular non-watching nodes should never receive any of these return MisbehavingError{10}; } diff --git a/src/llmq/dkgsessionmgr.h b/src/llmq/dkgsessionmgr.h index e82d9d3cd949..72f884c5285d 100644 --- a/src/llmq/dkgsessionmgr.h +++ b/src/llmq/dkgsessionmgr.h @@ -57,6 +57,7 @@ class CDKGSessionManager CQuorumSnapshotManager& m_qsnapman; const ChainstateManager& m_chainman; const CSporkManager& spork_manager; + const bool m_quorums_watch{false}; //TODO name struct instead of std::pair std::map, CDKGSessionHandler> dkgSessionHandlers; @@ -88,7 +89,7 @@ class CDKGSessionManager CDKGDebugManager& _dkgDebugManager, CMasternodeMetaMan& mn_metaman, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, - const CSporkManager& sporkman, const util::DbWrapperParams& db_params); + const CSporkManager& sporkman, const util::DbWrapperParams& db_params, bool quorums_watch); ~CDKGSessionManager(); void StartThreads(CConnman& connman, PeerManager& peerman); diff --git a/src/llmq/options.cpp b/src/llmq/options.cpp index 3ac8fdc489ec..f0fe01f93377 100644 --- a/src/llmq/options.cpp +++ b/src/llmq/options.cpp @@ -61,12 +61,6 @@ bool QuorumDataRecoveryEnabled() return gArgs.GetBoolArg("-llmq-data-recovery", DEFAULT_ENABLE_QUORUM_DATA_RECOVERY); } -bool IsWatchQuorumsEnabled() -{ - static bool fIsWatchQuroumsEnabled = gArgs.GetBoolArg("-watchquorums", DEFAULT_WATCH_QUORUMS); - return fIsWatchQuroumsEnabled; -} - std::map GetEnabledQuorumVvecSyncEntries() { std::map mapQuorumVvecSyncEntries; diff --git a/src/llmq/options.h b/src/llmq/options.h index 9e4e8604b5ff..44ea96b521cc 100644 --- a/src/llmq/options.h +++ b/src/llmq/options.h @@ -43,9 +43,6 @@ bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, gsl::not_n /// Returns the state of `-llmq-data-recovery` bool QuorumDataRecoveryEnabled(); -/// Returns the state of `-watchquorums` -bool IsWatchQuorumsEnabled(); - /// Returns the parsed entries given by `-llmq-qvvec-sync` std::map GetEnabledQuorumVvecSyncEntries(); diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 8fc8c1cbc8e3..61aa2982b791 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -211,9 +211,7 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, const util::DbWrapperParams& db_params) : - db{util::MakeDbWrapper( - {db_params.path / "llmq" / "quorumdb", db_params.memory, db_params.wipe, /*cache_size=*/1 << 20})}, + const CSporkManager& sporkman, const util::DbWrapperParams& db_params, bool quorums_watch) : blsWorker{_blsWorker}, m_dmnman{dmnman}, dkgManager{_dkgManager}, @@ -222,7 +220,9 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& m_mn_activeman{mn_activeman}, m_chainman{chainman}, m_mn_sync{mn_sync}, - m_sporkman{sporkman} + m_sporkman{sporkman}, + m_quorums_watch{quorums_watch}, + db{util::MakeDbWrapper({db_params.path / "llmq" / "quorumdb", db_params.memory, db_params.wipe, /*cache_size=*/1 << 20})} { utils::InitQuorumsCache(mapQuorumsCache, false); quorumThreadInterrupt.reset(); @@ -251,7 +251,7 @@ void CQuorumManager::Stop() void CQuorumManager::TriggerQuorumDataRecoveryThreads(CConnman& connman, const CBlockIndex* pIndex) const { - if ((m_mn_activeman == nullptr && !IsWatchQuorumsEnabled()) || !QuorumDataRecoveryEnabled() || pIndex == nullptr) { + if ((m_mn_activeman == nullptr && !m_quorums_watch) || !QuorumDataRecoveryEnabled() || pIndex == nullptr) { return; } @@ -309,7 +309,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, CConnman& con CheckQuorumConnections(connman, params, pindexNew); } - if (m_mn_activeman != nullptr || IsWatchQuorumsEnabled()) { + if (m_mn_activeman != nullptr || m_quorums_watch) { // Cleanup expired data requests LOCK(cs_data_requests); auto it = mapQuorumDataRequests.begin(); @@ -329,7 +329,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, CConnman& con void CQuorumManager::CheckQuorumConnections(CConnman& connman, const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const { - if (m_mn_activeman == nullptr && !IsWatchQuorumsEnabled()) return; + if (m_mn_activeman == nullptr && !m_quorums_watch) return; auto lastQuorums = ScanQuorums(llmqParams.type, pindexNew, (size_t)llmqParams.keepOldConnections); @@ -368,7 +368,7 @@ void CQuorumManager::CheckQuorumConnections(CConnman& connman, const Consensus:: for (const auto& quorum : lastQuorums) { if (utils::EnsureQuorumConnections(llmqParams, connman, m_dmnman, m_qsnapman, m_chainman, m_sporkman, m_dmnman.GetListAtChainTip(), quorum->m_quorum_base_block_index, myProTxHash, - /* is_masternode = */ m_mn_activeman != nullptr)) { + /*is_masternode=*/m_mn_activeman != nullptr, m_quorums_watch)) { if (connmanQuorumsToDelete.erase(quorum->qc->quorumHash) > 0) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- llmqType[%d] h[%d] keeping mn quorum connections for quorum: [%d:%s]\n", __func__, ToUnderlying(llmqParams.type), pindexNew->nHeight, quorum->m_quorum_base_block_index->nHeight, quorum->m_quorum_base_block_index->GetBlockHash().ToString()); } @@ -804,7 +804,7 @@ MessageProcessingResult CQuorumManager::ProcessMessage(CNode& pfrom, CConnman& c } if (msg_type == NetMsgType::QDATA) { - if ((m_mn_activeman == nullptr && !IsWatchQuorumsEnabled()) || pfrom.GetVerifiedProRegTxHash().IsNull()) { + if ((m_mn_activeman == nullptr && !m_quorums_watch) || pfrom.GetVerifiedProRegTxHash().IsNull()) { return errorHandler("Not a verified masternode and -watchquorums is not enabled"); } @@ -1095,7 +1095,7 @@ void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) // window and it's better to have more room so we pick next cycle. // dkgMiningWindowStart for small quorums is 10 i.e. a safe block to start // these calculations is at height 576 + 24 * 2 + 10 = 576 + 58. - if ((m_mn_activeman == nullptr && !IsWatchQuorumsEnabled()) || pIndex == nullptr || (pIndex->nHeight % 576 != 58)) { + if ((m_mn_activeman == nullptr && !m_quorums_watch) || pIndex == nullptr || (pIndex->nHeight % 576 != 58)) { return; } diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index c18540f767d9..3130ee341dd0 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -233,9 +233,6 @@ class CQuorum class CQuorumManager { private: - mutable Mutex cs_db; - std::unique_ptr db GUARDED_BY(cs_db){nullptr}; - CBLSWorker& blsWorker; CDeterministicMNManager& m_dmnman; CDKGSessionManager& dkgManager; @@ -245,18 +242,25 @@ class CQuorumManager const ChainstateManager& m_chainman; const CMasternodeSync& m_mn_sync; const CSporkManager& m_sporkman; + const bool m_quorums_watch{false}; + +private: + mutable Mutex cs_db; + std::unique_ptr db GUARDED_BY(cs_db){nullptr}; mutable Mutex cs_map_quorums; mutable std::map> mapQuorumsCache GUARDED_BY(cs_map_quorums); + mutable Mutex cs_scan_quorums; // TODO: merge cs_map_quorums, cs_scan_quorums mutexes mutable std::map>> scanQuorumsCache GUARDED_BY(cs_scan_quorums); + mutable Mutex cs_cleanup; mutable std::map> cleanupQuorumsCache GUARDED_BY(cs_cleanup); - mutable Mutex cs_quorumBaseBlockIndexCache; // On mainnet, we have around 62 quorums active at any point; let's cache a little more than double that to be safe. // it maps `quorum_hash` to `pindex` + mutable Mutex cs_quorumBaseBlockIndexCache; mutable Uint256LruHashMap quorumBaseBlockIndexCache; mutable ctpl::thread_pool workerPool; @@ -270,7 +274,7 @@ class CQuorumManager CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, const util::DbWrapperParams& db_params); + const CSporkManager& sporkman, const util::DbWrapperParams& db_params, bool quorums_watch); ~CQuorumManager(); void Start(); @@ -302,6 +306,8 @@ class CQuorumManager size_t nCountRequested) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db, !cs_map_quorums, !cs_scan_quorums); + bool IsWatching() const { return m_quorums_watch; } + private: // all private methods here are cs_main-free void CheckQuorumConnections(CConnman& connman, const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index d0449d5031da..405bc34e9c1b 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -838,9 +838,9 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash, - bool is_masternode) + bool is_masternode, bool quorums_watch) { - if (!is_masternode && !IsWatchQuorumsEnabled()) { + if (!is_masternode && !quorums_watch) { return false; } @@ -851,7 +851,7 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& bool isMember = ranges::find_if(members, [&](const auto& dmn) { return dmn->proTxHash == myProTxHash; }) != members.end(); - if (!isMember && !IsWatchQuorumsEnabled()) { + if (!isMember && !quorums_watch) { return false; } diff --git a/src/llmq/utils.h b/src/llmq/utils.h index d44714e2138d..75d773ca9066 100644 --- a/src/llmq/utils.h +++ b/src/llmq/utils.h @@ -59,7 +59,7 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman& CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, const CSporkManager& sporkman, const CDeterministicMNList& tip_mn_list, gsl::not_null pQuorumBaseBlockIndex, const uint256& myProTxHash, - bool is_masternode); + bool is_masternode, bool quorums_watch); void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman& connman, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 0f5a58e6be7b..4e30fa097950 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3999,7 +3999,7 @@ void PeerManagerImpl::ProcessMessage( m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDDSQUEUE, true)); // Tell our peer that he should send us intra-quorum messages const auto tip_mn_list = Assert(m_dmnman)->GetListAtChainTip(); - if (llmq::IsWatchQuorumsEnabled() && m_connman.IsMasternodeQuorumNode(&pfrom, tip_mn_list)) { + if (m_llmq_ctx->qman->IsWatching() && m_connman.IsMasternodeQuorumNode(&pfrom, tip_mn_list)) { m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::QWATCH)); } } diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index ba7be336acc9..1894d60080c1 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -61,6 +61,7 @@ std::optional LoadChainstate(bool fReset, bool block_tree_db_in_memory, bool coins_db_in_memory, bool dash_dbs_in_memory, + bool quorums_watch, std::function shutdown_requested, std::function coins_error_cb) { @@ -88,7 +89,7 @@ std::optional LoadChainstate(bool fReset, DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, mn_activeman, chain_helper, cpoolman, dmnman, evodb, mnhf_manager, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, - /*llmq_dbs_wipe=*/fReset || fReindexChainState, consensus_params); + /*llmq_dbs_wipe=*/fReset || fReindexChainState, quorums_watch, consensus_params); if (fReset) { pblocktree->WriteReindexing(true); @@ -224,6 +225,7 @@ void DashChainstateSetup(ChainstateManager& chainman, const fs::path& data_dir, bool llmq_dbs_in_memory, bool llmq_dbs_wipe, + bool quorums_watch, const Consensus::Params& consensus_params) { // Same logic as pblocktree @@ -240,7 +242,8 @@ void DashChainstateSetup(ChainstateManager& chainman, llmq_ctx.reset(); llmq_ctx = std::make_unique(chainman, *dmnman, *evodb, mn_metaman, *mnhf_manager, sporkman, *mempool, mn_activeman.get(), mn_sync, - util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}); + util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, + quorums_watch); mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); // Enable CMNHFManager::{Process, Undo}Block mnhf_manager->ConnectManagers(llmq_ctx->qman.get()); diff --git a/src/node/chainstate.h b/src/node/chainstate.h index c8d321b89931..6e1326b8879e 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -105,6 +105,7 @@ std::optional LoadChainstate(bool fReset, bool block_tree_db_in_memory, bool coins_db_in_memory, bool dash_dbs_in_memory, + bool quorums_watch, std::function shutdown_requested = nullptr, std::function coins_error_cb = nullptr); @@ -125,6 +126,7 @@ void DashChainstateSetup(ChainstateManager& chainman, const fs::path& data_dir, bool llmq_dbs_in_memory, bool llmq_dbs_wipe, + bool quorums_watch, const Consensus::Params& consensus_params); void DashChainstateSetupClose(std::unique_ptr& chain_helper, diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 62d308acb73c..3007ad99d3bf 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -134,7 +135,7 @@ void DashChainstateSetup(ChainstateManager& chainman, DashChainstateSetup(chainman, *Assert(node.govman.get()), *Assert(node.mn_metaman.get()), *Assert(node.mn_sync.get()), *Assert(node.sporkman.get()), node.mn_activeman, node.chain_helper, node.cpoolman, node.dmnman, node.evodb, node.mnhf_manager, node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), - llmq_dbs_in_memory, llmq_dbs_wipe, consensus_params); + llmq_dbs_in_memory, llmq_dbs_wipe, /*quorums_watch=*/false, consensus_params); } void DashChainstateSetupClose(NodeContext& node) @@ -331,7 +332,8 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector Date: Mon, 8 Dec 2025 23:12:37 +0530 Subject: [PATCH 02/12] refactor: drop `QuorumDataRecoveryEnabled()` Same rationale as previous commit. --- src/init.cpp | 5 +++-- src/llmq/context.cpp | 8 +++++--- src/llmq/context.h | 3 ++- src/llmq/options.cpp | 5 ----- src/llmq/options.h | 3 --- src/llmq/quorums.cpp | 6 ++++-- src/llmq/quorums.h | 9 +++++---- src/node/chainstate.cpp | 6 ++++-- src/node/chainstate.h | 2 ++ src/test/util/setup_common.cpp | 3 ++- 10 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index dc895d47a551..2646d8200cab 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1409,9 +1409,8 @@ bool AppInitParameterInteraction(const ArgsManager& args) } try { - const bool fRecoveryEnabled{llmq::QuorumDataRecoveryEnabled()}; const bool fQuorumVvecRequestsEnabled{llmq::GetEnabledQuorumVvecSyncEntries().size() > 0}; - if (!fRecoveryEnabled && fQuorumVvecRequestsEnabled) { + if (!args.GetBoolArg("-llmq-data-recovery", llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY) && fQuorumVvecRequestsEnabled) { InitWarning(Untranslated("-llmq-qvvec-sync set but recovery is disabled due to -llmq-data-recovery=0")); } } catch (const std::invalid_argument& e) { @@ -1956,6 +1955,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) fReindex = args.GetBoolArg("-reindex", false); bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false); + const bool quorums_recovery = args.GetBoolArg("-llmq-data-recovery", llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY); const bool quorums_watch = args.GetBoolArg("-watchquorums", llmq::DEFAULT_WATCH_QUORUMS); // cache size calculations @@ -2032,6 +2032,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) /*block_tree_db_in_memory=*/false, /*coins_db_in_memory=*/false, /*dash_dbs_in_memory=*/false, + quorums_recovery, quorums_watch, /*shutdown_requested=*/ShutdownRequested, /*coins_error_cb=*/[]() { diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index 577063b40c3e..bb936f617d30 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -18,7 +18,8 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_watch) : + const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_recovery, + bool quorums_watch) : bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, qsnapman{std::make_unique(evo_db)}, @@ -27,8 +28,9 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d qdkgsman{std::make_unique(*bls_worker, dmnman, *dkg_debugman, mn_metaman, *quorum_block_processor, *qsnapman, mn_activeman, chainman, sporkman, db_params, quorums_watch)}, - qman{std::make_unique(*bls_worker, dmnman, *qdkgsman, evo_db, *quorum_block_processor, *qsnapman, - mn_activeman, chainman, mn_sync, sporkman, db_params, quorums_watch)}, + qman{std::make_unique(*bls_worker, dmnman, *qdkgsman, evo_db, *quorum_block_processor, + *qsnapman, mn_activeman, chainman, mn_sync, sporkman, db_params, + quorums_recovery, quorums_watch)}, sigman{std::make_unique(*qman, db_params)}, clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, sporkman, mempool, mn_sync)}, isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *sigman, sporkman, diff --git a/src/llmq/context.h b/src/llmq/context.h index d2261dcfec5c..53adc5ec094b 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -41,7 +41,8 @@ struct LLMQContext { explicit LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_watch); + const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_recovery, + bool quorums_watch); ~LLMQContext(); void Interrupt(); diff --git a/src/llmq/options.cpp b/src/llmq/options.cpp index f0fe01f93377..b8a2550dfa17 100644 --- a/src/llmq/options.cpp +++ b/src/llmq/options.cpp @@ -56,11 +56,6 @@ bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, gsl::not_n return DeploymentActiveAfter(pindex->GetAncestor(cycleQuorumBaseHeight - 1), Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024); } -bool QuorumDataRecoveryEnabled() -{ - return gArgs.GetBoolArg("-llmq-data-recovery", DEFAULT_ENABLE_QUORUM_DATA_RECOVERY); -} - std::map GetEnabledQuorumVvecSyncEntries() { std::map mapQuorumVvecSyncEntries; diff --git a/src/llmq/options.h b/src/llmq/options.h index 44ea96b521cc..782727c60448 100644 --- a/src/llmq/options.h +++ b/src/llmq/options.h @@ -40,9 +40,6 @@ bool IsQuorumPoseEnabled(const Consensus::LLMQType llmqType, const CSporkManager bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, gsl::not_null pindex); -/// Returns the state of `-llmq-data-recovery` -bool QuorumDataRecoveryEnabled(); - /// Returns the parsed entries given by `-llmq-qvvec-sync` std::map GetEnabledQuorumVvecSyncEntries(); diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 61aa2982b791..8b6ca7075743 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -211,7 +211,8 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, const util::DbWrapperParams& db_params, bool quorums_watch) : + const CSporkManager& sporkman, const util::DbWrapperParams& db_params, + bool quorums_recovery, bool quorums_watch) : blsWorker{_blsWorker}, m_dmnman{dmnman}, dkgManager{_dkgManager}, @@ -221,6 +222,7 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& m_chainman{chainman}, m_mn_sync{mn_sync}, m_sporkman{sporkman}, + m_quorums_recovery{quorums_recovery}, m_quorums_watch{quorums_watch}, db{util::MakeDbWrapper({db_params.path / "llmq" / "quorumdb", db_params.memory, db_params.wipe, /*cache_size=*/1 << 20})} { @@ -251,7 +253,7 @@ void CQuorumManager::Stop() void CQuorumManager::TriggerQuorumDataRecoveryThreads(CConnman& connman, const CBlockIndex* pIndex) const { - if ((m_mn_activeman == nullptr && !m_quorums_watch) || !QuorumDataRecoveryEnabled() || pIndex == nullptr) { + if ((m_mn_activeman == nullptr && !m_quorums_watch) || !m_quorums_recovery || pIndex == nullptr) { return; } diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 3130ee341dd0..3f92a7102142 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -242,6 +242,7 @@ class CQuorumManager const ChainstateManager& m_chainman; const CMasternodeSync& m_mn_sync; const CSporkManager& m_sporkman; + const bool m_quorums_recovery{false}; const bool m_quorums_watch{false}; private: @@ -271,10 +272,10 @@ class CQuorumManager CQuorumManager(const CQuorumManager&) = delete; CQuorumManager& operator=(const CQuorumManager&) = delete; explicit CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, - CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, - CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, - const ChainstateManager& chainman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, const util::DbWrapperParams& db_params, bool quorums_watch); + CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, + const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch); ~CQuorumManager(); void Start(); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index 1894d60080c1..26a0b45f8db5 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -61,6 +61,7 @@ std::optional LoadChainstate(bool fReset, bool block_tree_db_in_memory, bool coins_db_in_memory, bool dash_dbs_in_memory, + bool quorums_recovery, bool quorums_watch, std::function shutdown_requested, std::function coins_error_cb) @@ -89,7 +90,7 @@ std::optional LoadChainstate(bool fReset, DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, mn_activeman, chain_helper, cpoolman, dmnman, evodb, mnhf_manager, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, - /*llmq_dbs_wipe=*/fReset || fReindexChainState, quorums_watch, consensus_params); + /*llmq_dbs_wipe=*/fReset || fReindexChainState, quorums_recovery, quorums_watch, consensus_params); if (fReset) { pblocktree->WriteReindexing(true); @@ -225,6 +226,7 @@ void DashChainstateSetup(ChainstateManager& chainman, const fs::path& data_dir, bool llmq_dbs_in_memory, bool llmq_dbs_wipe, + bool quorums_recovery, bool quorums_watch, const Consensus::Params& consensus_params) { @@ -243,7 +245,7 @@ void DashChainstateSetup(ChainstateManager& chainman, llmq_ctx = std::make_unique(chainman, *dmnman, *evodb, mn_metaman, *mnhf_manager, sporkman, *mempool, mn_activeman.get(), mn_sync, util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, - quorums_watch); + quorums_recovery, quorums_watch); mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); // Enable CMNHFManager::{Process, Undo}Block mnhf_manager->ConnectManagers(llmq_ctx->qman.get()); diff --git a/src/node/chainstate.h b/src/node/chainstate.h index 6e1326b8879e..d8a9c3a4d22c 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -105,6 +105,7 @@ std::optional LoadChainstate(bool fReset, bool block_tree_db_in_memory, bool coins_db_in_memory, bool dash_dbs_in_memory, + bool quorums_recovery, bool quorums_watch, std::function shutdown_requested = nullptr, std::function coins_error_cb = nullptr); @@ -126,6 +127,7 @@ void DashChainstateSetup(ChainstateManager& chainman, const fs::path& data_dir, bool llmq_dbs_in_memory, bool llmq_dbs_wipe, + bool quorums_recovery, bool quorums_watch, const Consensus::Params& consensus_params); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 3007ad99d3bf..cc957f076dbb 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -135,7 +135,7 @@ void DashChainstateSetup(ChainstateManager& chainman, DashChainstateSetup(chainman, *Assert(node.govman.get()), *Assert(node.mn_metaman.get()), *Assert(node.mn_sync.get()), *Assert(node.sporkman.get()), node.mn_activeman, node.chain_helper, node.cpoolman, node.dmnman, node.evodb, node.mnhf_manager, node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), - llmq_dbs_in_memory, llmq_dbs_wipe, /*quorums_watch=*/false, consensus_params); + llmq_dbs_in_memory, llmq_dbs_wipe, /*quorums_recovery=*/false, /*quorums_watch=*/false, consensus_params); } void DashChainstateSetupClose(NodeContext& node) @@ -333,6 +333,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector Date: Tue, 9 Dec 2025 00:29:17 +0530 Subject: [PATCH 03/12] refactor: move `GetEnabledQuorumVvecSyncEntries()` invocation to init Same rationale as previous commit. --- src/init.cpp | 3 ++- src/llmq/context.cpp | 8 ++++---- src/llmq/context.h | 6 ++++-- src/llmq/options.cpp | 6 +++--- src/llmq/options.h | 24 ++++++++++++------------ src/llmq/quorums.cpp | 12 ++++++------ src/llmq/quorums.h | 9 ++++++--- src/node/chainstate.cpp | 6 ++++-- src/node/chainstate.h | 4 ++++ src/test/util/setup_common.cpp | 4 +++- 10 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 2646d8200cab..9b0eb62ab1f9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1409,7 +1409,7 @@ bool AppInitParameterInteraction(const ArgsManager& args) } try { - const bool fQuorumVvecRequestsEnabled{llmq::GetEnabledQuorumVvecSyncEntries().size() > 0}; + const bool fQuorumVvecRequestsEnabled{llmq::GetEnabledQuorumVvecSyncEntries(args).size() > 0}; if (!args.GetBoolArg("-llmq-data-recovery", llmq::DEFAULT_ENABLE_QUORUM_DATA_RECOVERY) && fQuorumVvecRequestsEnabled) { InitWarning(Untranslated("-llmq-qvvec-sync set but recovery is disabled due to -llmq-data-recovery=0")); } @@ -2025,6 +2025,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) args.GetBoolArg("-spentindex", DEFAULT_SPENTINDEX), args.GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX), chainparams.GetConsensus(), + llmq::GetEnabledQuorumVvecSyncEntries(args), fReindexChainState, cache_sizes.block_tree_db, cache_sizes.coins_db, diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index bb936f617d30..372abe10a85f 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -18,8 +18,8 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_recovery, - bool quorums_watch) : + const CMasternodeSync& mn_sync, const llmq::QvvecSyncModeMap& sync_map, + const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch) : bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, qsnapman{std::make_unique(evo_db)}, @@ -29,8 +29,8 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d *quorum_block_processor, *qsnapman, mn_activeman, chainman, sporkman, db_params, quorums_watch)}, qman{std::make_unique(*bls_worker, dmnman, *qdkgsman, evo_db, *quorum_block_processor, - *qsnapman, mn_activeman, chainman, mn_sync, sporkman, db_params, - quorums_recovery, quorums_watch)}, + *qsnapman, mn_activeman, chainman, mn_sync, sporkman, sync_map, + db_params, quorums_recovery, quorums_watch)}, sigman{std::make_unique(*qman, db_params)}, clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, sporkman, mempool, mn_sync)}, isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *sigman, sporkman, diff --git a/src/llmq/context.h b/src/llmq/context.h index 53adc5ec094b..17e70283a9d9 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_LLMQ_CONTEXT_H #define BITCOIN_LLMQ_CONTEXT_H +#include + #include class CActiveMasternodeManager; @@ -41,8 +43,8 @@ struct LLMQContext { explicit LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_recovery, - bool quorums_watch); + const CMasternodeSync& mn_sync, const llmq::QvvecSyncModeMap& sync_map, + const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch); ~LLMQContext(); void Interrupt(); diff --git a/src/llmq/options.cpp b/src/llmq/options.cpp index b8a2550dfa17..30d6f77b148f 100644 --- a/src/llmq/options.cpp +++ b/src/llmq/options.cpp @@ -56,10 +56,10 @@ bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, gsl::not_n return DeploymentActiveAfter(pindex->GetAncestor(cycleQuorumBaseHeight - 1), Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024); } -std::map GetEnabledQuorumVvecSyncEntries() +QvvecSyncModeMap GetEnabledQuorumVvecSyncEntries(const ArgsManager& args) { - std::map mapQuorumVvecSyncEntries; - for (const auto& strEntry : gArgs.GetArgs("-llmq-qvvec-sync")) { + QvvecSyncModeMap mapQuorumVvecSyncEntries; + for (const auto& strEntry : args.GetArgs("-llmq-qvvec-sync")) { Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE; QvvecSyncMode mode{QvvecSyncMode::Invalid}; std::istringstream ssEntry(strEntry); diff --git a/src/llmq/options.h b/src/llmq/options.h index 782727c60448..b19d44ed25da 100644 --- a/src/llmq/options.h +++ b/src/llmq/options.h @@ -5,20 +5,22 @@ #ifndef BITCOIN_LLMQ_OPTIONS_H #define BITCOIN_LLMQ_OPTIONS_H -#include #include #include #include #include +class ArgsManager; class CBlockIndex; class ChainstateManager; class CSporkManager; +namespace Consensus { +struct LLMQParams; +enum class LLMQType : uint8_t; +} // namespace Consensus -namespace llmq -{ - +namespace llmq { enum class QvvecSyncMode { Invalid = -1, Always = 0, @@ -26,28 +28,26 @@ enum class QvvecSyncMode { }; /** Maximum number of dedicated script-checking threads allowed */ -static const int MAX_BLSCHECK_THREADS = 33; +static const int MAX_BLSCHECK_THREADS{33}; /** -parbls default (number of bls-checking threads, 0 = auto) */ -static const int DEFAULT_BLSCHECK_THREADS = 0; - +static const int DEFAULT_BLSCHECK_THREADS{0}; +/** -llmq-data-recovery default */ static constexpr bool DEFAULT_ENABLE_QUORUM_DATA_RECOVERY{true}; - -// If true, we will connect to all new quorums and watch their communication +/** -watchquorums default, if true, we will connect to all new quorums and watch their communication */ static constexpr bool DEFAULT_WATCH_QUORUMS{false}; bool IsAllMembersConnectedEnabled(const Consensus::LLMQType llmqType, const CSporkManager& sporkman); bool IsQuorumPoseEnabled(const Consensus::LLMQType llmqType, const CSporkManager& sporkman); - bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, gsl::not_null pindex); /// Returns the parsed entries given by `-llmq-qvvec-sync` -std::map GetEnabledQuorumVvecSyncEntries(); +using QvvecSyncModeMap = std::map; +QvvecSyncModeMap GetEnabledQuorumVvecSyncEntries(const ArgsManager& args); std::vector GetEnabledQuorumTypes(const ChainstateManager& chainman, gsl::not_null pindex); std::vector> GetEnabledQuorumParams( const ChainstateManager& chainman, gsl::not_null pindex); - } // namespace llmq #endif // BITCOIN_LLMQ_OPTIONS_H diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 8b6ca7075743..17a3846f46e8 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -211,8 +211,8 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, const util::DbWrapperParams& db_params, - bool quorums_recovery, bool quorums_watch) : + const CSporkManager& sporkman, const llmq::QvvecSyncModeMap& sync_map, + const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch) : blsWorker{_blsWorker}, m_dmnman{dmnman}, dkgManager{_dkgManager}, @@ -222,6 +222,7 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& m_chainman{chainman}, m_mn_sync{mn_sync}, m_sporkman{sporkman}, + m_sync_map{sync_map}, m_quorums_recovery{quorums_recovery}, m_quorums_watch{quorums_watch}, db{util::MakeDbWrapper({db_params.path / "llmq" / "quorumdb", db_params.memory, db_params.wipe, /*cache_size=*/1 << 20})} @@ -257,8 +258,6 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(CConnman& connman, const C return; } - const std::map mapQuorumVvecSync = GetEnabledQuorumVvecSyncEntries(); - LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- Process block %s\n", __func__, pIndex->GetBlockHash().ToString()); for (const auto& params : Params().GetConsensus().llmqs) { @@ -279,8 +278,9 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(CConnman& connman, const C uint16_t nDataMask{0}; const bool fWeAreQuorumMember = pQuorum->IsValidMember(proTxHash); - const bool fSyncForTypeEnabled = mapQuorumVvecSync.count(pQuorum->qc->llmqType) > 0; - const QvvecSyncMode syncMode = fSyncForTypeEnabled ? mapQuorumVvecSync.at(pQuorum->qc->llmqType) : QvvecSyncMode::Invalid; + const bool fSyncForTypeEnabled = m_sync_map.count(pQuorum->qc->llmqType) > 0; + const QvvecSyncMode syncMode = fSyncForTypeEnabled ? m_sync_map.at(pQuorum->qc->llmqType) + : QvvecSyncMode::Invalid; const bool fSyncCurrent = syncMode == QvvecSyncMode::Always || (syncMode == QvvecSyncMode::OnlyIfTypeMember && fWeAreQuorumTypeMember); if ((fWeAreQuorumMember || (fSyncForTypeEnabled && fSyncCurrent)) && !pQuorum->HasVerificationVector()) { diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 3f92a7102142..a637a90bd82a 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -242,6 +243,7 @@ class CQuorumManager const ChainstateManager& m_chainman; const CMasternodeSync& m_mn_sync; const CSporkManager& m_sporkman; + const llmq::QvvecSyncModeMap m_sync_map; const bool m_quorums_recovery{false}; const bool m_quorums_watch{false}; @@ -272,9 +274,10 @@ class CQuorumManager CQuorumManager(const CQuorumManager&) = delete; CQuorumManager& operator=(const CQuorumManager&) = delete; explicit CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, - CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, - const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, - const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, + CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, + const ChainstateManager& chainman, const CMasternodeSync& mn_sync, + const CSporkManager& sporkman, const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch); ~CQuorumManager(); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index 26a0b45f8db5..458ff961905b 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -54,6 +54,7 @@ std::optional LoadChainstate(bool fReset, bool is_spentindex_enabled, bool is_timeindex_enabled, const Consensus::Params& consensus_params, + const llmq::QvvecSyncModeMap& sync_map, bool fReindexChainState, int64_t nBlockTreeDBCache, int64_t nCoinDBCache, @@ -89,7 +90,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, mn_activeman, chain_helper, cpoolman, - dmnman, evodb, mnhf_manager, llmq_ctx, mempool, data_dir, dash_dbs_in_memory, + dmnman, evodb, mnhf_manager, llmq_ctx, mempool, data_dir, sync_map, dash_dbs_in_memory, /*llmq_dbs_wipe=*/fReset || fReindexChainState, quorums_recovery, quorums_watch, consensus_params); if (fReset) { @@ -224,6 +225,7 @@ void DashChainstateSetup(ChainstateManager& chainman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, + const llmq::QvvecSyncModeMap& sync_map, bool llmq_dbs_in_memory, bool llmq_dbs_wipe, bool quorums_recovery, @@ -243,7 +245,7 @@ void DashChainstateSetup(ChainstateManager& chainman, } llmq_ctx.reset(); llmq_ctx = std::make_unique(chainman, *dmnman, *evodb, mn_metaman, *mnhf_manager, sporkman, - *mempool, mn_activeman.get(), mn_sync, + *mempool, mn_activeman.get(), mn_sync, sync_map, util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, quorums_recovery, quorums_watch); mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); diff --git a/src/node/chainstate.h b/src/node/chainstate.h index d8a9c3a4d22c..c1104bdc5358 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_NODE_CHAINSTATE_H #define BITCOIN_NODE_CHAINSTATE_H +#include + #include #include #include @@ -98,6 +100,7 @@ std::optional LoadChainstate(bool fReset, bool is_spentindex_enabled, bool is_timeindex_enabled, const Consensus::Params& consensus_params, + const llmq::QvvecSyncModeMap& sync_map, bool fReindexChainState, int64_t nBlockTreeDBCache, int64_t nCoinDBCache, @@ -125,6 +128,7 @@ void DashChainstateSetup(ChainstateManager& chainman, std::unique_ptr& llmq_ctx, CTxMemPool* mempool, const fs::path& data_dir, + const llmq::QvvecSyncModeMap& sync_map, bool llmq_dbs_in_memory, bool llmq_dbs_wipe, bool quorums_recovery, diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index cc957f076dbb..59d60d858416 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -135,7 +135,8 @@ void DashChainstateSetup(ChainstateManager& chainman, DashChainstateSetup(chainman, *Assert(node.govman.get()), *Assert(node.mn_metaman.get()), *Assert(node.mn_sync.get()), *Assert(node.sporkman.get()), node.mn_activeman, node.chain_helper, node.cpoolman, node.dmnman, node.evodb, node.mnhf_manager, node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), - llmq_dbs_in_memory, llmq_dbs_wipe, /*quorums_recovery=*/false, /*quorums_watch=*/false, consensus_params); + llmq::QvvecSyncModeMap{}, llmq_dbs_in_memory, llmq_dbs_wipe, /*quorums_recovery=*/false, + /*quorums_watch=*/false, consensus_params); } void DashChainstateSetupClose(NodeContext& node) @@ -326,6 +327,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector Date: Fri, 19 Dec 2025 02:23:59 +0530 Subject: [PATCH 04/12] refactor: drop remaining `gArgs` usage in LLMQ code Same rationale as previous commit. --- src/init.cpp | 11 +++++++++++ src/llmq/blockprocessor.cpp | 15 +-------------- src/llmq/blockprocessor.h | 2 +- src/llmq/context.cpp | 9 +++++---- src/llmq/context.h | 3 ++- src/llmq/options.h | 4 ++-- src/llmq/signing.cpp | 12 ++++++------ src/llmq/signing.h | 4 ++-- src/node/chainstate.cpp | 9 +++++++-- src/node/chainstate.h | 4 ++++ src/test/util/setup_common.cpp | 9 ++++++--- src/test/validation_chainstatemanager_tests.cpp | 10 ++++++---- 12 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 9b0eb62ab1f9..a89289edc1f5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2035,6 +2035,17 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) /*dash_dbs_in_memory=*/false, quorums_recovery, quorums_watch, + /*bls_threads=*/[&args]() -> int8_t { + int8_t threads = args.GetIntArg("-parbls", llmq::DEFAULT_BLSCHECK_THREADS); + if (threads <= 0) { + // -parbls=0 means autodetect (number of cores - 1 validator threads) + // -parbls=-n means "leave n cores free" (number of cores - n - 1 validator threads) + threads += GetNumCores(); + } + // Subtract 1 because the main thread counts towards the par threads + return std::clamp(threads - 1, 0, llmq::MAX_BLSCHECK_THREADS); + }(), + args.GetIntArg("-maxrecsigsage", llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE), /*shutdown_requested=*/ShutdownRequested, /*coins_error_cb=*/[]() { uiInterface.ThreadSafeMessageBox( diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index 791cd430115a..dbffa4e06e1d 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -46,26 +46,13 @@ static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT_Q_INDEXED = "q_m static const std::string DB_BEST_BLOCK_UPGRADE = "q_bbu2"; CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb, - CQuorumSnapshotManager& qsnapman) : + CQuorumSnapshotManager& qsnapman, int8_t bls_threads) : m_chainstate{chainstate}, m_dmnman{dmnman}, m_evoDb{evoDb}, m_qsnapman{qsnapman} { utils::InitQuorumsCache(mapHasMinedCommitmentCache); - - int bls_threads = gArgs.GetIntArg("-parbls", DEFAULT_BLSCHECK_THREADS); - if (bls_threads <= 0) { - // -parbls=0 means autodetect (number of cores - 1 validator threads) - // -parbls=-n means "leave n cores free" (number of cores - n - 1 validator threads) - bls_threads += GetNumCores(); - } - // Subtract 1 because the main thread counts towards the par threads - bls_threads = std::max(bls_threads - 1, 0); - - // Number of script-checking threads <= MAX_BLSCHECK_THREADS - bls_threads = std::min(bls_threads, MAX_BLSCHECK_THREADS); - LogPrintf("BLS verification uses %d additional threads\n", bls_threads); m_bls_queue.StartWorkerThreads(bls_threads); } diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index 97e4edf3f30e..e44506131036 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -59,7 +59,7 @@ class CQuorumBlockProcessor CQuorumBlockProcessor(const CQuorumBlockProcessor&) = delete; CQuorumBlockProcessor& operator=(const CQuorumBlockProcessor&) = delete; explicit CQuorumBlockProcessor(CChainState& chainstate, CDeterministicMNManager& dmnman, CEvoDB& evoDb, - CQuorumSnapshotManager& qsnapman); + CQuorumSnapshotManager& qsnapman, int8_t bls_threads); ~CQuorumBlockProcessor(); [[nodiscard]] MessageProcessingResult ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv) diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index 372abe10a85f..f609980015ff 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -19,19 +19,20 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch) : + const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch, + int8_t bls_threads, int64_t max_recsigs_age) : bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, qsnapman{std::make_unique(evo_db)}, - quorum_block_processor{ - std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db, *qsnapman)}, + quorum_block_processor{std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db, + *qsnapman, bls_threads)}, qdkgsman{std::make_unique(*bls_worker, dmnman, *dkg_debugman, mn_metaman, *quorum_block_processor, *qsnapman, mn_activeman, chainman, sporkman, db_params, quorums_watch)}, qman{std::make_unique(*bls_worker, dmnman, *qdkgsman, evo_db, *quorum_block_processor, *qsnapman, mn_activeman, chainman, mn_sync, sporkman, sync_map, db_params, quorums_recovery, quorums_watch)}, - sigman{std::make_unique(*qman, db_params)}, + sigman{std::make_unique(*qman, db_params, max_recsigs_age)}, clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, sporkman, mempool, mn_sync)}, isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *sigman, sporkman, mempool, mn_sync, db_params)} diff --git a/src/llmq/context.h b/src/llmq/context.h index 17e70283a9d9..a8189f7e3ea1 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -44,7 +44,8 @@ struct LLMQContext { CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch); + const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch, + int8_t bls_threads, int64_t max_recsigs_age); ~LLMQContext(); void Interrupt(); diff --git a/src/llmq/options.h b/src/llmq/options.h index b19d44ed25da..41347d8f3239 100644 --- a/src/llmq/options.h +++ b/src/llmq/options.h @@ -28,9 +28,9 @@ enum class QvvecSyncMode { }; /** Maximum number of dedicated script-checking threads allowed */ -static const int MAX_BLSCHECK_THREADS{33}; +static const int8_t MAX_BLSCHECK_THREADS{33}; /** -parbls default (number of bls-checking threads, 0 = auto) */ -static const int DEFAULT_BLSCHECK_THREADS{0}; +static const int8_t DEFAULT_BLSCHECK_THREADS{0}; /** -llmq-data-recovery default */ static constexpr bool DEFAULT_ENABLE_QUORUM_DATA_RECOVERY{true}; /** -watchquorums default, if true, we will connect to all new quorums and watch their communication */ diff --git a/src/llmq/signing.cpp b/src/llmq/signing.cpp index c8a14c61d249..b87a679a9d44 100644 --- a/src/llmq/signing.cpp +++ b/src/llmq/signing.cpp @@ -326,9 +326,11 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge) ////////////////// -CSigningManager::CSigningManager(const CQuorumManager& _qman, const util::DbWrapperParams& db_params) : +CSigningManager::CSigningManager(const CQuorumManager& _qman, const util::DbWrapperParams& db_params, + int64_t max_recsigs_age) : db{db_params}, - qman{_qman} + qman{_qman}, + m_max_recsigs_age{max_recsigs_age} { } @@ -534,10 +536,8 @@ void CSigningManager::TruncateRecoveredSig(Consensus::LLMQType llmqType, const u void CSigningManager::Cleanup() { - int64_t maxAge = gArgs.GetIntArg("-maxrecsigsage", DEFAULT_MAX_RECOVERED_SIGS_AGE); - - db.CleanupOldRecoveredSigs(maxAge); - db.CleanupOldVotes(maxAge); + db.CleanupOldRecoveredSigs(m_max_recsigs_age); + db.CleanupOldVotes(m_max_recsigs_age); } void CSigningManager::RegisterRecoveredSigsListener(CRecoveredSigsListener* l) diff --git a/src/llmq/signing.h b/src/llmq/signing.h index 5ffee265fced..726e7e62041a 100644 --- a/src/llmq/signing.h +++ b/src/llmq/signing.h @@ -158,9 +158,9 @@ class CRecoveredSigsListener class CSigningManager { private: - CRecoveredSigsDb db; const CQuorumManager& qman; + const int64_t m_max_recsigs_age; mutable Mutex cs_pending; // Incoming and not verified yet @@ -176,7 +176,7 @@ class CSigningManager CSigningManager() = delete; CSigningManager(const CSigningManager&) = delete; CSigningManager& operator=(const CSigningManager&) = delete; - explicit CSigningManager(const CQuorumManager& _qman, const util::DbWrapperParams& db_params); + explicit CSigningManager(const CQuorumManager& _qman, const util::DbWrapperParams& db_params, int64_t max_recsigs_age); ~CSigningManager(); bool AlreadyHave(const CInv& inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs_pending); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index 458ff961905b..d80690bfde0d 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -64,6 +64,8 @@ std::optional LoadChainstate(bool fReset, bool dash_dbs_in_memory, bool quorums_recovery, bool quorums_watch, + int8_t bls_threads, + int64_t max_recsigs_age, std::function shutdown_requested, std::function coins_error_cb) { @@ -91,7 +93,8 @@ std::optional LoadChainstate(bool fReset, DashChainstateSetup(chainman, govman, mn_metaman, mn_sync, sporkman, mn_activeman, chain_helper, cpoolman, dmnman, evodb, mnhf_manager, llmq_ctx, mempool, data_dir, sync_map, dash_dbs_in_memory, - /*llmq_dbs_wipe=*/fReset || fReindexChainState, quorums_recovery, quorums_watch, consensus_params); + /*llmq_dbs_wipe=*/fReset || fReindexChainState, quorums_recovery, quorums_watch, + bls_threads, max_recsigs_age, consensus_params); if (fReset) { pblocktree->WriteReindexing(true); @@ -230,6 +233,8 @@ void DashChainstateSetup(ChainstateManager& chainman, bool llmq_dbs_wipe, bool quorums_recovery, bool quorums_watch, + int8_t bls_threads, + int64_t max_recsigs_age, const Consensus::Params& consensus_params) { // Same logic as pblocktree @@ -247,7 +252,7 @@ void DashChainstateSetup(ChainstateManager& chainman, llmq_ctx = std::make_unique(chainman, *dmnman, *evodb, mn_metaman, *mnhf_manager, sporkman, *mempool, mn_activeman.get(), mn_sync, sync_map, util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, - quorums_recovery, quorums_watch); + quorums_recovery, quorums_watch, 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()); diff --git a/src/node/chainstate.h b/src/node/chainstate.h index c1104bdc5358..3e28d5bf0447 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -110,6 +110,8 @@ std::optional LoadChainstate(bool fReset, bool dash_dbs_in_memory, bool quorums_recovery, bool quorums_watch, + int8_t bls_threads, + int64_t max_recsigs_age, std::function shutdown_requested = nullptr, std::function coins_error_cb = nullptr); @@ -133,6 +135,8 @@ void DashChainstateSetup(ChainstateManager& chainman, bool llmq_dbs_wipe, bool quorums_recovery, bool quorums_watch, + int8_t bls_threads, + int64_t max_recsigs_age, const Consensus::Params& consensus_params); void DashChainstateSetupClose(std::unique_ptr& chain_helper, diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 59d60d858416..8235a7e86abb 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -135,8 +136,8 @@ void DashChainstateSetup(ChainstateManager& chainman, DashChainstateSetup(chainman, *Assert(node.govman.get()), *Assert(node.mn_metaman.get()), *Assert(node.mn_sync.get()), *Assert(node.sporkman.get()), node.mn_activeman, node.chain_helper, node.cpoolman, node.dmnman, node.evodb, node.mnhf_manager, node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), - llmq::QvvecSyncModeMap{}, llmq_dbs_in_memory, llmq_dbs_wipe, /*quorums_recovery=*/false, - /*quorums_watch=*/false, consensus_params); + llmq::QvvecSyncModeMap{}, llmq_dbs_in_memory, llmq_dbs_wipe, /*quorums_recovery=*/false, /*quorums_watch=*/false, + llmq::DEFAULT_BLSCHECK_THREADS, llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE, consensus_params); } void DashChainstateSetupClose(NodeContext& node) @@ -336,7 +337,9 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector #include -#include #include -#include -#include #include #include #include #include -#include #include #include #include @@ -20,6 +16,12 @@ #include #include +#include +#include +#include +#include +#include + #include #include From 5d54cfe458c8a1586e4a74efdb562e6651baa7ae Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 19 Dec 2025 02:05:08 +0530 Subject: [PATCH 05/12] refactor: couple listener registration with instantiation The context that creates the signer should register the listener rather than relying on the timing being exactly right on when Start() is called by the controlling manager. Also: - Use more descriptive function names replacing Start()/Stop() - Fixup order of events in ActiveContext c/dtor and Start()/Stop() --- src/chainlock/chainlock.cpp | 6 ------ src/chainlock/signing.cpp | 4 ++-- src/chainlock/signing.h | 4 ++-- src/instantsend/instantsend.h | 2 +- src/instantsend/net_instantsend.cpp | 8 -------- src/instantsend/signing.cpp | 4 ++-- src/instantsend/signing.h | 4 ++-- src/llmq/signing_shares.cpp | 4 ++-- src/llmq/signing_shares.h | 4 ++-- src/masternode/active/context.cpp | 10 +++++++--- 10 files changed, 20 insertions(+), 30 deletions(-) diff --git a/src/chainlock/chainlock.cpp b/src/chainlock/chainlock.cpp index 8ea6e20c3912..da2e6ee05166 100644 --- a/src/chainlock/chainlock.cpp +++ b/src/chainlock/chainlock.cpp @@ -63,9 +63,6 @@ CChainLocksHandler::~CChainLocksHandler() void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman) { - if (auto signer = m_signer.load(std::memory_order_acquire); signer) { - signer->Start(); - } scheduler->scheduleEvery( [&]() { auto signer = m_signer.load(std::memory_order_acquire); @@ -83,9 +80,6 @@ void CChainLocksHandler::Start(const llmq::CInstantSendManager& isman) void CChainLocksHandler::Stop() { scheduler->stop(); - if (auto signer = m_signer.load(std::memory_order_acquire); signer) { - signer->Stop(); - } } bool CChainLocksHandler::AlreadyHave(const CInv& inv) const diff --git a/src/chainlock/signing.cpp b/src/chainlock/signing.cpp index 9b574d5cc6ee..0eba67843312 100644 --- a/src/chainlock/signing.cpp +++ b/src/chainlock/signing.cpp @@ -30,12 +30,12 @@ ChainLockSigner::ChainLockSigner(CChainState& chainstate, ChainLockSignerParent& ChainLockSigner::~ChainLockSigner() = default; -void ChainLockSigner::Start() +void ChainLockSigner::RegisterRecoveryInterface() { m_sigman.RegisterRecoveredSigsListener(this); } -void ChainLockSigner::Stop() +void ChainLockSigner::UnregisterRecoveryInterface() { m_sigman.UnregisterRecoveredSigsListener(this); } diff --git a/src/chainlock/signing.h b/src/chainlock/signing.h index 357b3295f757..a6fac9de17d6 100644 --- a/src/chainlock/signing.h +++ b/src/chainlock/signing.h @@ -70,8 +70,8 @@ class ChainLockSigner final : public llmq::CRecoveredSigsListener llmq::CSigSharesManager& shareman, CSporkManager& sporkman, const CMasternodeSync& mn_sync); ~ChainLockSigner(); - void Start(); - void Stop(); + void RegisterRecoveryInterface(); + void UnregisterRecoveryInterface(); void EraseFromBlockHashTxidMap(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(!cs_signer); diff --git a/src/instantsend/instantsend.h b/src/instantsend/instantsend.h index 9b93198e85f4..22421c8fc34f 100644 --- a/src/instantsend/instantsend.h +++ b/src/instantsend/instantsend.h @@ -118,7 +118,7 @@ class CInstantSendManager final : public instantsend::InstantSendSignerParent } void DisconnectSigner() { m_signer.store(nullptr, std::memory_order_release); } - instantsend::InstantSendSigner* Signer() const { return m_signer.load(); } + instantsend::InstantSendSigner* Signer() const { return m_signer.load(std::memory_order_acquire); } private: void AddNonLockedTx(const CTransactionRef& tx, const CBlockIndex* pindexMined) diff --git a/src/instantsend/net_instantsend.cpp b/src/instantsend/net_instantsend.cpp index efd217c10d51..e9d51321466a 100644 --- a/src/instantsend/net_instantsend.cpp +++ b/src/instantsend/net_instantsend.cpp @@ -72,18 +72,10 @@ void NetInstantSend::Start() } workThread = std::thread(&util::TraceThread, "isman", [this] { WorkThreadMain(); }); - - if (auto signer = m_is_manager.Signer(); signer) { - signer->Start(); - } } void NetInstantSend::Stop() { - if (auto signer = m_is_manager.Signer(); signer) { - signer->Stop(); - } - // make sure to call Interrupt() first if (!workInterrupt) { assert(false); diff --git a/src/instantsend/signing.cpp b/src/instantsend/signing.cpp index 984968d9c53d..b8c22c814b90 100644 --- a/src/instantsend/signing.cpp +++ b/src/instantsend/signing.cpp @@ -46,12 +46,12 @@ InstantSendSigner::InstantSendSigner(CChainState& chainstate, llmq::CChainLocksH InstantSendSigner::~InstantSendSigner() = default; -void InstantSendSigner::Start() +void InstantSendSigner::RegisterRecoveryInterface() { m_sigman.RegisterRecoveredSigsListener(this); } -void InstantSendSigner::Stop() +void InstantSendSigner::UnregisterRecoveryInterface() { m_sigman.UnregisterRecoveredSigsListener(this); } diff --git a/src/instantsend/signing.h b/src/instantsend/signing.h index cf878e8c21e9..d954daaae535 100644 --- a/src/instantsend/signing.h +++ b/src/instantsend/signing.h @@ -82,8 +82,8 @@ class InstantSendSigner final : public llmq::CRecoveredSigsListener CTxMemPool& mempool, const CMasternodeSync& mn_sync); ~InstantSendSigner(); - void Start(); - void Stop(); + void RegisterRecoveryInterface(); + void UnregisterRecoveryInterface(); void ClearInputsFromQueue(const Uint256HashSet& ids) EXCLUSIVE_LOCKS_REQUIRED(!cs_input_requests); diff --git a/src/llmq/signing_shares.cpp b/src/llmq/signing_shares.cpp index 382f7aef43d2..c6e3e444f43d 100644 --- a/src/llmq/signing_shares.cpp +++ b/src/llmq/signing_shares.cpp @@ -237,12 +237,12 @@ void CSigSharesManager::Stop() workerPool.stop(true); } -void CSigSharesManager::RegisterAsRecoveredSigsListener() +void CSigSharesManager::RegisterRecoveryInterface() { sigman.RegisterRecoveredSigsListener(this); } -void CSigSharesManager::UnregisterAsRecoveredSigsListener() +void CSigSharesManager::UnregisterRecoveryInterface() { sigman.UnregisterRecoveredSigsListener(this); } diff --git a/src/llmq/signing_shares.h b/src/llmq/signing_shares.h index 8570c3c11435..e6d91f7b25a2 100644 --- a/src/llmq/signing_shares.h +++ b/src/llmq/signing_shares.h @@ -431,8 +431,8 @@ class CSigSharesManager : public llmq::CRecoveredSigsListener void Start() EXCLUSIVE_LOCKS_REQUIRED(!cs); void Stop() EXCLUSIVE_LOCKS_REQUIRED(!cs); - void RegisterAsRecoveredSigsListener() EXCLUSIVE_LOCKS_REQUIRED(!cs); - void UnregisterAsRecoveredSigsListener() EXCLUSIVE_LOCKS_REQUIRED(!cs); + void RegisterRecoveryInterface() EXCLUSIVE_LOCKS_REQUIRED(!cs); + void UnregisterRecoveryInterface() EXCLUSIVE_LOCKS_REQUIRED(!cs); void InterruptWorkerThread() EXCLUSIVE_LOCKS_REQUIRED(!cs); void ProcessMessage(const CNode& pnode, const std::string& msg_type, CDataStream& vRecv) EXCLUSIVE_LOCKS_REQUIRED(!cs); diff --git a/src/masternode/active/context.cpp b/src/masternode/active/context.cpp index 12575ad34462..f97a86510772 100644 --- a/src/masternode/active/context.cpp +++ b/src/masternode/active/context.cpp @@ -40,8 +40,8 @@ ActiveContext::ActiveContext(ChainstateManager& chainman, CConnman& connman, CDe ActiveContext::~ActiveContext() { - m_llmq_ctx.clhandler->DisconnectSigner(); m_llmq_ctx.isman->DisconnectSigner(); + m_llmq_ctx.clhandler->DisconnectSigner(); } void ActiveContext::Interrupt() @@ -52,13 +52,17 @@ void ActiveContext::Interrupt() void ActiveContext::Start(CConnman& connman, PeerManager& peerman) { m_llmq_ctx.qdkgsman->StartThreads(connman, peerman); - shareman->RegisterAsRecoveredSigsListener(); shareman->Start(); + cl_signer->RegisterRecoveryInterface(); + is_signer->RegisterRecoveryInterface(); + shareman->RegisterRecoveryInterface(); } void ActiveContext::Stop() { + shareman->UnregisterRecoveryInterface(); + is_signer->UnregisterRecoveryInterface(); + cl_signer->UnregisterRecoveryInterface(); shareman->Stop(); - shareman->UnregisterAsRecoveredSigsListener(); m_llmq_ctx.qdkgsman->StopThreads(); } From 6b811c2b445818eacb7c710e5d56070306e24a96 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 23 Dec 2025 19:48:57 +0530 Subject: [PATCH 06/12] refactor: make `CDKGSessionManager` a plugable obj for `CQuorumManager` Also: - Drop unneeded argument from LLMQContext::Start() - Drop LLMQContext::Interrupt() that does nothing --- src/init.cpp | 5 +---- src/llmq/context.cpp | 16 +++++++------- src/llmq/context.h | 3 +-- src/llmq/quorums.cpp | 21 ++++++++++-------- src/llmq/quorums.h | 22 +++++++++++++------ src/node/chainstate.cpp | 1 - src/test/util/setup_common.cpp | 1 - .../validation_chainstatemanager_tests.cpp | 2 -- 8 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index a89289edc1f5..cc9f38c66be4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -258,9 +258,6 @@ void Interrupt(NodeContext& node) if (node.peerman) { node.peerman->InterruptHandlers(); } - if (node.llmq_ctx) { - node.llmq_ctx->Interrupt(); - } InterruptMapPort(); if (node.connman) node.connman->Interrupt(); @@ -2323,7 +2320,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // ********************************************************* Step 10a: schedule Dash-specific tasks - node.llmq_ctx->Start(*node.peerman); + node.llmq_ctx->Start(); node.peerman->StartHandlers(); if (node.active_ctx) node.active_ctx->Start(*node.connman, *node.peerman); diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index f609980015ff..76334c409332 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -29,9 +29,9 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d qdkgsman{std::make_unique(*bls_worker, dmnman, *dkg_debugman, mn_metaman, *quorum_block_processor, *qsnapman, mn_activeman, chainman, sporkman, db_params, quorums_watch)}, - qman{std::make_unique(*bls_worker, dmnman, *qdkgsman, evo_db, *quorum_block_processor, - *qsnapman, mn_activeman, chainman, mn_sync, sporkman, sync_map, - db_params, quorums_recovery, quorums_watch)}, + qman{std::make_unique(*bls_worker, dmnman, evo_db, *quorum_block_processor, *qsnapman, + mn_activeman, chainman, mn_sync, sporkman, sync_map, db_params, + quorums_recovery, quorums_watch)}, sigman{std::make_unique(*qman, db_params, max_recsigs_age)}, clhandler{std::make_unique(chainman.ActiveChainstate(), *qman, sporkman, mempool, mn_sync)}, isman{std::make_unique(*clhandler, chainman.ActiveChainstate(), *sigman, sporkman, @@ -39,16 +39,16 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d { // Have to start it early to let VerifyDB check ChainLock signatures in coinbase bls_worker->Start(); + qman->ConnectManager(qdkgsman.get()); } -LLMQContext::~LLMQContext() { +LLMQContext::~LLMQContext() +{ + qman->DisconnectManager(); bls_worker->Stop(); } -void LLMQContext::Interrupt() { -} - -void LLMQContext::Start(PeerManager& peerman) +void LLMQContext::Start() { qman->Start(); clhandler->Start(*isman); diff --git a/src/llmq/context.h b/src/llmq/context.h index a8189f7e3ea1..653dfdc1fc2f 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -48,8 +48,7 @@ struct LLMQContext { int8_t bls_threads, int64_t max_recsigs_age); ~LLMQContext(); - void Interrupt(); - void Start(PeerManager& peerman); + void Start(); void Stop(); /** Guaranteed if LLMQContext is initialized then all members are valid too diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 17a3846f46e8..9901d3909ebe 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -207,15 +207,14 @@ bool CQuorum::ReadContributions(const CDBWrapper& db) return true; } -CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, - CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, - CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, - const ChainstateManager& chainman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch) : +CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CEvoDB& _evoDb, + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, + const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params, + bool quorums_recovery, bool quorums_watch) : blsWorker{_blsWorker}, m_dmnman{dmnman}, - dkgManager{_dkgManager}, quorumBlockProcessor{_quorumBlockProcessor}, m_qsnapman{qsnapman}, m_mn_activeman{mn_activeman}, @@ -451,7 +450,9 @@ bool CQuorumManager::BuildQuorumContributions(const CFinalCommitmentPtr& fqc, co std::vector memberIndexes; std::vector vvecs; std::vector skContributions; - if (!dkgManager.GetVerifiedContributions((Consensus::LLMQType)fqc->llmqType, quorum->m_quorum_base_block_index, fqc->validMembers, memberIndexes, vvecs, skContributions)) { + if (!m_qdkgsman || + !m_qdkgsman->GetVerifiedContributions((Consensus::LLMQType)fqc->llmqType, quorum->m_quorum_base_block_index, + fqc->validMembers, memberIndexes, vvecs, skContributions)) { return false; } @@ -795,7 +796,9 @@ MessageProcessingResult CQuorumManager::ProcessMessage(CNode& pfrom, CConnman& c } std::vector> vecEncrypted; - if (!dkgManager.GetEncryptedContributions(request.GetLLMQType(), pQuorumBaseBlockIndex, pQuorum->qc->validMembers, request.GetProTxHash(), vecEncrypted)) { + if (!m_qdkgsman || + !m_qdkgsman->GetEncryptedContributions(request.GetLLMQType(), pQuorumBaseBlockIndex, + pQuorum->qc->validMembers, request.GetProTxHash(), vecEncrypted)) { return sendQDATA(CQuorumDataRequest::Errors::ENCRYPTED_CONTRIBUTIONS_MISSING, request_limit_exceeded); } diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index a637a90bd82a..84cc3464ea1c 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -236,13 +236,13 @@ class CQuorumManager private: CBLSWorker& blsWorker; CDeterministicMNManager& m_dmnman; - CDKGSessionManager& dkgManager; CQuorumBlockProcessor& quorumBlockProcessor; CQuorumSnapshotManager& m_qsnapman; const CActiveMasternodeManager* const m_mn_activeman; const ChainstateManager& m_chainman; const CMasternodeSync& m_mn_sync; const CSporkManager& m_sporkman; + llmq::CDKGSessionManager* m_qdkgsman{nullptr}; const llmq::QvvecSyncModeMap m_sync_map; const bool m_quorums_recovery{false}; const bool m_quorums_watch{false}; @@ -273,14 +273,22 @@ class CQuorumManager CQuorumManager() = delete; CQuorumManager(const CQuorumManager&) = delete; CQuorumManager& operator=(const CQuorumManager&) = delete; - explicit CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CDKGSessionManager& _dkgManager, - CEvoDB& _evoDb, CQuorumBlockProcessor& _quorumBlockProcessor, - CQuorumSnapshotManager& qsnapman, const CActiveMasternodeManager* const mn_activeman, - const ChainstateManager& chainman, const CMasternodeSync& mn_sync, - const CSporkManager& sporkman, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch); + explicit CQuorumManager(CBLSWorker& _blsWorker, CDeterministicMNManager& dmnman, CEvoDB& _evoDb, + CQuorumBlockProcessor& _quorumBlockProcessor, CQuorumSnapshotManager& qsnapman, + const CActiveMasternodeManager* const mn_activeman, const ChainstateManager& chainman, + const CMasternodeSync& mn_sync, const CSporkManager& sporkman, + const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params, + bool quorums_recovery, bool quorums_watch); ~CQuorumManager(); + void ConnectManager(gsl::not_null qdkgsman) + { + // Prohibit double initialization + assert(m_qdkgsman == nullptr); + m_qdkgsman = qdkgsman; + } + void DisconnectManager() { m_qdkgsman = nullptr; } + void Start(); void Stop(); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index d80690bfde0d..b045a7a568ae 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -245,7 +245,6 @@ void DashChainstateSetup(ChainstateManager& chainman, cpoolman = std::make_unique(*evodb, chainman); if (llmq_ctx) { - llmq_ctx->Interrupt(); llmq_ctx->Stop(); } llmq_ctx.reset(); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 8235a7e86abb..bc42cf0762f6 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -408,7 +408,6 @@ TestingSetup::~TestingSetup() // Interrupt() and PrepareShutdown() routines if (m_node.llmq_ctx) { - m_node.llmq_ctx->Interrupt(); m_node.llmq_ctx->Stop(); } if (m_node.connman) { diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index 3bd30da33ca6..5352527c1a35 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -72,7 +72,6 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) BOOST_CHECK(!manager.SnapshotBlockhash().has_value()); if (m_node.llmq_ctx) { - m_node.llmq_ctx->Interrupt(); m_node.llmq_ctx->Stop(); } DashChainstateSetupClose(m_node); @@ -122,7 +121,6 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) SyncWithValidationInterfaceQueue(); if (m_node.llmq_ctx) { - m_node.llmq_ctx->Interrupt(); m_node.llmq_ctx->Stop(); } DashChainstateSetupClose(m_node); From b9e20f461f054c266b7ad1c00046f5119172e95a Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:35:30 +0530 Subject: [PATCH 07/12] refactor: introduce `MakePeerManager()` helper for test setup We are going to modify PeerManager multiple times, this should make the diffs that'll attract smaller. --- src/test/denialofservice_tests.cpp | 24 ++++-------------------- src/test/net_peer_connection_tests.cpp | 6 +----- src/test/util/setup_common.cpp | 19 ++++++++++++++----- src/test/util/setup_common.h | 8 +++++++- 4 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 59ed403e5067..cc45a34c8ca8 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -148,11 +148,7 @@ 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, /*banman=*/nullptr, *m_node.dstxman, - *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, - /*active_ctx=*/nullptr, /*cj_walletman=*/nullptr, m_node.llmq_ctx, - /*ignore_incoming_txs=*/false); + auto peerLogic = MakePeerManager(*connman, m_node, /*banman=*/nullptr, /*mn_activeman=*/nullptr, chainparams, /*ignore_incoming_txs=*/false); constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS; CConnman::Options options; @@ -253,11 +249,7 @@ 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, /*banman=*/nullptr, *m_node.dstxman, - *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, - /*active_ctx=*/nullptr, /*cj_walletman=*/nullptr, m_node.llmq_ctx, - /*ignore_incoming_txs=*/false); + auto peerLogic = MakePeerManager(*connman, m_node, /*banman=*/nullptr, /*mn_activeman=*/nullptr, chainparams, /*ignore_incoming_txs=*/false); constexpr int max_outbound_block_relay{MAX_BLOCK_RELAY_ONLY_CONNECTIONS}; constexpr int64_t MINIMUM_CONNECT_TIME{30}; @@ -321,11 +313,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) const CChainParams& chainparams = Params(); auto banman = std::make_unique(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_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.dstxman, - *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, - /*active_ctx=*/nullptr, /*cj_walletman=*/nullptr, m_node.llmq_ctx, - /*ignore_incoming_txs=*/false); + auto peerLogic = MakePeerManager(*connman, m_node, banman.get(), /*mn_activeman=*/nullptr, chainparams, /*ignore_incoming_txs=*/false); CNetAddr tor_netaddr; BOOST_REQUIRE( @@ -427,11 +415,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) const CChainParams& chainparams = Params(); auto banman = std::make_unique(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_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.dstxman, - *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, - /*active_ctx=*/nullptr, /*cj_walletman=*/nullptr, m_node.llmq_ctx, - /*ignore_incoming_txs=*/false); + auto peerLogic = MakePeerManager(*connman, m_node, banman.get(), /*mn_activeman=*/nullptr, chainparams, /*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 03469be6e3a2..5c981fb2ebb1 100644 --- a/src/test/net_peer_connection_tests.cpp +++ b/src/test/net_peer_connection_tests.cpp @@ -85,11 +85,7 @@ BOOST_AUTO_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection) { const auto& chainparams = Params(); auto connman = std::make_unique(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman); - auto peerman = PeerManager::make(chainparams, *connman, *m_node.addrman, /*banman=*/nullptr, *m_node.dstxman, - *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, - /*active_ctx=*/nullptr, /*cj_walletman=*/nullptr, m_node.llmq_ctx, - /*ignore_incoming_txs=*/false); + auto peerman = MakePeerManager(*connman, m_node, /*banman=*/nullptr, /*mn_activeman=*/nullptr, chainparams, /*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 bc42cf0762f6..88a57cf2e4a1 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -127,6 +127,18 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) return os; } +std::unique_ptr MakePeerManager(CConnman& connman, + NodeContext& node, + BanMan* banman, + CActiveMasternodeManager* mn_activeman, + const CChainParams& chainparams, + bool ignore_incoming_txs) +{ + return PeerManager::make(chainparams, connman, *node.addrman, banman, *node.dstxman, *node.chainman, *node.mempool, *node.mn_metaman, + *node.mn_sync, *node.govman, *node.sporkman, mn_activeman, node.dmnman, /*active_ctx=*/nullptr, + node.cj_walletman.get(), node.llmq_ctx, ignore_incoming_txs); +} + void DashChainstateSetup(ChainstateManager& chainman, NodeContext& node, bool llmq_dbs_in_memory, @@ -374,11 +386,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.dstxman, - *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, - /*active_ctx=*/nullptr, m_node.cj_walletman.get(), m_node.llmq_ctx, - /*ignore_incoming_txs=*/false); + m_node.peerman = MakePeerManager(*m_node.connman, m_node, m_node.banman.get(), /*mn_activeman=*/nullptr, chainparams, + /*ignore_incoming_txs=*/false); { CConnman::Options options; options.m_msgproc = m_node.peerman.get(); diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index 10c7363a5095..114699d68a72 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -85,7 +85,13 @@ static inline bool InsecureRandBool() { return g_insecure_rand_ctx.randbool(); } static constexpr CAmount CENT{1000000}; -/** Initialize Dash-specific components during chainstate initialization (NodeContext-friendly aliases) */ +/** Initialize components during initialization (NodeContext-friendly aliases) */ +std::unique_ptr MakePeerManager(CConnman& connman, + node::NodeContext& node, + BanMan* banman, + CActiveMasternodeManager* mn_activeman, + const CChainParams& chainparams, + bool ignore_incoming_txs); void DashChainstateSetup(ChainstateManager& chainman, node::NodeContext& node, bool llmq_dbs_in_memory, From 9c61900af165f4f9c43d21552ce5e1856edb269d Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:35:59 +0530 Subject: [PATCH 08/12] refactor: create stub class for watch-only mode context --- src/Makefile.am | 2 ++ src/init.cpp | 20 ++++++++++++++---- src/llmq/observer/context.cpp | 17 ++++++++++++++++ src/llmq/observer/context.h | 27 ++++++++++++++++++++++++ src/net_processing.cpp | 34 ++++++++++++++++++++----------- src/net_processing.h | 8 ++++++-- src/node/context.cpp | 1 + src/node/context.h | 4 ++++ src/test/util/setup_common.cpp | 4 ++-- test/util/data/non-backported.txt | 2 ++ 10 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 src/llmq/observer/context.cpp create mode 100644 src/llmq/observer/context.h diff --git a/src/Makefile.am b/src/Makefile.am index c08753bbf3c1..8c6db62bfb0c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -285,6 +285,7 @@ BITCOIN_CORE_H = \ llmq/snapshot.h \ llmq/types.h \ llmq/utils.h \ + llmq/observer/context.h \ logging.h \ logging/timer.h \ mapport.h \ @@ -553,6 +554,7 @@ libbitcoin_node_a_SOURCES = \ llmq/signing_shares.cpp \ llmq/snapshot.cpp \ llmq/utils.cpp \ + llmq/observer/context.cpp \ mapport.cpp \ masternode/active/context.cpp \ masternode/active/notificationinterface.cpp \ diff --git a/src/init.cpp b/src/init.cpp index cc9f38c66be4..e27bbd111a76 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -94,8 +94,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -347,6 +348,10 @@ void PrepareShutdown(NodeContext& node) // CValidationInterface callbacks, flush them... GetMainSignals().FlushBackgroundCallbacks(); + if (node.observer_ctx) { + UnregisterValidationInterface(node.observer_ctx.get()); + } + if (g_active_notification_interface) { UnregisterValidationInterface(g_active_notification_interface.get()); g_active_notification_interface.reset(); @@ -363,6 +368,7 @@ void PrepareShutdown(NodeContext& node) // After all scheduled tasks have been flushed, destroy pointers // and reset all to nullptr. + node.observer_ctx.reset(); node.active_ctx.reset(); node.mn_sync.reset(); node.sporkman.reset(); @@ -2200,8 +2206,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) assert(!node.peerman); node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), *node.dstxman, chainman, *node.mempool, *node.mn_metaman, *node.mn_sync, - *node.govman, *node.sporkman, node.mn_activeman.get(), node.dmnman, - node.active_ctx, node.cj_walletman.get(), node.llmq_ctx, ignores_incoming_txs); + *node.govman, *node.sporkman, node.cj_walletman.get(), node.mn_activeman.get(), node.dmnman, + node.active_ctx, node.llmq_ctx, node.observer_ctx, ignores_incoming_txs); RegisterValidationInterface(node.peerman.get()); g_ds_notification_interface = std::make_unique( @@ -2209,11 +2215,14 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) ); RegisterValidationInterface(g_ds_notification_interface.get()); - // ********************************************************* Step 7c: Setup masternode mode + // ********************************************************* Step 7c: Setup masternode mode or watch-only mode assert(!node.active_ctx); assert(!g_active_notification_interface); + assert(!node.observer_ctx); + node.peerman->AddExtraHandler(std::make_unique(node.peerman.get(), *node.llmq_ctx->isman, *node.llmq_ctx->qman, chainman.ActiveChainstate())); node.peerman->AddExtraHandler(std::make_unique(node.peerman.get(), *node.llmq_ctx->sigman)); + if (node.mn_activeman) { std::unique_ptr cj_server = std::make_unique(node.peerman.get(), chainman, *node.connman, *node.dmnman, *node.dstxman, *node.mn_metaman, *node.mempool, *node.mn_activeman, *node.mn_sync, *node.llmq_ctx->isman); @@ -2223,6 +2232,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.peerman->AddExtraHandler(std::move(cj_server)); g_active_notification_interface = std::make_unique(*node.active_ctx, *node.mn_activeman); RegisterValidationInterface(g_active_notification_interface.get()); + } else if (quorums_watch) { + node.observer_ctx = std::make_unique(); + RegisterValidationInterface(node.observer_ctx.get()); } // ********************************************************* Step 7d: Setup other Dash services diff --git a/src/llmq/observer/context.cpp b/src/llmq/observer/context.cpp new file mode 100644 index 000000000000..f0f708e6ab25 --- /dev/null +++ b/src/llmq/observer/context.cpp @@ -0,0 +1,17 @@ +// 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 + +namespace llmq { +ObserverContext::ObserverContext() = default; + +ObserverContext::~ObserverContext() = default; + +void ObserverContext::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) +{ + if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones + return; +} +} // namespace llmq diff --git a/src/llmq/observer/context.h b/src/llmq/observer/context.h new file mode 100644 index 000000000000..4c915b38e420 --- /dev/null +++ b/src/llmq/observer/context.h @@ -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. + +#ifndef BITCOIN_LLMQ_OBSERVER_CONTEXT_H +#define BITCOIN_LLMQ_OBSERVER_CONTEXT_H + +#include + +#include + +class CBlockIndex; + +namespace llmq { +struct ObserverContext final : public CValidationInterface { + ObserverContext(const ObserverContext&) = delete; + ObserverContext& operator=(const ObserverContext&) = delete; + ObserverContext(); + ~ObserverContext(); + +protected: + // CValidationInterface + void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override; +}; +} // namespace llmq + +#endif // BITCOIN_LLMQ_OBSERVER_CONTEXT_H diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 4e30fa097950..45beea1b7f3d 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -585,10 +586,13 @@ class PeerManagerImpl final : public PeerManager PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman, BanMan* banman, CDSTXManager& dstxman, ChainstateManager& chainman, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, - CSporkManager& sporkman, const CActiveMasternodeManager* const mn_activeman, + CSporkManager& sporkman, + CJWalletManager* const cj_walletman, + const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, - const std::unique_ptr& active_ctx, CJWalletManager* const cj_walletman, - const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); + const std::unique_ptr& active_ctx, + const std::unique_ptr& llmq_ctx, + const std::unique_ptr& observer_ctx, bool ignore_incoming_txs); ~PeerManagerImpl() { @@ -810,13 +814,15 @@ class PeerManagerImpl final : public PeerManager std::unique_ptr m_txreconciliation; const std::unique_ptr& m_dmnman; const std::unique_ptr& m_active_ctx; - /** Pointer to this node's CJWalletManager. May be nullptr - check existence before dereferencing. */ - CJWalletManager* const m_cj_walletman; const std::unique_ptr& m_llmq_ctx; + [[maybe_unused]] const std::unique_ptr& m_observer_ctx; CMasternodeMetaMan& m_mn_metaman; CMasternodeSync& m_mn_sync; CGovernanceManager& m_govman; CSporkManager& m_sporkman; + /** Pointer to this node's CJWalletManager. May be nullptr - check existence before dereferencing. */ + CJWalletManager* const m_cj_walletman; + /** Pointer to this node's CActiveMasternodeManager. May be nullptr - check existence before dereferencing. */ const CActiveMasternodeManager* const m_mn_activeman; /** The height of the best chain */ @@ -2041,23 +2047,26 @@ std::unique_ptr PeerManager::make(const CChainParams& chainparams, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, + CJWalletManager* const cj_walletman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, const std::unique_ptr& active_ctx, - CJWalletManager* const cj_walletman, - const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) + const std::unique_ptr& llmq_ctx, + const std::unique_ptr& observer_ctx, bool ignore_incoming_txs) { - return std::make_unique(chainparams, connman, addrman, banman, dstxman, chainman, pool, mn_metaman, mn_sync, govman, sporkman, mn_activeman, dmnman, active_ctx, cj_walletman, llmq_ctx, ignore_incoming_txs); + return std::make_unique(chainparams, connman, addrman, banman, dstxman, chainman, pool, mn_metaman, mn_sync, govman, sporkman, cj_walletman, mn_activeman, dmnman, active_ctx, llmq_ctx, observer_ctx, ignore_incoming_txs); } PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman, BanMan* banman, CDSTXManager& dstxman, ChainstateManager& chainman, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, - CSporkManager& sporkman, const CActiveMasternodeManager* const mn_activeman, + CSporkManager& sporkman, + CJWalletManager* const cj_walletman, + const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, const std::unique_ptr& active_ctx, - CJWalletManager* const cj_walletman, - const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) + const std::unique_ptr& llmq_ctx, + const std::unique_ptr& observer_ctx, bool ignore_incoming_txs) : m_chainparams(chainparams), m_connman(connman), m_addrman(addrman), @@ -2067,12 +2076,13 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn m_mempool(pool), m_dmnman(dmnman), m_active_ctx(active_ctx), - m_cj_walletman(cj_walletman), m_llmq_ctx(llmq_ctx), + m_observer_ctx(observer_ctx), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), m_govman(govman), m_sporkman(sporkman), + m_cj_walletman(cj_walletman), m_mn_activeman(mn_activeman), m_ignore_incoming_txs(ignore_incoming_txs) { diff --git a/src/net_processing.h b/src/net_processing.h index 0d8128e04bcc..4c730d07d335 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -31,6 +31,9 @@ class CTransaction; class CTxMemPool; struct ActiveContext; struct LLMQContext; +namespace llmq { +struct ObserverContext; +} // namespace llmq /** Default for -maxorphantxsize, maximum size in megabytes the orphan map can grow before entries are removed */ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS_SIZE = 10; // this allows around 100 TXs of max size (and many more of normal size) @@ -103,11 +106,12 @@ class PeerManager : public CValidationInterface, public NetEventsInterface, publ BanMan* banman, CDSTXManager& dstxman, ChainstateManager& chainman, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, + CJWalletManager* const cj_walletman, const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& dmnman, const std::unique_ptr& active_ctx, - CJWalletManager* const cj_walletman, - const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs); + const std::unique_ptr& llmq_ctx, + const std::unique_ptr& observer_ctx, bool ignore_incoming_txs); virtual ~PeerManager() { } /** diff --git a/src/node/context.cpp b/src/node/context.cpp index a13ef83414e1..1afbb9586849 100644 --- a/src/node/context.cpp +++ b/src/node/context.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/src/node/context.h b/src/node/context.h index 15845e6ce2ce..57710d75ba67 100644 --- a/src/node/context.h +++ b/src/node/context.h @@ -35,6 +35,9 @@ class NetGroupManager; class PeerManager; struct ActiveContext; struct LLMQContext; +namespace llmq { +struct ObserverContext; +} // namespace llmq namespace interfaces { class Chain; @@ -95,6 +98,7 @@ struct NodeContext { //! Dash contexts std::unique_ptr active_ctx; std::unique_ptr llmq_ctx; + std::unique_ptr observer_ctx; //! Declare default constructor and destructor that are not inline, so code //! instantiating the NodeContext struct doesn't need to #include class diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 88a57cf2e4a1..695c71c4f3a8 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -135,8 +135,8 @@ std::unique_ptr MakePeerManager(CConnman& connman, bool ignore_incoming_txs) { return PeerManager::make(chainparams, connman, *node.addrman, banman, *node.dstxman, *node.chainman, *node.mempool, *node.mn_metaman, - *node.mn_sync, *node.govman, *node.sporkman, mn_activeman, node.dmnman, /*active_ctx=*/nullptr, - node.cj_walletman.get(), node.llmq_ctx, ignore_incoming_txs); + *node.mn_sync, *node.govman, *node.sporkman, node.cj_walletman.get(), mn_activeman, node.dmnman, + node.active_ctx, node.llmq_ctx, node.observer_ctx, ignore_incoming_txs); } void DashChainstateSetup(ChainstateManager& chainman, diff --git a/test/util/data/non-backported.txt b/test/util/data/non-backported.txt index eaa118ca8fca..9c3fd211f628 100644 --- a/test/util/data/non-backported.txt +++ b/test/util/data/non-backported.txt @@ -20,6 +20,8 @@ src/instantsend/*.cpp src/instantsend/*.h src/llmq/*.cpp src/llmq/*.h +src/llmq/observer/*.cpp +src/llmq/observer/*.h src/masternode/*.cpp src/masternode/*.h src/masternode/active/*.cpp From dac4769fc6a6e0ef28a53d6c8038db2f735702d5 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 9 Dec 2025 05:08:32 +0530 Subject: [PATCH 09/12] refactor: move `CDKGSessionManager` to `{Active,Observer}Context` --- src/dsnotificationinterface.cpp | 1 - src/init.cpp | 15 +++++--- src/llmq/context.cpp | 15 ++------ src/llmq/context.h | 13 ++----- src/llmq/dkgsessionmgr.cpp | 5 --- src/llmq/observer/context.cpp | 23 +++++++++++- src/llmq/observer/context.h | 28 +++++++++++++- src/masternode/active/context.cpp | 20 ++++++---- src/masternode/active/context.h | 15 ++++++-- .../active/notificationinterface.cpp | 2 + src/net_processing.cpp | 37 ++++++++++++++----- src/node/chainstate.cpp | 3 +- 12 files changed, 120 insertions(+), 57 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 830da58fb847..ff5e1cf9d4e9 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -78,7 +78,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con m_llmq_ctx->isman->UpdatedBlockTip(pindexNew); m_llmq_ctx->clhandler->UpdatedBlockTip(*m_llmq_ctx->isman); - m_llmq_ctx->qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload); m_llmq_ctx->qman->UpdatedBlockTip(pindexNew, m_connman, fInitialDownload); if (m_govman.IsValid()) { diff --git a/src/init.cpp b/src/init.cpp index e27bbd111a76..63d1362b69df 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2223,17 +2223,20 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.peerman->AddExtraHandler(std::make_unique(node.peerman.get(), *node.llmq_ctx->isman, *node.llmq_ctx->qman, chainman.ActiveChainstate())); node.peerman->AddExtraHandler(std::make_unique(node.peerman.get(), *node.llmq_ctx->sigman)); + const util::DbWrapperParams dash_db_params{.path = args.GetDataDirNet(), .memory = false, .wipe = (fReindex || fReindexChainState)}; if (node.mn_activeman) { - std::unique_ptr cj_server = std::make_unique(node.peerman.get(), chainman, *node.connman, *node.dmnman, *node.dstxman, *node.mn_metaman, *node.mempool, *node.mn_activeman, *node.mn_sync, *node.llmq_ctx->isman); - - node.active_ctx = std::make_unique(chainman, *node.connman, *node.dmnman, *node.govman, + auto cj_server = std::make_unique(node.peerman.get(), chainman, *node.connman, *node.dmnman, *node.dstxman, *node.mn_metaman, + *node.mempool, *node.mn_activeman, *node.mn_sync, *node.llmq_ctx->isman); + node.active_ctx = std::make_unique(*cj_server, *node.connman, *node.dmnman, *node.govman, chainman, *node.mn_metaman, *node.mnhf_manager, *node.sporkman, *node.mempool, *node.llmq_ctx, *node.peerman, - *node.mn_activeman, *node.mn_sync, *cj_server); + *node.mn_activeman, *node.mn_sync, dash_db_params, quorums_watch); node.peerman->AddExtraHandler(std::move(cj_server)); g_active_notification_interface = std::make_unique(*node.active_ctx, *node.mn_activeman); RegisterValidationInterface(g_active_notification_interface.get()); } else if (quorums_watch) { - node.observer_ctx = std::make_unique(); + node.observer_ctx = std::make_unique(*node.llmq_ctx->bls_worker, *node.dmnman, *node.mn_metaman, *node.llmq_ctx->dkg_debugman, + *node.llmq_ctx->quorum_block_processor, *node.llmq_ctx->qman, *node.llmq_ctx->qsnapman, chainman, + *node.sporkman, dash_db_params); RegisterValidationInterface(node.observer_ctx.get()); } @@ -2342,7 +2345,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.peerman->ScheduleHandlers(*node.scheduler); if (node.mn_activeman) { - node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.llmq_ctx->qdkgsman)), std::chrono::hours{1}); + node.scheduler->scheduleEvery(std::bind(&llmq::CDKGSessionManager::CleanupOldContributions, std::ref(*node.active_ctx->qdkgsman)), std::chrono::hours{1}); } if (node.cj_walletman) { diff --git a/src/llmq/context.cpp b/src/llmq/context.cpp index 76334c409332..309f874fc21f 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -9,26 +9,21 @@ #include #include #include -#include #include #include #include #include LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, - CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, - CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch, - int8_t bls_threads, int64_t max_recsigs_age) : + CSporkManager& sporkman, CTxMemPool& mempool, + const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, + const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params, + bool quorums_recovery, bool quorums_watch, int8_t bls_threads, int64_t max_recsigs_age) : bls_worker{std::make_shared()}, dkg_debugman{std::make_unique()}, qsnapman{std::make_unique(evo_db)}, quorum_block_processor{std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db, *qsnapman, bls_threads)}, - qdkgsman{std::make_unique(*bls_worker, dmnman, *dkg_debugman, mn_metaman, - *quorum_block_processor, *qsnapman, mn_activeman, chainman, - sporkman, db_params, quorums_watch)}, qman{std::make_unique(*bls_worker, dmnman, evo_db, *quorum_block_processor, *qsnapman, mn_activeman, chainman, mn_sync, sporkman, sync_map, db_params, quorums_recovery, quorums_watch)}, @@ -39,12 +34,10 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d { // Have to start it early to let VerifyDB check ChainLock signatures in coinbase bls_worker->Start(); - qman->ConnectManager(qdkgsman.get()); } LLMQContext::~LLMQContext() { - qman->DisconnectManager(); bls_worker->Stop(); } diff --git a/src/llmq/context.h b/src/llmq/context.h index 653dfdc1fc2f..a0cea150b1ee 100644 --- a/src/llmq/context.h +++ b/src/llmq/context.h @@ -14,9 +14,7 @@ class CBLSWorker; class ChainstateManager; class CDeterministicMNManager; class CEvoDB; -class CMasternodeMetaMan; class CMasternodeSync; -class CMNHFManager; class CSporkManager; class CTxMemPool; class PeerManager; @@ -24,7 +22,6 @@ class PeerManager; namespace llmq { class CChainLocksHandler; class CDKGDebugManager; -class CDKGSessionManager; class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; @@ -41,11 +38,10 @@ struct LLMQContext { LLMQContext(const LLMQContext&) = delete; LLMQContext& operator=(const LLMQContext&) = delete; explicit LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& dmnman, CEvoDB& evo_db, - CMasternodeMetaMan& mn_metaman, CMNHFManager& mnhfman, CSporkManager& sporkman, - CTxMemPool& mempool, const CActiveMasternodeManager* const mn_activeman, - const CMasternodeSync& mn_sync, const llmq::QvvecSyncModeMap& sync_map, - const util::DbWrapperParams& db_params, bool quorums_recovery, bool quorums_watch, - int8_t bls_threads, int64_t max_recsigs_age); + CSporkManager& sporkman, CTxMemPool& mempool, + const CActiveMasternodeManager* const mn_activeman, const CMasternodeSync& mn_sync, + const llmq::QvvecSyncModeMap& sync_map, const util::DbWrapperParams& db_params, + bool quorums_recovery, bool quorums_watch, int8_t bls_threads, int64_t max_recsigs_age); ~LLMQContext(); void Start(); @@ -65,7 +61,6 @@ struct LLMQContext { const std::unique_ptr dkg_debugman; const std::unique_ptr qsnapman; const std::unique_ptr quorum_block_processor; - const std::unique_ptr qdkgsman; const std::unique_ptr qman; const std::unique_ptr sigman; const std::unique_ptr clhandler; diff --git a/src/llmq/dkgsessionmgr.cpp b/src/llmq/dkgsessionmgr.cpp index 2c70e1aa21f3..6303a41184a3 100644 --- a/src/llmq/dkgsessionmgr.cpp +++ b/src/llmq/dkgsessionmgr.cpp @@ -45,11 +45,6 @@ CDKGSessionManager::CDKGSessionManager(CBLSWorker& _blsWorker, CDeterministicMNM spork_manager{sporkman}, m_quorums_watch{quorums_watch} { - if (mn_activeman == nullptr && !m_quorums_watch) { - // Regular nodes do not care about any DKG internals, bail out - return; - } - const Consensus::Params& consensus_params = Params().GetConsensus(); for (const auto& params : consensus_params.llmqs) { auto session_count = (params.useRotation) ? params.signingActiveQuorumCount : 1; diff --git a/src/llmq/observer/context.cpp b/src/llmq/observer/context.cpp index f0f708e6ab25..681f8f6eeaa7 100644 --- a/src/llmq/observer/context.cpp +++ b/src/llmq/observer/context.cpp @@ -4,14 +4,33 @@ #include +#include +#include + namespace llmq { -ObserverContext::ObserverContext() = default; +ObserverContext::ObserverContext(CBLSWorker& bls_worker, CDeterministicMNManager& dmnman, + CMasternodeMetaMan& mn_metaman, llmq::CDKGDebugManager& dkg_debugman, + llmq::CQuorumBlockProcessor& qblockman, llmq::CQuorumManager& qman, + llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, + const CSporkManager& sporkman, const util::DbWrapperParams& db_params) : + m_qman{qman}, + qdkgsman{std::make_unique(bls_worker, dmnman, dkg_debugman, mn_metaman, qblockman, + qsnapman, /*mn_activeman=*/nullptr, chainman, sporkman, + db_params, /*quorums_watch=*/true)} +{ + m_qman.ConnectManager(qdkgsman.get()); +} -ObserverContext::~ObserverContext() = default; +ObserverContext::~ObserverContext() +{ + m_qman.DisconnectManager(); +} void ObserverContext::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) { if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones return; + + qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload); } } // namespace llmq diff --git a/src/llmq/observer/context.h b/src/llmq/observer/context.h index 4c915b38e420..86b03d2cb128 100644 --- a/src/llmq/observer/context.h +++ b/src/llmq/observer/context.h @@ -9,18 +9,44 @@ #include +class CBLSWorker; class CBlockIndex; +class CDeterministicMNManager; +class ChainstateManager; +class CMasternodeMetaMan; +class CSporkManager; +namespace llmq { +class CDKGDebugManager; +class CDKGSessionManager; +class CQuorumBlockProcessor; +class CQuorumManager; +class CQuorumSnapshotManager; +} // namespace llmq +namespace util { +struct DbWrapperParams; +} // namespace util namespace llmq { struct ObserverContext final : public CValidationInterface { +private: + llmq::CQuorumManager& m_qman; + +public: + ObserverContext() = delete; ObserverContext(const ObserverContext&) = delete; ObserverContext& operator=(const ObserverContext&) = delete; - ObserverContext(); + ObserverContext(CBLSWorker& bls_worker, CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman, + llmq::CDKGDebugManager& dkg_debugman, llmq::CQuorumBlockProcessor& qblockman, + llmq::CQuorumManager& qman, llmq::CQuorumSnapshotManager& qsnapman, const ChainstateManager& chainman, + const CSporkManager& sporkman, const util::DbWrapperParams& db_params); ~ObserverContext(); protected: // CValidationInterface void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override; + +public: + const std::unique_ptr qdkgsman; }; } // namespace llmq diff --git a/src/masternode/active/context.cpp b/src/masternode/active/context.cpp index f97a86510772..d737e3b74567 100644 --- a/src/masternode/active/context.cpp +++ b/src/masternode/active/context.cpp @@ -13,17 +13,21 @@ #include #include #include +#include #include #include -ActiveContext::ActiveContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, - CGovernanceManager& govman, CMNHFManager& mnhfman, CSporkManager& sporkman, - CTxMemPool& mempool, LLMQContext& llmq_ctx, PeerManager& peerman, - const CActiveMasternodeManager& mn_activeman, const CMasternodeSync& mn_sync, - CCoinJoinServer& cj_server) : +ActiveContext::ActiveContext(CCoinJoinServer& cj_server, CConnman& connman, CDeterministicMNManager& dmnman, + CGovernanceManager& govman, ChainstateManager& chainman, CMasternodeMetaMan& mn_metaman, + CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, LLMQContext& llmq_ctx, + PeerManager& peerman, const CActiveMasternodeManager& mn_activeman, + const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_watch) : m_llmq_ctx{llmq_ctx}, m_cj_server(cj_server), gov_signer{std::make_unique(connman, dmnman, govman, mn_activeman, chainman, mn_sync)}, + qdkgsman{std::make_unique(*llmq_ctx.bls_worker, dmnman, *llmq_ctx.dkg_debugman, + mn_metaman, *llmq_ctx.quorum_block_processor, *llmq_ctx.qsnapman, + &mn_activeman, chainman, sporkman, db_params, quorums_watch)}, shareman{std::make_unique(connman, chainman.ActiveChainstate(), *llmq_ctx.sigman, peerman, mn_activeman, *llmq_ctx.qman, sporkman)}, ehf_sighandler{ @@ -36,10 +40,12 @@ ActiveContext::ActiveContext(ChainstateManager& chainman, CConnman& connman, CDe { m_llmq_ctx.clhandler->ConnectSigner(cl_signer.get()); m_llmq_ctx.isman->ConnectSigner(is_signer.get()); + m_llmq_ctx.qman->ConnectManager(qdkgsman.get()); } ActiveContext::~ActiveContext() { + m_llmq_ctx.qman->DisconnectManager(); m_llmq_ctx.isman->DisconnectSigner(); m_llmq_ctx.clhandler->DisconnectSigner(); } @@ -51,7 +57,7 @@ void ActiveContext::Interrupt() void ActiveContext::Start(CConnman& connman, PeerManager& peerman) { - m_llmq_ctx.qdkgsman->StartThreads(connman, peerman); + qdkgsman->StartThreads(connman, peerman); shareman->Start(); cl_signer->RegisterRecoveryInterface(); is_signer->RegisterRecoveryInterface(); @@ -64,5 +70,5 @@ void ActiveContext::Stop() is_signer->UnregisterRecoveryInterface(); cl_signer->UnregisterRecoveryInterface(); shareman->Stop(); - m_llmq_ctx.qdkgsman->StopThreads(); + qdkgsman->StopThreads(); } diff --git a/src/masternode/active/context.h b/src/masternode/active/context.h index 1d7c253a1da5..c330730ace6f 100644 --- a/src/masternode/active/context.h +++ b/src/masternode/active/context.h @@ -13,6 +13,7 @@ class CCoinJoinServer; class CConnman; class CDeterministicMNManager; class CGovernanceManager; +class CMasternodeMetaMan; class CMasternodeSync; class CMNHFManager; class CSporkManager; @@ -27,9 +28,13 @@ namespace instantsend { class InstantSendSigner; } // namespace instantsend namespace llmq { +class CDKGSessionManager; class CEHFSignalsHandler; class CSigSharesManager; } // namespace llmq +namespace util { +struct DbWrapperParams; +} // namespace util struct ActiveContext { private: @@ -40,10 +45,11 @@ struct ActiveContext { ActiveContext() = delete; ActiveContext(const ActiveContext&) = delete; ActiveContext& operator=(const ActiveContext&) = delete; - explicit ActiveContext(ChainstateManager& chainman, CConnman& connman, CDeterministicMNManager& dmnman, - CGovernanceManager& govman, CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, - LLMQContext& llmq_ctx, PeerManager& peerman, const CActiveMasternodeManager& mn_activeman, - const CMasternodeSync& mn_sync, CCoinJoinServer& cj_server); + explicit ActiveContext(CCoinJoinServer& cj_server, CConnman& connman, CDeterministicMNManager& dmnman, + CGovernanceManager& govman, ChainstateManager& chainman, CMasternodeMetaMan& mn_metaman, + CMNHFManager& mnhfman, CSporkManager& sporkman, CTxMemPool& mempool, LLMQContext& llmq_ctx, + PeerManager& peerman, const CActiveMasternodeManager& mn_activeman, + const CMasternodeSync& mn_sync, const util::DbWrapperParams& db_params, bool quorums_watch); ~ActiveContext(); void Interrupt(); @@ -57,6 +63,7 @@ struct ActiveContext { */ CCoinJoinServer& m_cj_server; const std::unique_ptr gov_signer; + const std::unique_ptr qdkgsman; const std::unique_ptr shareman; const std::unique_ptr ehf_sighandler; diff --git a/src/masternode/active/notificationinterface.cpp b/src/masternode/active/notificationinterface.cpp index 126ba167940b..d9904f496b99 100644 --- a/src/masternode/active/notificationinterface.cpp +++ b/src/masternode/active/notificationinterface.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ void ActiveNotificationInterface::UpdatedBlockTip(const CBlockIndex* pindexNew, m_mn_activeman.UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); m_active_ctx.ehf_sighandler->UpdatedBlockTip(pindexNew); m_active_ctx.gov_signer->UpdatedBlockTip(pindexNew); + m_active_ctx.qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload); } void ActiveNotificationInterface::NotifyRecoveredSig(const std::shared_ptr& sig, bool proactive_relay) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 45beea1b7f3d..0dbdf3efd174 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -815,7 +815,7 @@ class PeerManagerImpl final : public PeerManager const std::unique_ptr& m_dmnman; const std::unique_ptr& m_active_ctx; const std::unique_ptr& m_llmq_ctx; - [[maybe_unused]] const std::unique_ptr& m_observer_ctx; + const std::unique_ptr& m_observer_ctx; CMasternodeMetaMan& m_mn_metaman; CMasternodeSync& m_mn_sync; CGovernanceManager& m_govman; @@ -2358,7 +2358,8 @@ bool PeerManagerImpl::AlreadyHave(const CInv& inv) case MSG_QUORUM_COMPLAINT: case MSG_QUORUM_JUSTIFICATION: case MSG_QUORUM_PREMATURE_COMMITMENT: - return m_llmq_ctx->qdkgsman->AlreadyHave(inv); + return (m_observer_ctx && m_observer_ctx->qdkgsman->AlreadyHave(inv)) + || (m_active_ctx && m_active_ctx->qdkgsman->AlreadyHave(inv)); case MSG_QUORUM_RECOVERED_SIG: // TODO: move it to NetSigning return m_llmq_ctx->sigman->AlreadyHave(inv); @@ -2373,7 +2374,6 @@ bool PeerManagerImpl::AlreadyHave(const CInv& inv) // At the end inventories that are handled by NetHandler case MSG_DSQ: if (m_cj_walletman && m_cj_walletman->hasQueue(inv.hash)) return true; - for (const auto& handler : m_handlers) { if (handler->AlreadyHave(inv)) return true; } @@ -2938,7 +2938,8 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic if (!push && (inv.type == MSG_QUORUM_CONTRIB)) { llmq::CDKGContribution o; - if (m_llmq_ctx->qdkgsman->GetContribution(inv.hash, o)) { + if ((m_observer_ctx && m_observer_ctx->qdkgsman->GetContribution(inv.hash, o)) + || (m_active_ctx && m_active_ctx->qdkgsman->GetContribution(inv.hash, o))) { m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::QCONTRIB, o)); push = true; } @@ -2946,7 +2947,8 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic if (!push && (inv.type == MSG_QUORUM_COMPLAINT)) { llmq::CDKGComplaint o; - if (m_llmq_ctx->qdkgsman->GetComplaint(inv.hash, o)) { + if ((m_observer_ctx && m_observer_ctx->qdkgsman->GetComplaint(inv.hash, o)) + || (m_active_ctx && m_active_ctx->qdkgsman->GetComplaint(inv.hash, o))) { m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::QCOMPLAINT, o)); push = true; } @@ -2954,7 +2956,8 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic if (!push && (inv.type == MSG_QUORUM_JUSTIFICATION)) { llmq::CDKGJustification o; - if (m_llmq_ctx->qdkgsman->GetJustification(inv.hash, o)) { + if ((m_observer_ctx && m_observer_ctx->qdkgsman->GetJustification(inv.hash, o)) + || (m_active_ctx && m_active_ctx->qdkgsman->GetJustification(inv.hash, o))) { m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::QJUSTIFICATION, o)); push = true; } @@ -2962,7 +2965,8 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic if (!push && (inv.type == MSG_QUORUM_PREMATURE_COMMITMENT)) { llmq::CDKGPrematureCommitment o; - if (m_llmq_ctx->qdkgsman->GetPrematureCommitment(inv.hash, o)) { + if ((m_observer_ctx && m_observer_ctx->qdkgsman->GetPrematureCommitment(inv.hash, o)) + || (m_active_ctx && m_active_ctx->qdkgsman->GetPrematureCommitment(inv.hash, o))) { m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::QPCOMMITMENT, o)); push = true; } @@ -5456,17 +5460,32 @@ void PeerManagerImpl::ProcessMessage( if (found) { - //probably one the extensions + // probably one the extensions if (m_cj_walletman) { PostProcessMessage(m_cj_walletman->processMessage(pfrom, m_chainman.ActiveChainstate(), m_connman, m_mempool, msg_type, vRecv), pfrom.GetId()); } if (m_active_ctx) { + assert(is_masternode); m_active_ctx->shareman->ProcessMessage(pfrom, msg_type, vRecv); + PostProcessMessage(m_active_ctx->qdkgsman->ProcessMessage(pfrom, is_masternode, msg_type, vRecv), pfrom.GetId()); + } + if (m_observer_ctx) { + assert(!is_masternode); + PostProcessMessage(m_observer_ctx->qdkgsman->ProcessMessage(pfrom, is_masternode, msg_type, vRecv), pfrom.GetId()); + } + if (!m_active_ctx && !m_observer_ctx) { + assert(!is_masternode); + if (msg_type == NetMsgType::QCONTRIB + || msg_type == NetMsgType::QCOMPLAINT + || msg_type == NetMsgType::QJUSTIFICATION + || msg_type == NetMsgType::QPCOMMITMENT + || msg_type == NetMsgType::QWATCH) { + Misbehaving(pfrom.GetId(), /*howmuch=*/10); + } } PostProcessMessage(m_sporkman.ProcessMessage(pfrom, m_connman, msg_type, vRecv), pfrom.GetId()); PostProcessMessage(CMNAuth::ProcessMessage(pfrom, peer->m_their_services, m_connman, m_mn_metaman, m_mn_activeman, m_mn_sync, m_dmnman->GetListAtChainTip(), msg_type, vRecv), pfrom.GetId()); PostProcessMessage(m_llmq_ctx->quorum_block_processor->ProcessMessage(pfrom, msg_type, vRecv), pfrom.GetId()); - PostProcessMessage(m_llmq_ctx->qdkgsman->ProcessMessage(pfrom, is_masternode, msg_type, vRecv), pfrom.GetId()); PostProcessMessage(m_llmq_ctx->qman->ProcessMessage(pfrom, m_connman, msg_type, vRecv), pfrom.GetId()); PostProcessMessage(ProcessPlatformBanMessage(pfrom.GetId(), msg_type, vRecv), pfrom.GetId()); diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index b045a7a568ae..9c2dbe91d39b 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -248,8 +248,7 @@ void DashChainstateSetup(ChainstateManager& chainman, llmq_ctx->Stop(); } llmq_ctx.reset(); - llmq_ctx = std::make_unique(chainman, *dmnman, *evodb, mn_metaman, *mnhf_manager, sporkman, - *mempool, mn_activeman.get(), mn_sync, sync_map, + llmq_ctx = std::make_unique(chainman, *dmnman, *evodb, sporkman, *mempool, mn_activeman.get(), mn_sync, sync_map, util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, quorums_recovery, quorums_watch, bls_threads, max_recsigs_age); mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); From 8f8078fab89d54690d521c4a3426d6411a83eff5 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 9 Dec 2025 21:40:48 +0530 Subject: [PATCH 10/12] refactor: initialize `CJWalletManager` after `ActiveContext` Needed when `CActiveMasternodeManager` is moved to `ActiveContext` --- src/init.cpp | 24 +++++++++++++----------- src/net_processing.cpp | 23 +++++++++++------------ src/net_processing.h | 4 ++-- src/test/util/setup_common.cpp | 4 ++-- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 63d1362b69df..9fe17a0bf06c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2194,20 +2194,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) assert(!node.dstxman); node.dstxman = std::make_unique(); - assert(!node.cj_walletman); - if (!node.mn_activeman) { - node.cj_walletman = CJWalletManager::make(chainman, *node.dmnman, *node.mn_metaman, *node.mempool, *node.mn_sync, - *node.llmq_ctx->isman, !ignores_incoming_txs); - } - if (node.cj_walletman) { - RegisterValidationInterface(node.cj_walletman.get()); - } - assert(!node.peerman); node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), *node.dstxman, chainman, *node.mempool, *node.mn_metaman, *node.mn_sync, - *node.govman, *node.sporkman, node.cj_walletman.get(), node.mn_activeman.get(), node.dmnman, - node.active_ctx, node.llmq_ctx, node.observer_ctx, ignores_incoming_txs); + *node.govman, *node.sporkman, node.mn_activeman.get(), node.active_ctx, node.dmnman, + node.cj_walletman, node.llmq_ctx, node.observer_ctx, ignores_incoming_txs); RegisterValidationInterface(node.peerman.get()); g_ds_notification_interface = std::make_unique( @@ -2242,6 +2233,17 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // ********************************************************* Step 7d: Setup other Dash services + assert(!node.cj_walletman); + if (!node.active_ctx) { + // Can return nullptr if built without wallet support, must check before use + node.cj_walletman = CJWalletManager::make(chainman, *node.dmnman, *node.mn_metaman, *node.mempool, *node.mn_sync, + *node.llmq_ctx->isman, !ignores_incoming_txs); + } + + if (node.cj_walletman) { + RegisterValidationInterface(node.cj_walletman.get()); + } + bool fLoadCacheFiles = !(fReindex || fReindexChainState) && (chainman.ActiveChain().Tip() != nullptr); if (!node.netfulfilledman->LoadCache(fLoadCacheFiles)) { diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 0dbdf3efd174..5a43dede1499 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -587,10 +587,10 @@ class PeerManagerImpl final : public PeerManager CDSTXManager& dstxman, ChainstateManager& chainman, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, - CJWalletManager* const cj_walletman, const CActiveMasternodeManager* const mn_activeman, - const std::unique_ptr& dmnman, const std::unique_ptr& active_ctx, + const std::unique_ptr& dmnman, + const std::unique_ptr& cj_walletman, const std::unique_ptr& llmq_ctx, const std::unique_ptr& observer_ctx, bool ignore_incoming_txs); @@ -812,16 +812,15 @@ class PeerManagerImpl final : public PeerManager ChainstateManager& m_chainman; 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_dmnman; + const std::unique_ptr& m_cj_walletman; const std::unique_ptr& m_llmq_ctx; const std::unique_ptr& m_observer_ctx; CMasternodeMetaMan& m_mn_metaman; CMasternodeSync& m_mn_sync; CGovernanceManager& m_govman; CSporkManager& m_sporkman; - /** Pointer to this node's CJWalletManager. May be nullptr - check existence before dereferencing. */ - CJWalletManager* const m_cj_walletman; /** Pointer to this node's CActiveMasternodeManager. May be nullptr - check existence before dereferencing. */ const CActiveMasternodeManager* const m_mn_activeman; @@ -2047,24 +2046,24 @@ std::unique_ptr PeerManager::make(const CChainParams& chainparams, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, - CJWalletManager* const cj_walletman, const CActiveMasternodeManager* const mn_activeman, - const std::unique_ptr& dmnman, const std::unique_ptr& active_ctx, + const std::unique_ptr& dmnman, + const std::unique_ptr& cj_walletman, const std::unique_ptr& llmq_ctx, const std::unique_ptr& observer_ctx, bool ignore_incoming_txs) { - return std::make_unique(chainparams, connman, addrman, banman, dstxman, chainman, pool, mn_metaman, mn_sync, govman, sporkman, cj_walletman, mn_activeman, dmnman, active_ctx, llmq_ctx, observer_ctx, ignore_incoming_txs); + return std::make_unique(chainparams, connman, addrman, banman, dstxman, chainman, pool, mn_metaman, mn_sync, govman, sporkman, mn_activeman, active_ctx, dmnman, cj_walletman, llmq_ctx, observer_ctx, ignore_incoming_txs); } PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, AddrMan& addrman, BanMan* banman, CDSTXManager& dstxman, ChainstateManager& chainman, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, - CJWalletManager* const cj_walletman, const CActiveMasternodeManager* const mn_activeman, - const std::unique_ptr& dmnman, const std::unique_ptr& active_ctx, + const std::unique_ptr& dmnman, + const std::unique_ptr& cj_walletman, const std::unique_ptr& llmq_ctx, const std::unique_ptr& observer_ctx, bool ignore_incoming_txs) : m_chainparams(chainparams), @@ -2074,15 +2073,15 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn m_dstxman(dstxman), m_chainman(chainman), m_mempool(pool), - m_dmnman(dmnman), m_active_ctx(active_ctx), + m_dmnman(dmnman), + m_cj_walletman(cj_walletman), m_llmq_ctx(llmq_ctx), m_observer_ctx(observer_ctx), m_mn_metaman(mn_metaman), m_mn_sync(mn_sync), m_govman(govman), m_sporkman(sporkman), - m_cj_walletman(cj_walletman), m_mn_activeman(mn_activeman), m_ignore_incoming_txs(ignore_incoming_txs) { diff --git a/src/net_processing.h b/src/net_processing.h index 4c730d07d335..ef10b01b4233 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -106,10 +106,10 @@ class PeerManager : public CValidationInterface, public NetEventsInterface, publ BanMan* banman, CDSTXManager& dstxman, ChainstateManager& chainman, CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, - CJWalletManager* const cj_walletman, const CActiveMasternodeManager* const mn_activeman, - const std::unique_ptr& dmnman, const std::unique_ptr& active_ctx, + const std::unique_ptr& dmnman, + const std::unique_ptr& cj_walletman, const std::unique_ptr& llmq_ctx, const std::unique_ptr& observer_ctx, bool ignore_incoming_txs); virtual ~PeerManager() { } diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 695c71c4f3a8..ec5c36eb9a62 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -135,8 +135,8 @@ std::unique_ptr MakePeerManager(CConnman& connman, bool ignore_incoming_txs) { return PeerManager::make(chainparams, connman, *node.addrman, banman, *node.dstxman, *node.chainman, *node.mempool, *node.mn_metaman, - *node.mn_sync, *node.govman, *node.sporkman, node.cj_walletman.get(), mn_activeman, node.dmnman, - node.active_ctx, node.llmq_ctx, node.observer_ctx, ignore_incoming_txs); + *node.mn_sync, *node.govman, *node.sporkman, mn_activeman, node.active_ctx, node.dmnman, node.cj_walletman, + node.llmq_ctx, node.observer_ctx, ignore_incoming_txs); } void DashChainstateSetup(ChainstateManager& chainman, From 2c6cbc91eb0972695cdbe5b10ac9638896449ac7 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Tue, 9 Dec 2025 02:56:03 +0530 Subject: [PATCH 11/12] refactor: use `gsl::not_null` in `CQuorumManager` wherever possible --- src/llmq/quorums.cpp | 21 ++++++++++++--------- src/llmq/quorums.h | 13 +++++++------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 9901d3909ebe..efd432a2101c 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -251,9 +251,9 @@ void CQuorumManager::Stop() workerPool.stop(true); } -void CQuorumManager::TriggerQuorumDataRecoveryThreads(CConnman& connman, const CBlockIndex* pIndex) const +void CQuorumManager::TriggerQuorumDataRecoveryThreads(CConnman& connman, gsl::not_null pIndex) const { - if ((m_mn_activeman == nullptr && !m_quorums_watch) || !m_quorums_recovery || pIndex == nullptr) { + if ((m_mn_activeman == nullptr && !m_quorums_watch) || !m_quorums_recovery) { return; } @@ -304,6 +304,7 @@ void CQuorumManager::TriggerQuorumDataRecoveryThreads(CConnman& connman, const C void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, CConnman& connman, bool fInitialDownload) const { + if (!pindexNew) return; if (!m_mn_sync.IsBlockchainSynced()) return; for (const auto& params : Params().GetConsensus().llmqs) { @@ -328,7 +329,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, CConnman& con } void CQuorumManager::CheckQuorumConnections(CConnman& connman, const Consensus::LLMQParams& llmqParams, - const CBlockIndex* pindexNew) const + gsl::not_null pindexNew) const { if (m_mn_activeman == nullptr && !m_quorums_watch) return; @@ -530,9 +531,11 @@ std::vector CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp return ScanQuorums(llmqType, pindex, nCountRequested); } -std::vector CQuorumManager::ScanQuorums(Consensus::LLMQType llmqType, const CBlockIndex* pindexStart, size_t nCountRequested) const +std::vector CQuorumManager::ScanQuorums(Consensus::LLMQType llmqType, + gsl::not_null pindexStart, + size_t nCountRequested) const { - if (pindexStart == nullptr || nCountRequested == 0 || !m_chainman.IsQuorumTypeEnabled(llmqType, pindexStart)) { + if (nCountRequested == 0 || !m_chainman.IsQuorumTypeEnabled(llmqType, pindexStart)) { return {}; } @@ -679,7 +682,7 @@ CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, gsl::not_nul return BuildQuorumFromCommitment(llmqType, pQuorumBaseBlockIndex, populate_cache); } -size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorum& quorum, const CBlockIndex* pIndex) const +size_t CQuorumManager::GetQuorumRecoveryStartOffset(const CQuorum& quorum, gsl::not_null pIndex) const { assert(m_mn_activeman); @@ -922,7 +925,7 @@ void CQuorumManager::StartCachePopulatorThread(CQuorumCPtr pQuorum) const } void CQuorumManager::StartQuorumDataRecoveryThread(CConnman& connman, CQuorumCPtr pQuorum, - const CBlockIndex* pIndex, uint16_t nDataMaskIn) const + gsl::not_null pIndex, uint16_t nDataMaskIn) const { assert(m_mn_activeman); @@ -1091,7 +1094,7 @@ static void DataCleanupHelper(CDBWrapper& db, std::set skip_list, bool } } -void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) const +void CQuorumManager::StartCleanupOldQuorumDataThread(gsl::not_null pIndex) const { // Note: this function is CPU heavy and we don't want it to be running during DKGs. // The largest dkgMiningWindowStart for a related quorum type is 42 (LLMQ_60_75). @@ -1100,7 +1103,7 @@ void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) // window and it's better to have more room so we pick next cycle. // dkgMiningWindowStart for small quorums is 10 i.e. a safe block to start // these calculations is at height 576 + 24 * 2 + 10 = 576 + 58. - if ((m_mn_activeman == nullptr && !m_quorums_watch) || pIndex == nullptr || (pIndex->nHeight % 576 != 58)) { + if ((m_mn_activeman == nullptr && !m_quorums_watch) || (pIndex->nHeight % 576 != 58)) { return; } diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 84cc3464ea1c..81d1dcf617f4 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -292,7 +292,7 @@ class CQuorumManager void Start(); void Stop(); - void TriggerQuorumDataRecoveryThreads(CConnman& connman, const CBlockIndex* pIndex) const + void TriggerQuorumDataRecoveryThreads(CConnman& connman, gsl::not_null pIndex) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db, !cs_scan_quorums, !cs_map_quorums); void UpdatedBlockTip(const CBlockIndex* pindexNew, CConnman& connman, bool fInitialDownload) const @@ -314,7 +314,7 @@ class CQuorumManager EXCLUSIVE_LOCKS_REQUIRED(!cs_db, !cs_map_quorums, !cs_scan_quorums); // this one is cs_main-free - std::vector ScanQuorums(Consensus::LLMQType llmqType, const CBlockIndex* pindexStart, + std::vector ScanQuorums(Consensus::LLMQType llmqType, gsl::not_null pindexStart, size_t nCountRequested) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db, !cs_map_quorums, !cs_scan_quorums); @@ -322,7 +322,8 @@ class CQuorumManager private: // all private methods here are cs_main-free - void CheckQuorumConnections(CConnman& connman, const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const + void CheckQuorumConnections(CConnman& connman, const Consensus::LLMQParams& llmqParams, + gsl::not_null pindexNew) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db, !cs_scan_quorums, !cs_map_quorums); CQuorumPtr BuildQuorumFromCommitment(Consensus::LLMQType llmqType, @@ -335,13 +336,13 @@ class CQuorumManager /// Returns the start offset for the masternode with the given proTxHash. This offset is applied when picking data recovery members of a quorum's /// memberlist and is calculated based on a list of all member of all active quorums for the given llmqType in a way that each member /// should receive the same number of request if all active llmqType members requests data from one llmqType quorum. - size_t GetQuorumRecoveryStartOffset(const CQuorum& quorum, const CBlockIndex* pIndex) const; + size_t GetQuorumRecoveryStartOffset(const CQuorum& quorum, gsl::not_null pIndex) const; void StartCachePopulatorThread(CQuorumCPtr pQuorum) const; - void StartQuorumDataRecoveryThread(CConnman& connman, CQuorumCPtr pQuorum, const CBlockIndex* pIndex, + void StartQuorumDataRecoveryThread(CConnman& connman, CQuorumCPtr pQuorum, gsl::not_null pIndex, uint16_t nDataMask) const; - void StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) const; + void StartCleanupOldQuorumDataThread(gsl::not_null pIndex) const; void MigrateOldQuorumDB(CEvoDB& evoDb) const EXCLUSIVE_LOCKS_REQUIRED(!cs_db); }; From 0114f587cecb394020278fe7d69eb6b20c9b1fad Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Sat, 20 Dec 2025 16:03:02 +0530 Subject: [PATCH 12/12] fix: guard `quorumBaseBlockIndexCache` --- src/llmq/quorums.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 81d1dcf617f4..84f26d9a4f67 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -264,7 +264,8 @@ class CQuorumManager // On mainnet, we have around 62 quorums active at any point; let's cache a little more than double that to be safe. // it maps `quorum_hash` to `pindex` mutable Mutex cs_quorumBaseBlockIndexCache; - mutable Uint256LruHashMap quorumBaseBlockIndexCache; + mutable Uint256LruHashMap quorumBaseBlockIndexCache + GUARDED_BY(cs_quorumBaseBlockIndexCache); mutable ctpl::thread_pool workerPool; mutable CThreadInterrupt quorumThreadInterrupt;