diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index 26a871bcda51..24eb5965c26d 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -101,32 +101,25 @@ int main(int argc, char* argv[]) std::unique_ptr llmq_ctx; std::unique_ptr chain_helper; + node::CacheSizes cache_sizes; cache_sizes.block_tree_db = 2 << 20; cache_sizes.coins_db = 2 << 22; cache_sizes.coins = (450 << 20) - (2 << 20) - (2 << 22); node::ChainstateLoadOptions options; - options.bls_threads = 1; - options.worker_count = 1; - options.max_recsigs_age = 1; + options.mn_metaman = &metaman; + options.sporkman = &sporkman; + options.chainlocks = &chainlocks; + options.mn_sync = &mn_sync; + options.data_dir = gArgs.GetDataDirNet(); options.check_interrupt = [] { return false; }; - auto [status, error] = node::LoadChainstate(chainman, - metaman, - sporkman, - chainlocks, - mn_sync, - chain_helper, - dmnman, - evodb, - llmq_ctx, - gArgs.GetDataDirNet(), - cache_sizes, - options); + options.coins_error_cb = [] {}; + auto [status, error] = node::LoadChainstate(chainman, cache_sizes, options, evodb, dmnman, llmq_ctx, chain_helper); if (status != node::ChainstateLoadStatus::SUCCESS) { std::cerr << "Failed to load Chain state from your datadir." << std::endl; goto epilogue; } else { - std::tie(status, error) = node::VerifyLoadedChainstate(chainman, *evodb, options); + std::tie(status, error) = node::VerifyLoadedChainstate(chainman, options, *evodb); if (status != node::ChainstateLoadStatus::SUCCESS) { std::cerr << "Failed to verify loaded Chain state from your datadir." << std::endl; goto epilogue; @@ -283,6 +276,8 @@ int main(int argc, char* argv[]) } GetMainSignals().UnregisterBackgroundSignalScheduler(); // Tear down Dash kernel objects before kernel::~Context(). - node::DashChainstateSetupClose(chain_helper, dmnman, llmq_ctx, /*mempool=*/nullptr); + chain_helper.reset(); + llmq_ctx.reset(); + dmnman.reset(); evodb.reset(); } diff --git a/src/init.cpp b/src/init.cpp index 34b43d4f8096..49d91ff9203f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -158,7 +158,6 @@ using kernel::DumpMempool; using node::CacheSizes; using node::CalculateCacheSizes; -using node::DashChainstateSetupClose; using node::DEFAULT_PERSIST_MEMPOOL; using node::DEFAULT_PRINTPRIORITY; using node::DEFAULT_STOPAFTERBLOCKIMPORT; @@ -430,8 +429,14 @@ void PrepareShutdown(NodeContext& node) chainstate->ResetCoinsViews(); } } - DashChainstateSetupClose(node.chain_helper, node.dmnman, node.llmq_ctx, - Assert(node.mempool.get())); + // The mempool holds raw pointers to dmnman and llmq_ctx->isman, so it has to + // let go of them before either manager is destroyed. + if (node.mempool) { + node.mempool->DisconnectManagers(); + } + node.chain_helper.reset(); + node.llmq_ctx.reset(); + node.dmnman.reset(); node.evodb.reset(); } for (const auto& client : node.chain_clients) { @@ -2021,10 +2026,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) */ node.mn_sync = std::make_unique(std::make_unique(*node.connman, *node.netfulfilledman)); - bilingual_str strLoadError; - node::ChainstateLoadOptions options; options.mempool = Assert(node.mempool.get()); + options.mn_metaman = Assert(node.mn_metaman.get()); + options.sporkman = Assert(node.sporkman.get()); + options.chainlocks = Assert(node.chainlocks.get()); + options.mn_sync = Assert(node.mn_sync.get()); + options.data_dir = args.GetDataDirNet(); options.reindex = node::fReindex; options.reindex_chainstate = fReindexChainState; options.prune = node::fPruneMode; @@ -2039,7 +2047,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) const int64_t adjusted_threads = std::clamp(threads, 1, int64_t{llmq::MAX_BLSCHECK_THREADS} + 1) - 1; return static_cast(adjusted_threads); }(); - options.worker_count = llmq::DEFAULT_WORKER_COUNT; options.max_recsigs_age = args.GetIntArg("-maxrecsigsage", llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE); options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS); options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL); @@ -2049,59 +2056,43 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) _("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR); }; - options.notify_bls_state = [](bool bls_state) { - LogPrintf("%s: bls_legacy_scheme=%d\n", __func__, bls_state); - }; uiInterface.InitMessage(_("Loading block index…").translated); const auto load_block_index_start_time{SteadyClock::now()}; - auto catch_exceptions = [](auto&& fn) -> node::ChainstateLoadResult { + auto catch_exceptions = [](auto&& f) { try { - return fn(); + return f(); } catch (const std::exception& e) { LogPrintf("%s\n", e.what()); - return {node::ChainstateLoadStatus::FAILURE, _("Error opening block database")}; + return std::make_tuple(node::ChainstateLoadStatus::FAILURE, _("Error opening block database")); } }; - auto [status, error] = catch_exceptions([&] { - return LoadChainstate(chainman, - *node.mn_metaman, - *node.sporkman, - *node.chainlocks, - *node.mn_sync, - node.chain_helper, - node.dmnman, - node.evodb, - node.llmq_ctx, - args.GetDataDirNet(), - cache_sizes, - options); - }); + auto [status, error] = catch_exceptions([&]{ return LoadChainstate(chainman, cache_sizes, options, node.evodb, node.dmnman, node.llmq_ctx, node.chain_helper); }); if (status == node::ChainstateLoadStatus::SUCCESS) { uiInterface.InitMessage(_("Verifying blocks…").translated); if (chainman.m_blockman.m_have_pruned && options.check_blocks > MIN_BLOCKS_TO_KEEP) { LogWarning("pruned datadir may not have more than %d blocks; only checking available blocks\n", MIN_BLOCKS_TO_KEEP); } - std::tie(status, error) = catch_exceptions([&] { - return VerifyLoadedChainstate(chainman, *Assert(node.evodb), options); - }); + std::tie(status, error) = catch_exceptions([&]{ return VerifyLoadedChainstate(chainman, options, *Assert(node.evodb), [](bool bls_state) { + LogPrintf("AppInitMain: bls_legacy_scheme=%d\n", bls_state); + });}); + if (status == node::ChainstateLoadStatus::SUCCESS) { + fLoaded = true; + LogPrintf(" block index %15dms\n", Ticks(SteadyClock::now() - load_block_index_start_time)); + } } - if (status == node::ChainstateLoadStatus::SUCCESS) { - fLoaded = true; - LogPrintf(" block index %15dms\n", Ticks(SteadyClock::now() - load_block_index_start_time)); - } else if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB) { + + if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB) { return InitError(error); - } else { - strLoadError = error; } if (!fLoaded && !ShutdownRequested()) { // first suggest a reindex if (!options.reindex) { bool fRet = uiInterface.ThreadSafeQuestion( - strLoadError + Untranslated(".\n\n") + _("Do you want to rebuild the block database now?"), - strLoadError.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.", + error + Untranslated(".\n\n") + _("Do you want to rebuild the block database now?"), + error.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.", "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT); if (fRet) { fReindex = true; @@ -2111,7 +2102,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) return false; } } else { - return InitError(strLoadError); + return InitError(error); } } } diff --git a/src/llmq/options.h b/src/llmq/options.h index 9973472d0e3b..8bb0b22b1f06 100644 --- a/src/llmq/options.h +++ b/src/llmq/options.h @@ -27,6 +27,9 @@ enum class QvvecSyncMode : int8_t { OnlyIfTypeMember = 1, }; +// Keep recovered signatures for a week. This is a "-maxrecsigsage" option default. +static constexpr int64_t DEFAULT_MAX_RECOVERED_SIGS_AGE{60 * 60 * 24 * 7}; + /** -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.h b/src/llmq/signing.h index a8175ef4d2e1..76b6c4326cb3 100644 --- a/src/llmq/signing.h +++ b/src/llmq/signing.h @@ -42,9 +42,6 @@ class CQuorumManager; class CSigSharesManager; class SignHash; -// Keep recovered signatures for a week. This is a "-maxrecsigsage" option default. -static constexpr int64_t DEFAULT_MAX_RECOVERED_SIGS_AGE{60 * 60 * 24 * 7}; - class CSigBase { protected: diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index f6c246cebc30..c86f6173afad 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -35,26 +35,30 @@ #include namespace node { -ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, - CMasternodeMetaMan& mn_metaman, - CSporkManager& sporkman, - chainlock::Chainlocks& chainlocks, - const CMasternodeSync& mn_sync, - std::unique_ptr& chain_helper, - std::unique_ptr& dmnman, - std::unique_ptr& evodb, - std::unique_ptr& llmq_ctx, - const fs::path& data_dir, - const CacheSizes& cache_sizes, - const ChainstateLoadOptions& options) +ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes, + const ChainstateLoadOptions& options, std::unique_ptr& evodb, + std::unique_ptr& dmnman, std::unique_ptr& llmq_ctx, + std::unique_ptr& chain_helper) { + assert(options.mn_metaman); + assert(options.sporkman); + assert(options.chainlocks); + assert(options.mn_sync); + + const bool to_wipe_data = options.reindex || options.reindex_chainstate; auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { - return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull(); + return to_wipe_data || chainstate->CoinsTip().GetBestBlock().IsNull(); }; LOCK(cs_main); + evodb.reset(); - evodb = std::make_unique(util::DbWrapperParams{.path = data_dir, .memory = options.dash_dbs_in_memory, .wipe = options.reindex || options.reindex_chainstate}); + // TODO: pass DbWrapperParams as options instead multiple params + evodb = std::make_unique(util::DbWrapperParams{.path = options.data_dir, .memory = options.dash_dbs_in_memory, .wipe = to_wipe_data}); + + dmnman.reset(); + dmnman = std::make_unique(*evodb, *options.mn_metaman); + chainman.m_total_coinstip_cache = cache_sizes.coins; chainman.m_total_coinsdb_cache = cache_sizes.coins_db; @@ -70,10 +74,20 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, pblocktree.reset(); pblocktree.reset(new CBlockTreeDB(cache_sizes.block_tree_db, options.block_tree_db_in_memory, options.reindex)); - DashChainstateSetup(chainman, mn_metaman, sporkman, chainlocks, mn_sync, chain_helper, - dmnman, *evodb, llmq_ctx, options.mempool, data_dir, options.dash_dbs_in_memory, - /*llmq_dbs_wipe=*/options.reindex || options.reindex_chainstate, options.bls_threads, options.worker_count, - options.max_recsigs_age); + // Initialize llmq_ctx and connection to mempool + llmq_ctx.reset(); + llmq_ctx = std::make_unique(*dmnman, *evodb, *options.sporkman, chainman, + util::DbWrapperParams{.path = options.data_dir, .memory = options.dash_dbs_in_memory, .wipe = to_wipe_data}, + options.bls_threads, options.worker_count, options.max_recsigs_age); + if (options.mempool) { + options.mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); + } + + // Initialize chain_helper + chain_helper.reset(); + chain_helper = std::make_unique(*evodb, *dmnman, *options.mn_sync, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), + *(llmq_ctx->qsnapman), chainman, chainman.GetConsensus(), *options.chainlocks, + *(llmq_ctx->qman)); if (options.reindex) { pblocktree->WriteReindexing(true); @@ -96,6 +110,8 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, if (!chainman.BlockIndex().empty() && !chainman.m_blockman.LookupBlockIndex(chainman.GetConsensus().hashGenesisBlock)) { + // If the loaded chain has a wrong genesis, bail out immediately + // (we're likely using a testnet datadir, or the other way around). return {ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB, _("Incorrect or no genesis block found. Wrong datadir for network?")}; } @@ -190,56 +206,8 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, return {ChainstateLoadStatus::SUCCESS, {}}; } -void DashChainstateSetup(ChainstateManager& chainman, - CMasternodeMetaMan& mn_metaman, - CSporkManager& sporkman, - chainlock::Chainlocks& chainlocks, - const CMasternodeSync& mn_sync, - std::unique_ptr& chain_helper, - std::unique_ptr& dmnman, - CEvoDB& evodb, - std::unique_ptr& llmq_ctx, - CTxMemPool* mempool, - const fs::path& data_dir, - bool llmq_dbs_in_memory, - bool llmq_dbs_wipe, - int8_t bls_threads, - int16_t worker_count, - int64_t max_recsigs_age) -{ - // Same logic as pblocktree - dmnman.reset(); - dmnman = std::make_unique(evodb, mn_metaman); - - llmq_ctx.reset(); - llmq_ctx = std::make_unique(*dmnman, evodb, sporkman, chainman, - util::DbWrapperParams{.path = data_dir, .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, - bls_threads, worker_count, max_recsigs_age); - if (mempool) { - mempool->ConnectManagers(dmnman.get(), llmq_ctx->isman.get()); - } - chain_helper.reset(); - chain_helper = std::make_unique(evodb, *dmnman, mn_sync, *(llmq_ctx->isman), *(llmq_ctx->quorum_block_processor), - *(llmq_ctx->qsnapman), chainman, chainman.GetConsensus(), chainlocks, - *(llmq_ctx->qman)); -} - -void DashChainstateSetupClose(std::unique_ptr& chain_helper, - std::unique_ptr& dmnman, - std::unique_ptr& llmq_ctx, - CTxMemPool* mempool) - -{ - chain_helper.reset(); - llmq_ctx.reset(); - if (mempool) { - mempool->DisconnectManagers(); - } - dmnman.reset(); -} - -ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, CEvoDB& evodb, - const ChainstateLoadOptions& options) +ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options, CEvoDB& evodb, + std::function notify_bls_state) { auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull(); @@ -258,7 +226,8 @@ ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, CEvoDB& const bool v19active{DeploymentActiveAfter(tip, chainman, Consensus::DEPLOYMENT_V19)}; if (v19active) { bls::bls_legacy_scheme.store(false); - if (options.notify_bls_state) options.notify_bls_state(bls::bls_legacy_scheme.load()); + // TODO: remove notify_bls_state, it's alien and irrelevant once v19 activated + if (notify_bls_state) notify_bls_state(bls::bls_legacy_scheme.load()); } if (!CVerifyDB().VerifyDB( @@ -273,7 +242,7 @@ ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, CEvoDB& // Make sure we use the right scheme. if (v19active && bls::bls_legacy_scheme.load()) { bls::bls_legacy_scheme.store(false); - if (options.notify_bls_state) options.notify_bls_state(bls::bls_legacy_scheme.load()); + if (notify_bls_state) notify_bls_state(bls::bls_legacy_scheme.load()); } if (options.check_level >= 3) { diff --git a/src/node/chainstate.h b/src/node/chainstate.h index 36233b4e1aba..3f66cddd2ddd 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -5,13 +5,16 @@ #ifndef BITCOIN_NODE_CHAINSTATE_H #define BITCOIN_NODE_CHAINSTATE_H +#include +#include +#include + #include #include #include #include #include #include -#include class CChainstateHelper; class CDeterministicMNManager; @@ -24,29 +27,32 @@ class CTxMemPool; struct LLMQContext; namespace chainlock { class Chainlocks; } -namespace fs { -class path; -} // namespace fs namespace node { + struct CacheSizes; struct ChainstateLoadOptions { CTxMemPool* mempool{nullptr}; + CMasternodeMetaMan* mn_metaman{nullptr}; + CSporkManager* sporkman{nullptr}; + chainlock::Chainlocks* chainlocks{nullptr}; + const CMasternodeSync* mn_sync{nullptr}; + fs::path data_dir; + bool block_tree_db_in_memory{false}; bool coins_db_in_memory{false}; bool dash_dbs_in_memory{false}; bool reindex{false}; bool reindex_chainstate{false}; bool prune{false}; - int8_t bls_threads{0}; - int16_t worker_count{0}; - int64_t max_recsigs_age{0}; + int8_t bls_threads{llmq::DEFAULT_BLSCHECK_THREADS}; + int16_t worker_count{llmq::DEFAULT_WORKER_COUNT}; + int64_t max_recsigs_age{llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE}; int64_t check_blocks{DEFAULT_CHECKBLOCKS}; int64_t check_level{DEFAULT_CHECKLEVEL}; std::function check_interrupt; std::function coins_error_cb; - std::function notify_bls_state; }; //! Chainstate load status. Simple applications can just check for the success @@ -70,45 +76,16 @@ using ChainstateLoadResult = std::tuple; * - a failure that definitively cannot be recovered from with a reindex * * LoadChainstate returns a (status code, error string) tuple. + * + * The evodb, dmnman, llmq_ctx and chain_helper arguments are outputs: any + * instance they hold is destroyed and replaced with a freshly constructed one. */ -ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, - CMasternodeMetaMan& mn_metaman, - CSporkManager& sporkman, - chainlock::Chainlocks& chainlocks, - const CMasternodeSync& mn_sync, - std::unique_ptr& chain_helper, - std::unique_ptr& dmnman, - std::unique_ptr& evodb, - std::unique_ptr& llmq_ctx, - const fs::path& data_dir, - const CacheSizes& cache_sizes, - const ChainstateLoadOptions& options); - -/** Initialize Dash-specific components during chainstate initialization */ -void DashChainstateSetup(ChainstateManager& chainman, - CMasternodeMetaMan& mn_metaman, - CSporkManager& sporkman, - chainlock::Chainlocks& chainlocks, - const CMasternodeSync& mn_sync, - std::unique_ptr& chain_helper, - std::unique_ptr& dmnman, - CEvoDB& evodb, - std::unique_ptr& llmq_ctx, - CTxMemPool* mempool, - const fs::path& data_dir, - bool llmq_dbs_in_memory, - bool llmq_dbs_wipe, - int8_t bls_threads, - int16_t worker_count, - int64_t max_recsigs_age); - -void DashChainstateSetupClose(std::unique_ptr& chain_helper, - std::unique_ptr& dmnman, - std::unique_ptr& llmq_ctx, - CTxMemPool* mempool); - -ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, CEvoDB& evodb, - const ChainstateLoadOptions& options); +ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes, + const ChainstateLoadOptions& options, std::unique_ptr& evodb, + std::unique_ptr& dmnman, std::unique_ptr& llmq_ctx, + std::unique_ptr& chain_helper); +ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options, CEvoDB& evodb, + std::function notify_bls_state = nullptr); } // namespace node #endif // BITCOIN_NODE_CHAINSTATE_H diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index de67c720d420..0a64da394f70 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -88,13 +88,6 @@ using node::BlockAssembler; using node::CalculateCacheSizes; -using node::DashChainstateSetup; -using node::DashChainstateSetupClose; -using node::LoadChainstate; -using node::NodeContext; -using node::VerifyLoadedChainstate; -using node::fPruneMode; -using node::fReindex; using node::LoadChainstate; using node::NodeContext; using node::VerifyLoadedChainstate; @@ -141,23 +134,6 @@ std::unique_ptr MakePeerManager(CConnman& connman, node.llmq_ctx, ignore_incoming_txs); } -void DashChainstateSetup(ChainstateManager& chainman, - NodeContext& node, - bool llmq_dbs_in_memory, - bool llmq_dbs_wipe) -{ - DashChainstateSetup(chainman, *Assert(node.mn_metaman.get()), - *Assert(node.sporkman.get()), *Assert(node.chainlocks), *Assert(node.mn_sync), node.chain_helper, node.dmnman, *node.evodb, - node.llmq_ctx, Assert(node.mempool.get()), node.args->GetDataDirNet(), llmq_dbs_in_memory, llmq_dbs_wipe, - llmq::DEFAULT_BLSCHECK_THREADS, llmq::DEFAULT_WORKER_COUNT, llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE); -} - -void DashChainstateSetupClose(NodeContext& node) -{ - DashChainstateSetupClose(node.chain_helper, node.dmnman, node.llmq_ctx, - Assert(node.mempool.get())); -} - struct NetworkSetup { NetworkSetup() @@ -320,40 +296,32 @@ ChainTestingSetup::~ChainTestingSetup() void ChainTestingSetup::LoadVerifyActivateChainstate() { auto& chainman{*Assert(m_node.chainman)}; + node::ChainstateLoadOptions options; options.mempool = Assert(m_node.mempool.get()); + options.mn_metaman = Assert(m_node.mn_metaman.get()); + options.sporkman = Assert(m_node.sporkman.get()); + options.chainlocks = Assert(m_node.chainlocks.get()); + options.mn_sync = Assert(m_node.mn_sync.get()); + options.data_dir = Assert(m_node.args)->GetDataDirNet(); options.block_tree_db_in_memory = m_block_tree_db_in_memory; options.coins_db_in_memory = m_coins_db_in_memory; options.dash_dbs_in_memory = true; options.reindex = node::fReindex; options.reindex_chainstate = m_args.GetBoolArg("-reindex-chainstate", false); options.prune = node::fPruneMode; - options.bls_threads = llmq::DEFAULT_BLSCHECK_THREADS; - options.worker_count = llmq::DEFAULT_WORKER_COUNT; - options.max_recsigs_age = llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE; options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS); options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL); - options.notify_bls_state = [](bool bls_state) { - LogPrintf("%s: bls_legacy_scheme=%d\n", __func__, bls_state); - }; - auto [status, error] = LoadChainstate(chainman, - *Assert(m_node.mn_metaman.get()), - *Assert(m_node.sporkman.get()), - *Assert(m_node.chainlocks.get()), - *Assert(m_node.mn_sync.get()), - m_node.chain_helper, - m_node.dmnman, - m_node.evodb, - m_node.llmq_ctx, - Assert(m_node.args)->GetDataDirNet(), - m_cache_sizes, - options); + options.check_interrupt = [] { return false; }; + options.coins_error_cb = [] {}; + + auto [status, error] = LoadChainstate(chainman, m_cache_sizes, options, m_node.evodb, m_node.dmnman, m_node.llmq_ctx, + m_node.chain_helper); assert(status == node::ChainstateLoadStatus::SUCCESS); - std::tie(status, error) = VerifyLoadedChainstate( - chainman, - *Assert(m_node.evodb.get()), - options); + std::tie(status, error) = VerifyLoadedChainstate(chainman, options, *Assert(m_node.evodb), [](bool bls_state) { + LogPrintf("LoadVerifyActivateChainstate: bls_legacy_scheme=%d\n", bls_state); + }); assert(status == node::ChainstateLoadStatus::SUCCESS); BlockValidationState state; @@ -427,9 +395,12 @@ TestingSetup::~TestingSetup() m_node.connman->Stop(); } - // DashChainstateSetup() is called by LoadChainstate() internally but - // winding them down is our responsibility - DashChainstateSetupClose(m_node); + if (m_node.mempool) { + m_node.mempool->DisconnectManagers(); + } + m_node.chain_helper.reset(); + m_node.llmq_ctx.reset(); + m_node.dmnman.reset(); } TestChain100Setup::TestChain100Setup( diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index b3ac553323a4..132a5a14b868 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -84,11 +84,6 @@ std::unique_ptr MakePeerManager(CConnman& connman, node::NodeContext& node, BanMan* banman, bool ignore_incoming_txs); -void DashChainstateSetup(ChainstateManager& chainman, - node::NodeContext& node, - bool llmq_dbs_in_memory, - bool llmq_dbs_wipe); -void DashChainstateSetupClose(node::NodeContext& node); /** Basic testing setup. * This just configures logging, data dir and chain parameters. diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index cd2f1d9cb5ce..5b576b3bc58e 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -4,6 +4,10 @@ // #include #include +#include +#include +#include +#include #include #include #include @@ -18,7 +22,6 @@ #include #include -#include #include #include #include @@ -33,6 +36,35 @@ using node::SnapshotMetadata; BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup) +static void DashChainstateSetup(ChainstateManager& chainman, + node::NodeContext& node, + bool llmq_dbs_in_memory, + bool llmq_dbs_wipe) +{ + node.llmq_ctx.reset(); + node.llmq_ctx = std::make_unique(*node.dmnman, *node.evodb, *Assert(node.sporkman.get()), chainman, + util::DbWrapperParams{.path = node.args->GetDataDirNet(), .memory = llmq_dbs_in_memory, .wipe = llmq_dbs_wipe}, + llmq::DEFAULT_BLSCHECK_THREADS, llmq::DEFAULT_WORKER_COUNT, llmq::DEFAULT_MAX_RECOVERED_SIGS_AGE); + if (node.mempool) { + node.mempool->ConnectManagers(node.dmnman.get(), node.llmq_ctx->isman.get()); + } + + // Initialize chain_helper + node.chain_helper.reset(); + node.chain_helper = std::make_unique(*node.evodb, *node.dmnman, *Assert(node.mn_sync), *(node.llmq_ctx->isman), *(node.llmq_ctx->quorum_block_processor), + *(node.llmq_ctx->qsnapman), chainman, chainman.GetConsensus(), *Assert(node.chainlocks), + *(node.llmq_ctx->qman)); +} + +static void DashChainstateSetupClose(node::NodeContext& node) +{ + if (node.mempool) { + node.mempool->DisconnectManagers(); + } + node.chain_helper.reset(); + node.llmq_ctx.reset(); +} + //! Basic tests for ChainstateManager. //! //! First create a legacy (IBD) chainstate, then create a snapshot chainstate. @@ -41,6 +73,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) ChainstateManager& manager = *m_node.chainman; CTxMemPool& mempool = *m_node.mempool; CEvoDB& evodb = *m_node.evodb; + m_node.dmnman = std::make_unique(evodb, *Assert(m_node.mn_metaman.get())); std::vector chainstates; BOOST_CHECK(!manager.SnapshotBlockhash().has_value()); @@ -71,9 +104,6 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) BOOST_CHECK(!manager.SnapshotBlockhash().has_value()); - if (m_node.clhandler) { - m_node.clhandler->Stop(); - } DashChainstateSetupClose(m_node); // Create a snapshot-based chainstate. @@ -118,10 +148,9 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) // Let scheduler events finish running to avoid accessing memory that is going to be unloaded SyncWithValidationInterfaceQueue(); - if (m_node.clhandler) { - m_node.clhandler->Stop(); - } DashChainstateSetupClose(m_node); + // dmnman holds a reference to m_node.evodb, it mustn't outlive it + m_node.dmnman.reset(); } //! Test rebalancing the caches associated with each chainstate.