Skip to content

Commit

Permalink
partial bitcoin#22564: Move mutable globals cleared in ::UnloadBlockI…
Browse files Browse the repository at this point in the history
…ndex to BlockManager

A lot of Dash logic relies on the initialization order remaining as it
is. Adjusting it to account for a new initialization order is non-trivial
and isn't strictly speaking necessary in the foreseeable future, so for
now, we'll omit moving down initializing ChainstateManager, PeerManager
and CTxMemPool.
  • Loading branch information
kwvg committed Aug 2, 2024
1 parent acf06e3 commit 39fea85
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 76 deletions.
11 changes: 4 additions & 7 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@

#include <statsd_client.h>

#include <algorithm>
#include <functional>
#include <set>
#include <stdint.h>
Expand Down Expand Up @@ -1563,8 +1564,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
if (!ignores_incoming_txs) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();

assert(!node.mempool);
int check_ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
const int mempool_check_ratio = std::clamp<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0, 1000000);
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), mempool_check_ratio);

assert(!node.chainman);
node.chainman = std::make_unique<ChainstateManager>();
Expand Down Expand Up @@ -1813,9 +1814,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
LogPrintf("* Using %.1f MiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));

bool fLoaded = false;

while (!fLoaded && !ShutdownRequested()) {
for (bool fLoaded = false; !fLoaded && !ShutdownRequested();) {
const bool fReset = fReindex;
auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
Expand All @@ -1841,8 +1840,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
chainman.m_total_coinstip_cache = nCoinCacheUsage;
chainman.m_total_coinsdb_cache = nCoinDBCache;

UnloadBlockIndex(node.mempool.get(), 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:
Expand Down
15 changes: 0 additions & 15 deletions src/node/blockstorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,21 +314,6 @@ bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params)
return true;
}

void BlockManager::Unload()
{
m_blocks_unlinked.clear();

m_block_index.clear();
m_prev_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);
Expand Down
8 changes: 0 additions & 8 deletions src/node/blockstorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,6 @@ class BlockManager
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, const uint256& hash, CBlockIndex*& best_header,
enum BlockStatus nStatus = BLOCK_VALID_TREE)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
Expand Down Expand Up @@ -195,11 +192,6 @@ class BlockManager
* This is also true for mempool checks.
*/
int GetSpendHeight(const CCoinsViewCache& inputs) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

~BlockManager()
{
Unload();
}
};

void CleanupBlockRevFiles();
Expand Down
1 change: 0 additions & 1 deletion src/test/util/setup_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ ChainTestingSetup::~ChainTestingSetup()
m_node.connman.reset();
m_node.addrman.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();
Expand Down
2 changes: 1 addition & 1 deletion src/test/validation_chainstate_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,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;

Expand Down
4 changes: 2 additions & 2 deletions src/test/validation_chainstatemanager_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
DashTestSetup(m_node, chainparams);

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());

Expand Down Expand Up @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
BOOST_CHECK(c2.ActivateBestChain(dummy_state, 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();
Expand Down
44 changes: 14 additions & 30 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1772,7 +1772,7 @@ class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
}
};

static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_main);
static std::array<ThresholdConditionCache, VERSIONBITS_NUM_BITS> warningcache GUARDED_BY(cs_main);

static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams)
{
Expand Down Expand Up @@ -2553,7 +2553,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) {
Expand Down Expand Up @@ -4373,20 +4373,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);
Expand Down Expand Up @@ -5457,20 +5443,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);
Expand Down Expand Up @@ -5501,3 +5473,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();
}
}
16 changes: 4 additions & 12 deletions src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,6 @@ extern arith_uint256 nMinimumChainWork;
/** Documentation for argument 'checklevel'. */
extern const std::vector<std::string> 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 */
Expand Down Expand Up @@ -847,9 +845,9 @@ class ChainstateManager

//! 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(
Expand Down Expand Up @@ -964,7 +962,7 @@ class ChainstateManager
std::optional<uint256> 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
Expand Down Expand Up @@ -1004,17 +1002,11 @@ class ChainstateManager
//! 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();
};

/**
Expand Down

0 comments on commit 39fea85

Please sign in to comment.