Skip to content

Commit

Permalink
init: Reset mempool and chainman via reconstruction
Browse files Browse the repository at this point in the history
Fixes bitcoin/bitcoin#22964

Previously, we used UnloadBlockIndex() in order to reset node.mempool
and node.chainman. However, that has proven to be fragile (see
bitcoin/bitcoin#22964), and requires
UnloadBlockIndex and its callees to be updated manually for each member
that's introduced to the mempool and chainman classes.

In this commit, we stop using the UnloadBlockIndex function and we
simply reconstruct node.mempool and node.chainman.

Since PeerManager needs a valid reference to both node.mempool and
node.chainman, we also move PeerManager's construction via `::make` to
after the chainstate activation sequence is complete.

There are no more callers to UnloadBlockIndex after this commit, so it
and its sole callees can be pruned.
  • Loading branch information
dongcarl authored and janus committed Jul 27, 2022
1 parent 45bed2d commit c0680c8
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 15 deletions.
29 changes: 16 additions & 13 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1282,19 +1282,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<CBlockPolicyEstimator>();

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

assert(!node.chainman);
node.chainman = std::make_unique<ChainstateManager>();
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<std::string> uacomments;
for (const std::string& cmt : args.GetArgs("-uacomment")) {
Expand Down Expand Up @@ -1423,8 +1410,17 @@ 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));

assert(!node.mempool);
assert(!node.chainman);
int check_ratio = std::min<int>(std::max<int>(args.GetIntArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);

bool fLoaded = false;
while (!fLoaded && !ShutdownRequested()) {
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);

node.chainman = std::make_unique<ChainstateManager>();
ChainstateManager& chainman = *node.chainman;

const bool fReset = fReindex;
bilingual_str strLoadError;

Expand Down Expand Up @@ -1556,6 +1552,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)))}) {
Expand Down
2 changes: 0 additions & 2 deletions src/node/chainstate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ std::optional<ChainstateLoadingError> LoadChainstate(bool fReset,
CleanupBlockRevFiles();
}

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:
Expand Down

0 comments on commit c0680c8

Please sign in to comment.