diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index fcbb6aaccee..1e4200db029 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -256,7 +256,5 @@ epilogue: } GetMainSignals().UnregisterBackgroundSignalScheduler(); - WITH_LOCK(::cs_main, UnloadBlockIndex(nullptr, chainman)); - init::UnsetGlobals(); } diff --git a/src/init.cpp b/src/init.cpp index cccb088eec7..fdcb2b8ac76 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -73,6 +73,7 @@ #include #include +#include #include #include #include @@ -1288,19 +1289,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) // as they would never get updated. if (!ignores_incoming_txs) node.fee_estimator = std::make_unique(); - assert(!node.mempool); - int check_ratio = std::min(std::max(args.GetIntArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); - node.mempool = std::make_unique(node.fee_estimator.get(), check_ratio); - - assert(!node.chainman); - node.chainman = std::make_unique(); - ChainstateManager& chainman = *node.chainman; - - assert(!node.peerman); - node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), - chainman, *node.mempool, ignores_incoming_txs); - RegisterValidationInterface(node.peerman.get()); - // sanitize comments per BIP-0014, format user agent and check total size std::vector uacomments; for (const std::string& cmt : args.GetArgs("-uacomment")) { @@ -1429,8 +1417,16 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) LogPrintf("* Using %.1f MiB for chain state database\n", cache_sizes.coins_db * (1.0 / 1024 / 1024)); LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", cache_sizes.coins * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024)); - bool fLoaded = false; - while (!fLoaded && !ShutdownRequested()) { + assert(!node.mempool); + assert(!node.chainman); + const int mempool_check_ratio = std::clamp(args.GetIntArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0, 1000000); + + for (bool fLoaded = false; !fLoaded && !ShutdownRequested();) { + node.mempool = std::make_unique(node.fee_estimator.get(), mempool_check_ratio); + + node.chainman = std::make_unique(); + ChainstateManager& chainman = *node.chainman; + const bool fReset = fReindex; bilingual_str strLoadError; @@ -1562,6 +1558,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) return false; } + ChainstateManager& chainman = *Assert(node.chainman); + + assert(!node.peerman); + node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(), + chainman, *node.mempool, ignores_incoming_txs); + RegisterValidationInterface(node.peerman.get()); + // ********************************************************* Step 8: start indexers if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { if (const auto error{WITH_LOCK(cs_main, return CheckLegacyTxindex(*Assert(chainman.m_blockman.m_block_tree_db)))}) { diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 8ed22bbbce8..25771aaceeb 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -297,20 +297,6 @@ bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params) return true; } -void BlockManager::Unload() -{ - m_blocks_unlinked.clear(); - - m_block_index.clear(); - - m_blockfile_info.clear(); - m_last_blockfile = 0; - m_dirty_blockindex.clear(); - m_dirty_fileinfo.clear(); - - m_have_pruned = false; -} - bool BlockManager::WriteBlockIndexDB() { AssertLockHeld(::cs_main); diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index e4b96573726..622eac7fef7 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -154,9 +154,6 @@ public: bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); - /** Clear all data members. */ - void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main); - CBlockIndex* AddToBlockIndex(const CBlockHeader& block, CBlockIndex*& best_header) EXCLUSIVE_LOCKS_REQUIRED(cs_main); /** Create a new block index entry for a given block hash */ CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); @@ -189,11 +186,6 @@ public: //! Create or update a prune lock identified by its name void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); - - ~BlockManager() - { - Unload(); - } }; //! Find the first block that is not pruned diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index e43211402ca..99615dea692 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -32,8 +32,6 @@ std::optional LoadChainstate(bool fReset, chainman.m_total_coinstip_cache = nCoinCacheUsage; chainman.m_total_coinsdb_cache = nCoinDBCache; - UnloadBlockIndex(mempool, chainman); - auto& pblocktree{chainman.m_blockman.m_block_tree_db}; // new CBlockTreeDB tries to delete the existing file, which // fails if it's still open from the previous loop. Close it first: diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 1830ec05afc..2fc71c2a6ec 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -182,7 +182,6 @@ ChainTestingSetup::~ChainTestingSetup() m_node.addrman.reset(); m_node.netgroupman.reset(); m_node.args = nullptr; - WITH_LOCK(::cs_main, UnloadBlockIndex(m_node.mempool.get(), *m_node.chainman)); m_node.mempool.reset(); m_node.scheduler.reset(); m_node.chainman.reset(); diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp index b0d7389d39b..2a3990bb7c7 100644 --- a/src/test/validation_chainstate_tests.cpp +++ b/src/test/validation_chainstate_tests.cpp @@ -93,7 +93,7 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup) BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root)); // Ensure our active chain is the snapshot chainstate. - BOOST_CHECK(chainman.IsSnapshotActive()); + BOOST_CHECK(WITH_LOCK(::cs_main, return chainman.IsSnapshotActive())); curr_tip = ::g_best_block; diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index 5d0ec593e3c..6dc522b4214 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23)); BOOST_CHECK(!manager.IsSnapshotActive()); - BOOST_CHECK(!manager.IsSnapshotValidated()); + BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated())); auto all = manager.GetAll(); BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end()); @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager) BOOST_CHECK(c2.ActivateBestChain(_, nullptr)); BOOST_CHECK(manager.IsSnapshotActive()); - BOOST_CHECK(!manager.IsSnapshotValidated()); + BOOST_CHECK(WITH_LOCK(::cs_main, return !manager.IsSnapshotValidated())); BOOST_CHECK_EQUAL(&c2, &manager.ActiveChainstate()); BOOST_CHECK(&c1 != &manager.ActiveChainstate()); auto all2 = manager.GetAll(); diff --git a/src/validation.cpp b/src/validation.cpp index 3676316f76f..208bcee0081 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1921,7 +1921,7 @@ public: } }; -static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main); +static std::array warningcache GUARDED_BY(cs_main); static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const Consensus::Params& consensusparams) { @@ -2550,7 +2550,7 @@ void CChainState::UpdateTip(const CBlockIndex* pindexNew) const CBlockIndex* pindex = pindexNew; for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { WarningBitsConditionChecker checker(bit); - ThresholdState state = checker.GetStateFor(pindex, m_params.GetConsensus(), warningcache[bit]); + ThresholdState state = checker.GetStateFor(pindex, m_params.GetConsensus(), warningcache.at(bit)); if (state == ThresholdState::ACTIVE || state == ThresholdState::LOCKED_IN) { const bilingual_str warning = strprintf(_("Unknown new rules activated (versionbit %i)"), bit); if (state == ThresholdState::ACTIVE) { @@ -4143,20 +4143,6 @@ void CChainState::UnloadBlockIndex() setBlockIndexCandidates.clear(); } -// May NOT be used after any connections are up as much -// of the peer-processing logic assumes a consistent -// block index state -void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman) -{ - AssertLockHeld(::cs_main); - chainman.Unload(); - if (mempool) mempool->clear(); - g_versionbitscache.Clear(); - for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) { - warningcache[b].clear(); - } -} - bool ChainstateManager::LoadBlockIndex() { AssertLockHeld(cs_main); @@ -5187,20 +5173,6 @@ bool ChainstateManager::IsSnapshotActive() const return m_snapshot_chainstate && m_active_chainstate == m_snapshot_chainstate.get(); } -void ChainstateManager::Unload() -{ - AssertLockHeld(::cs_main); - for (CChainState* chainstate : this->GetAll()) { - chainstate->m_chain.SetTip(nullptr); - chainstate->UnloadBlockIndex(); - } - - m_failed_blocks.clear(); - m_blockman.Unload(); - m_best_header = nullptr; - m_best_invalid = nullptr; -} - void ChainstateManager::MaybeRebalanceCaches() { AssertLockHeld(::cs_main); @@ -5231,3 +5203,15 @@ void ChainstateManager::MaybeRebalanceCaches() } } } + +ChainstateManager::~ChainstateManager() +{ + LOCK(::cs_main); + + // TODO: The version bits cache and warning cache should probably become + // non-globals + g_versionbitscache.Clear(); + for (auto& i : warningcache) { + i.clear(); + } +} diff --git a/src/validation.h b/src/validation.h index 38d3d984657..e3ea8617e79 100644 --- a/src/validation.h +++ b/src/validation.h @@ -134,8 +134,6 @@ extern arith_uint256 nMinimumChainWork; /** Documentation for argument 'checklevel'. */ extern const std::vector CHECKLEVEL_DOC; -/** Unload database information */ -void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); /** Run instances of script checking worker threads */ void StartScriptCheckWorkerThreads(int threads_num); /** Stop all of the script checking worker threads */ @@ -831,9 +829,9 @@ private: //! If true, the assumed-valid chainstate has been fully validated //! by the background validation chainstate. - bool m_snapshot_validated{false}; + bool m_snapshot_validated GUARDED_BY(::cs_main){false}; - CBlockIndex* m_best_invalid; + CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr}; //! Internal helper for ActivateSnapshot(). [[nodiscard]] bool PopulateAndValidateSnapshot( @@ -940,7 +938,7 @@ public: std::optional SnapshotBlockhash() const; //! Is there a snapshot in use and has it been fully validated? - bool IsSnapshotValidated() const { return m_snapshot_validated; } + bool IsSnapshotValidated() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { return m_snapshot_validated; } /** * Process an incoming block. This only returns after the best known valid @@ -988,17 +986,11 @@ public: //! Load the block tree and coins database from disk, initializing state if we're running with -reindex bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main); - //! Unload block index and chain data before shutdown. - void Unload() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); - //! Check to see if caches are out of balance and if so, call //! ResizeCoinsCaches() as needed. void MaybeRebalanceCaches() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); - ~ChainstateManager() { - LOCK(::cs_main); - UnloadBlockIndex(/*mempool=*/nullptr, *this); - } + ~ChainstateManager(); }; using FopenFn = std::function;