aboutsummaryrefslogtreecommitdiff
path: root/src/node/chainstate.cpp
diff options
context:
space:
mode:
authorJames O'Beirne <james.obeirne@pm.me>2022-11-03 14:37:24 -0400
committerJames O'Beirne <james.obeirne@pm.me>2023-02-22 12:13:26 -0500
commitf2a4f3376f1476b38a79a549bd81ba3006225df6 (patch)
treeaced8235f472238e709c1612236f4df299b5d87a /src/node/chainstate.cpp
parent637a90b973f60555ea4fef4b845ffa7533dcb866 (diff)
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
Diffstat (limited to 'src/node/chainstate.cpp')
-rw-r--r--src/node/chainstate.cpp78
1 files changed, 47 insertions, 31 deletions
diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp
index ba1024d22e..e9eea90bcb 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -28,38 +28,13 @@
#include <vector>
namespace node {
-ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes,
- const ChainstateLoadOptions& options)
+// Complete initialization of chainstates after the initial call has been made
+// to ChainstateManager::InitializeChainstate().
+static ChainstateLoadResult CompleteChainstateInitialization(
+ ChainstateManager& chainman,
+ const CacheSizes& cache_sizes,
+ const ChainstateLoadOptions& options) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
- auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
- return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
- };
-
- if (!chainman.AssumedValidBlock().IsNull()) {
- LogPrintf("Assuming ancestors of block %s have valid signatures.\n", chainman.AssumedValidBlock().GetHex());
- } else {
- LogPrintf("Validating signatures for all blocks.\n");
- }
- LogPrintf("Setting nMinimumChainWork=%s\n", chainman.MinimumChainWork().GetHex());
- if (chainman.MinimumChainWork() < UintToArith256(chainman.GetConsensus().nMinimumChainWork)) {
- LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex());
- }
- if (chainman.m_blockman.GetPruneTarget() == std::numeric_limits<uint64_t>::max()) {
- LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
- } else if (chainman.m_blockman.GetPruneTarget()) {
- LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", chainman.m_blockman.GetPruneTarget() / 1024 / 1024);
- }
-
- LOCK(cs_main);
- chainman.m_total_coinstip_cache = cache_sizes.coins;
- chainman.m_total_coinsdb_cache = cache_sizes.coins_db;
-
- // Load the fully validated chainstate.
- chainman.InitializeChainstate(options.mempool);
-
- // Load a chain created from a UTXO snapshot, if any exist.
- chainman.DetectSnapshotChainstate(options.mempool);
-
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:
@@ -106,6 +81,10 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
}
+ auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
+ };
+
// Conservative value which is arbitrarily chosen, as it will ultimately be changed
// by a call to `chainman.MaybeRebalanceCaches()`. We just need to make sure
// that the sum of the two caches (40%) does not exceed the allowable amount
@@ -170,6 +149,43 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
return {ChainstateLoadStatus::SUCCESS, {}};
}
+ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes,
+ const ChainstateLoadOptions& options)
+{
+ if (!chainman.AssumedValidBlock().IsNull()) {
+ LogPrintf("Assuming ancestors of block %s have valid signatures.\n", chainman.AssumedValidBlock().GetHex());
+ } else {
+ LogPrintf("Validating signatures for all blocks.\n");
+ }
+ LogPrintf("Setting nMinimumChainWork=%s\n", chainman.MinimumChainWork().GetHex());
+ if (chainman.MinimumChainWork() < UintToArith256(chainman.GetConsensus().nMinimumChainWork)) {
+ LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex());
+ }
+ if (chainman.m_blockman.GetPruneTarget() == std::numeric_limits<uint64_t>::max()) {
+ LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
+ } else if (chainman.m_blockman.GetPruneTarget()) {
+ LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", chainman.m_blockman.GetPruneTarget() / 1024 / 1024);
+ }
+
+ LOCK(cs_main);
+
+ chainman.m_total_coinstip_cache = cache_sizes.coins;
+ chainman.m_total_coinsdb_cache = cache_sizes.coins_db;
+
+ // Load the fully validated chainstate.
+ chainman.InitializeChainstate(options.mempool);
+
+ // Load a chain created from a UTXO snapshot, if any exist.
+ chainman.DetectSnapshotChainstate(options.mempool);
+
+ auto [init_status, init_error] = CompleteChainstateInitialization(chainman, cache_sizes, options);
+ if (init_status != ChainstateLoadStatus::SUCCESS) {
+ return {init_status, init_error};
+ }
+
+ return {ChainstateLoadStatus::SUCCESS, {}};
+}
+
ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options)
{
auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {