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/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/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 0008b0459a5a..9fe17a0bf06c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -94,8 +94,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -258,9 +259,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(); @@ -350,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(); @@ -366,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(); @@ -1409,9 +1412,8 @@ bool AppInitParameterInteraction(const ArgsManager& args) } try { - const bool fRecoveryEnabled{llmq::QuorumDataRecoveryEnabled()}; - const bool fQuorumVvecRequestsEnabled{llmq::GetEnabledQuorumVvecSyncEntries().size() > 0}; - if (!fRecoveryEnabled && fQuorumVvecRequestsEnabled) { + 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")); } } catch (const std::invalid_argument& e) { @@ -1956,6 +1958,9 @@ 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 CacheSizes cache_sizes = CalculateCacheSizes(args, g_enabled_filter_types.size()); @@ -2023,6 +2028,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, @@ -2030,6 +2036,19 @@ 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, + /*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( @@ -2175,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.mn_activeman.get(), node.dmnman, - node.active_ctx, node.cj_walletman.get(), node.llmq_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( @@ -2196,24 +2206,44 @@ 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); - node.active_ctx = std::make_unique(chainman, *node.connman, *node.dmnman, *node.govman, + const util::DbWrapperParams dash_db_params{.path = args.GetDataDirNet(), .memory = false, .wipe = (fReindex || fReindexChainState)}; + if (node.mn_activeman) { + 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.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()); } // ********************************************************* 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)) { @@ -2307,7 +2337,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); @@ -2317,7 +2347,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/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/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 2789b46e8aa7..309f874fc21f 100644 --- a/src/llmq/context.cpp +++ b/src/llmq/context.cpp @@ -9,27 +9,25 @@ #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 util::DbWrapperParams& db_params) : + 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)}, - 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)}, - sigman{std::make_unique(*qman, db_params)}, + quorum_block_processor{std::make_unique(chainman.ActiveChainstate(), dmnman, evo_db, + *qsnapman, bls_threads)}, + 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, mempool, mn_sync, db_params)} @@ -38,14 +36,12 @@ LLMQContext::LLMQContext(ChainstateManager& chainman, CDeterministicMNManager& d bls_worker->Start(); } -LLMQContext::~LLMQContext() { +LLMQContext::~LLMQContext() +{ 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 42441e899e70..a0cea150b1ee 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; @@ -12,9 +14,7 @@ class CBLSWorker; class ChainstateManager; class CDeterministicMNManager; class CEvoDB; -class CMasternodeMetaMan; class CMasternodeSync; -class CMNHFManager; class CSporkManager; class CTxMemPool; class PeerManager; @@ -22,7 +22,6 @@ class PeerManager; namespace llmq { class CChainLocksHandler; class CDKGDebugManager; -class CDKGSessionManager; class CInstantSendManager; class CQuorumBlockProcessor; class CQuorumManager; @@ -39,13 +38,13 @@ 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 util::DbWrapperParams& db_params); + 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 Interrupt(); - void Start(PeerManager& peerman); + void Start(); void Stop(); /** Guaranteed if LLMQContext is initialized then all members are valid too @@ -62,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/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..6303a41184a3 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,13 +42,9 @@ 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()) { - // 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; @@ -56,7 +52,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 +115,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/observer/context.cpp b/src/llmq/observer/context.cpp new file mode 100644 index 000000000000..681f8f6eeaa7 --- /dev/null +++ b/src/llmq/observer/context.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2025 The Dash Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include + +namespace llmq { +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() +{ + 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 new file mode 100644 index 000000000000..86b03d2cb128 --- /dev/null +++ b/src/llmq/observer/context.h @@ -0,0 +1,53 @@ +// 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 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(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 + +#endif // BITCOIN_LLMQ_OBSERVER_CONTEXT_H diff --git a/src/llmq/options.cpp b/src/llmq/options.cpp index 3ac8fdc489ec..30d6f77b148f 100644 --- a/src/llmq/options.cpp +++ b/src/llmq/options.cpp @@ -56,21 +56,10 @@ bool IsQuorumRotationEnabled(const Consensus::LLMQParams& llmqParams, gsl::not_n return DeploymentActiveAfter(pindex->GetAncestor(cycleQuorumBaseHeight - 1), Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0024); } -bool QuorumDataRecoveryEnabled() +QvvecSyncModeMap GetEnabledQuorumVvecSyncEntries(const ArgsManager& args) { - 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; - 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 9e4e8604b5ff..41347d8f3239 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,34 +28,26 @@ 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}; - -// 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 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(); +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 8fc8c1cbc8e3..efd432a2101c 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -207,22 +207,24 @@ 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 util::DbWrapperParams& db_params) : - db{util::MakeDbWrapper( - {db_params.path / "llmq" / "quorumdb", db_params.memory, db_params.wipe, /*cache_size=*/1 << 20})}, +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}, m_chainman{chainman}, m_mn_sync{mn_sync}, - m_sporkman{sporkman} + 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})} { utils::InitQuorumsCache(mapQuorumsCache, false); quorumThreadInterrupt.reset(); @@ -249,14 +251,12 @@ 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 && !IsWatchQuorumsEnabled()) || !QuorumDataRecoveryEnabled() || pIndex == nullptr) { + if ((m_mn_activeman == nullptr && !m_quorums_watch) || !m_quorums_recovery) { 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) { @@ -277,8 +277,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()) { @@ -303,13 +304,14 @@ 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) { 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(); @@ -327,9 +329,9 @@ 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 && !IsWatchQuorumsEnabled()) return; + if (m_mn_activeman == nullptr && !m_quorums_watch) return; auto lastQuorums = ScanQuorums(llmqParams.type, pindexNew, (size_t)llmqParams.keepOldConnections); @@ -368,7 +370,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()); } @@ -449,7 +451,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; } @@ -527,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 {}; } @@ -676,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); @@ -793,7 +799,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); } @@ -804,7 +812,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"); } @@ -917,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); @@ -1086,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). @@ -1095,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 && !IsWatchQuorumsEnabled()) || 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 c18540f767d9..84f26d9a4f67 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -233,31 +234,38 @@ 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; 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}; + +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 Uint256LruHashMap quorumBaseBlockIndexCache; + mutable Mutex cs_quorumBaseBlockIndexCache; + mutable Uint256LruHashMap quorumBaseBlockIndexCache + GUARDED_BY(cs_quorumBaseBlockIndexCache); mutable ctpl::thread_pool workerPool; mutable CThreadInterrupt quorumThreadInterrupt; @@ -266,17 +274,26 @@ 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 util::DbWrapperParams& db_params); + 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(); - 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 @@ -298,13 +315,16 @@ 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); + 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 + 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, @@ -317,13 +337,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); }; 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/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/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/masternode/active/context.cpp b/src/masternode/active/context.cpp index 12575ad34462..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,12 +40,14 @@ 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.clhandler->DisconnectSigner(); + m_llmq_ctx.qman->DisconnectManager(); m_llmq_ctx.isman->DisconnectSigner(); + m_llmq_ctx.clhandler->DisconnectSigner(); } void ActiveContext::Interrupt() @@ -51,14 +57,18 @@ void ActiveContext::Interrupt() void ActiveContext::Start(CConnman& connman, PeerManager& peerman) { - m_llmq_ctx.qdkgsman->StartThreads(connman, peerman); - shareman->RegisterAsRecoveredSigsListener(); + qdkgsman->StartThreads(connman, peerman); 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(); + 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 0f5a58e6be7b..5a43dede1499 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, + const CActiveMasternodeManager* const mn_activeman, + const std::unique_ptr& active_ctx, 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& cj_walletman, + const std::unique_ptr& llmq_ctx, + const std::unique_ptr& observer_ctx, bool ignore_incoming_txs); ~PeerManagerImpl() { @@ -808,15 +812,16 @@ 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; - /** Pointer to this node's CJWalletManager. May be nullptr - check existence before dereferencing. */ - CJWalletManager* const m_cj_walletman; + 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 CActiveMasternodeManager. May be nullptr - check existence before dereferencing. */ const CActiveMasternodeManager* const m_mn_activeman; /** The height of the best chain */ @@ -2042,22 +2047,25 @@ std::unique_ptr PeerManager::make(const CChainParams& chainparams, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, 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& 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, 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, 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, const CActiveMasternodeManager* const mn_activeman, - const std::unique_ptr& dmnman, + CSporkManager& sporkman, + const CActiveMasternodeManager* const mn_activeman, const std::unique_ptr& active_ctx, - CJWalletManager* const cj_walletman, - const std::unique_ptr& llmq_ctx, bool ignore_incoming_txs) + 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), m_connman(connman), m_addrman(addrman), @@ -2065,10 +2073,11 @@ 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), @@ -2348,7 +2357,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); @@ -2363,7 +2373,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; } @@ -2928,7 +2937,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; } @@ -2936,7 +2946,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; } @@ -2944,7 +2955,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; } @@ -2952,7 +2964,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; } @@ -3999,7 +4012,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)); } } @@ -5446,17 +5459,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/net_processing.h b/src/net_processing.h index 0d8128e04bcc..ef10b01b4233 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) @@ -104,10 +107,11 @@ class PeerManager : public CValidationInterface, public NetEventsInterface, publ CTxMemPool& pool, CMasternodeMetaMan& mn_metaman, CMasternodeSync& mn_sync, CGovernanceManager& govman, CSporkManager& sporkman, 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& 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/node/chainstate.cpp b/src/node/chainstate.cpp index ba7be336acc9..9c2dbe91d39b 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, @@ -61,6 +62,10 @@ 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, + int8_t bls_threads, + int64_t max_recsigs_age, std::function shutdown_requested, std::function coins_error_cb) { @@ -87,8 +92,9 @@ 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, - /*llmq_dbs_wipe=*/fReset || fReindexChainState, consensus_params); + dmnman, evodb, mnhf_manager, llmq_ctx, mempool, data_dir, sync_map, dash_dbs_in_memory, + /*llmq_dbs_wipe=*/fReset || fReindexChainState, quorums_recovery, quorums_watch, + bls_threads, max_recsigs_age, consensus_params); if (fReset) { pblocktree->WriteReindexing(true); @@ -222,8 +228,13 @@ 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, + bool quorums_watch, + int8_t bls_threads, + int64_t max_recsigs_age, const Consensus::Params& consensus_params) { // Same logic as pblocktree @@ -234,13 +245,12 @@ void DashChainstateSetup(ChainstateManager& chainman, cpoolman = std::make_unique(*evodb, chainman); if (llmq_ctx) { - llmq_ctx->Interrupt(); 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, - util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}); + 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()); // 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..3e28d5bf0447 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, @@ -105,6 +108,10 @@ 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, + int8_t bls_threads, + int64_t max_recsigs_age, std::function shutdown_requested = nullptr, std::function coins_error_cb = nullptr); @@ -123,8 +130,13 @@ 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, + 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/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/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 62d308acb73c..ec5c36eb9a62 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -64,6 +64,8 @@ #include #include #include +#include +#include #include #include #include @@ -125,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.active_ctx, node.dmnman, node.cj_walletman, + node.llmq_ctx, node.observer_ctx, ignore_incoming_txs); +} + void DashChainstateSetup(ChainstateManager& chainman, NodeContext& node, bool llmq_dbs_in_memory, @@ -134,7 +148,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, 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) @@ -325,13 +340,18 @@ 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(); @@ -400,7 +417,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/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, diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index 270cde9a352d..5352527c1a35 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -4,15 +4,11 @@ // #include #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 @@ -70,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); @@ -120,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); 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