Skip to content

Commit f2a4f33

Browse files
committed
move-only-ish: init: factor out chainstate initialization
Moves chainstate initialization into its own function. This is necessary to later support a more readable way of handling background-validation chainstate cleanup during init, since the chainstate initialization functions may need to be repeated after moving leveldb filesystem content around. This commit isn't strictly necessary, but the alternative is to (ab)use the `while` loop in init.cpp with a `continue` on the basis of a specific ChainstateLoadingError return value from LoadChainstate. Not only is this harder to read, but it can't be unittested. The approach here lets us consolidate background-validation cleanup to LoadChainstate, and therefore exercise it within tests. This commit is most easily reviewed with git diff --color-moved=dimmed-zebra --color-moved-ws=ignore-space-change
1 parent 637a90b commit f2a4f33

File tree

1 file changed

+47
-31
lines changed

1 file changed

+47
-31
lines changed

src/node/chainstate.cpp

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,13 @@
2828
#include <vector>
2929

3030
namespace node {
31-
ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes,
32-
const ChainstateLoadOptions& options)
31+
// Complete initialization of chainstates after the initial call has been made
32+
// to ChainstateManager::InitializeChainstate().
33+
static ChainstateLoadResult CompleteChainstateInitialization(
34+
ChainstateManager& chainman,
35+
const CacheSizes& cache_sizes,
36+
const ChainstateLoadOptions& options) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
3337
{
34-
auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
35-
return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
36-
};
37-
38-
if (!chainman.AssumedValidBlock().IsNull()) {
39-
LogPrintf("Assuming ancestors of block %s have valid signatures.\n", chainman.AssumedValidBlock().GetHex());
40-
} else {
41-
LogPrintf("Validating signatures for all blocks.\n");
42-
}
43-
LogPrintf("Setting nMinimumChainWork=%s\n", chainman.MinimumChainWork().GetHex());
44-
if (chainman.MinimumChainWork() < UintToArith256(chainman.GetConsensus().nMinimumChainWork)) {
45-
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex());
46-
}
47-
if (chainman.m_blockman.GetPruneTarget() == std::numeric_limits<uint64_t>::max()) {
48-
LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
49-
} else if (chainman.m_blockman.GetPruneTarget()) {
50-
LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", chainman.m_blockman.GetPruneTarget() / 1024 / 1024);
51-
}
52-
53-
LOCK(cs_main);
54-
chainman.m_total_coinstip_cache = cache_sizes.coins;
55-
chainman.m_total_coinsdb_cache = cache_sizes.coins_db;
56-
57-
// Load the fully validated chainstate.
58-
chainman.InitializeChainstate(options.mempool);
59-
60-
// Load a chain created from a UTXO snapshot, if any exist.
61-
chainman.DetectSnapshotChainstate(options.mempool);
62-
6338
auto& pblocktree{chainman.m_blockman.m_block_tree_db};
6439
// new CBlockTreeDB tries to delete the existing file, which
6540
// fails if it's still open from the previous loop. Close it first:
@@ -106,6 +81,10 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
10681
return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
10782
}
10883

84+
auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
85+
return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
86+
};
87+
10988
// Conservative value which is arbitrarily chosen, as it will ultimately be changed
11089
// by a call to `chainman.MaybeRebalanceCaches()`. We just need to make sure
11190
// that the sum of the two caches (40%) does not exceed the allowable amount
@@ -170,6 +149,43 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
170149
return {ChainstateLoadStatus::SUCCESS, {}};
171150
}
172151

152+
ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes,
153+
const ChainstateLoadOptions& options)
154+
{
155+
if (!chainman.AssumedValidBlock().IsNull()) {
156+
LogPrintf("Assuming ancestors of block %s have valid signatures.\n", chainman.AssumedValidBlock().GetHex());
157+
} else {
158+
LogPrintf("Validating signatures for all blocks.\n");
159+
}
160+
LogPrintf("Setting nMinimumChainWork=%s\n", chainman.MinimumChainWork().GetHex());
161+
if (chainman.MinimumChainWork() < UintToArith256(chainman.GetConsensus().nMinimumChainWork)) {
162+
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex());
163+
}
164+
if (chainman.m_blockman.GetPruneTarget() == std::numeric_limits<uint64_t>::max()) {
165+
LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
166+
} else if (chainman.m_blockman.GetPruneTarget()) {
167+
LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", chainman.m_blockman.GetPruneTarget() / 1024 / 1024);
168+
}
169+
170+
LOCK(cs_main);
171+
172+
chainman.m_total_coinstip_cache = cache_sizes.coins;
173+
chainman.m_total_coinsdb_cache = cache_sizes.coins_db;
174+
175+
// Load the fully validated chainstate.
176+
chainman.InitializeChainstate(options.mempool);
177+
178+
// Load a chain created from a UTXO snapshot, if any exist.
179+
chainman.DetectSnapshotChainstate(options.mempool);
180+
181+
auto [init_status, init_error] = CompleteChainstateInitialization(chainman, cache_sizes, options);
182+
if (init_status != ChainstateLoadStatus::SUCCESS) {
183+
return {init_status, init_error};
184+
}
185+
186+
return {ChainstateLoadStatus::SUCCESS, {}};
187+
}
188+
173189
ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options)
174190
{
175191
auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {

0 commit comments

Comments
 (0)