aboutsummaryrefslogtreecommitdiff
path: root/src/node
diff options
context:
space:
mode:
authorJames O'Beirne <james.obeirne@pm.me>2022-04-20 17:40:01 -0400
committerJames O'Beirne <james.obeirne@pm.me>2022-09-13 13:30:14 -0400
commit252abd1e8bc5cdf4368ad55e827a873240535b28 (patch)
tree2a1c9aa9ab01a4bb5951140d52b5c5720fce5ec9 /src/node
parentf9f1735f139b6a1f1c7fea50717ff90dc4ba2bce (diff)
downloadbitcoin-252abd1e8bc5cdf4368ad55e827a873240535b28.tar.xz
init: add utxo snapshot detection
Add functionality for activating a snapshot-based chainstate if one is detected on-disk. Also cautiously initialize chainstate cache usages so that we don't somehow blow past our cache allowances during initialization, then rebalance at the end of init. Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
Diffstat (limited to 'src/node')
-rw-r--r--src/node/chainstate.cpp24
-rw-r--r--src/node/utxo_snapshot.cpp12
-rw-r--r--src/node/utxo_snapshot.h6
3 files changed, 39 insertions, 3 deletions
diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp
index 3f1d6dd743..26af523491 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -48,10 +48,15 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
}
LOCK(cs_main);
- chainman.InitializeChainstate(options.mempool);
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:
@@ -98,12 +103,20 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
}
+ // 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
+ // during this temporary initialization state.
+ double init_cache_fraction = 0.2;
+
// At this point we're either in reindex or we've loaded a useful
// block tree into BlockIndex()!
for (Chainstate* chainstate : chainman.GetAll()) {
+ LogPrintf("Initializing chainstate %s\n", chainstate->ToString());
+
chainstate->InitCoinsDB(
- /*cache_size_bytes=*/cache_sizes.coins_db,
+ /*cache_size_bytes=*/chainman.m_total_coinsdb_cache * init_cache_fraction,
/*in_memory=*/options.coins_db_in_memory,
/*should_wipe=*/options.reindex || options.reindex_chainstate);
@@ -125,7 +138,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
}
// The on-disk coinsdb is now in a good state, create the cache
- chainstate->InitCoinsCache(cache_sizes.coins);
+ chainstate->InitCoinsCache(chainman.m_total_coinstip_cache * init_cache_fraction);
assert(chainstate->CanFlushToDisk());
if (!is_coinsview_empty(chainstate)) {
@@ -146,6 +159,11 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
};
}
+ // Now that chainstates are loaded and we're able to flush to
+ // disk, rebalance the coins caches to desired levels based
+ // on the condition of each chainstate.
+ chainman.MaybeRebalanceCaches();
+
return {ChainstateLoadStatus::SUCCESS, {}};
}
diff --git a/src/node/utxo_snapshot.cpp b/src/node/utxo_snapshot.cpp
index 29ff83a03b..bab1b75211 100644
--- a/src/node/utxo_snapshot.cpp
+++ b/src/node/utxo_snapshot.cpp
@@ -8,6 +8,7 @@
#include <logging.h>
#include <streams.h>
#include <uint256.h>
+#include <util/system.h>
#include <validation.h>
#include <cstdio>
@@ -76,4 +77,15 @@ std::optional<uint256> ReadSnapshotBaseBlockhash(fs::path chaindir)
return base_blockhash;
}
+std::optional<fs::path> FindSnapshotChainstateDir()
+{
+ fs::path possible_dir =
+ gArgs.GetDataDirNet() / fs::u8path(strprintf("chainstate%s", SNAPSHOT_CHAINSTATE_SUFFIX));
+
+ if (fs::exists(possible_dir)) {
+ return possible_dir;
+ }
+ return std::nullopt;
+}
+
} // namespace node
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index b82a791092..c94521792f 100644
--- a/src/node/utxo_snapshot.h
+++ b/src/node/utxo_snapshot.h
@@ -58,8 +58,14 @@ bool WriteSnapshotBaseBlockhash(Chainstate& snapshot_chainstate)
std::optional<uint256> ReadSnapshotBaseBlockhash(fs::path chaindir)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+//! Suffix appended to the chainstate (leveldb) dir when created based upon
+//! a snapshot.
constexpr std::string_view SNAPSHOT_CHAINSTATE_SUFFIX = "_snapshot";
+
+//! Return a path to the snapshot-based chainstate dir, if one exists.
+std::optional<fs::path> FindSnapshotChainstateDir();
+
} // namespace node
#endif // BITCOIN_NODE_UTXO_SNAPSHOT_H