Bitcoin Core  22.99.0
P2P Digital Currency
chainstate.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <node/chainstate.h>
6 
7 #include <consensus/params.h>
8 #include <node/blockstorage.h>
9 #include <validation.h>
10 
11 namespace node {
12 std::optional<ChainstateLoadingError> LoadChainstate(bool fReset,
13  ChainstateManager& chainman,
14  CTxMemPool* mempool,
15  bool fPruneMode,
16  const Consensus::Params& consensus_params,
17  bool fReindexChainState,
18  int64_t nBlockTreeDBCache,
19  int64_t nCoinDBCache,
20  int64_t nCoinCacheUsage,
21  bool block_tree_db_in_memory,
22  bool coins_db_in_memory,
23  std::function<bool()> shutdown_requested,
24  std::function<void()> coins_error_cb)
25 {
26  auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
27  return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
28  };
29 
30  LOCK(cs_main);
31  chainman.InitializeChainstate(mempool);
32  chainman.m_total_coinstip_cache = nCoinCacheUsage;
33  chainman.m_total_coinsdb_cache = nCoinDBCache;
34 
35  UnloadBlockIndex(mempool, chainman);
36 
37  auto& pblocktree{chainman.m_blockman.m_block_tree_db};
38  // new CBlockTreeDB tries to delete the existing file, which
39  // fails if it's still open from the previous loop. Close it first:
40  pblocktree.reset();
41  pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset));
42 
43  if (fReset) {
44  pblocktree->WriteReindexing(true);
45  //If we're reindexing in prune mode, wipe away unusable block files and all undo data files
46  if (fPruneMode)
48  }
49 
50  if (shutdown_requested && shutdown_requested()) return ChainstateLoadingError::SHUTDOWN_PROBED;
51 
52  // LoadBlockIndex will load fHavePruned if we've ever removed a
53  // block file from disk.
54  // Note that it also sets fReindex based on the disk flag!
55  // From here on out fReindex and fReset mean something different!
56  if (!chainman.LoadBlockIndex()) {
57  if (shutdown_requested && shutdown_requested()) return ChainstateLoadingError::SHUTDOWN_PROBED;
59  }
60 
61  if (!chainman.BlockIndex().empty() &&
62  !chainman.m_blockman.LookupBlockIndex(consensus_params.hashGenesisBlock)) {
64  }
65 
66  // Check for changed -prune state. What we are concerned about is a user who has pruned blocks
67  // in the past, but is now trying to run unpruned.
68  if (fHavePruned && !fPruneMode) {
70  }
71 
72  // At this point blocktree args are consistent with what's on disk.
73  // If we're not mid-reindex (based on disk + args), add a genesis block on disk
74  // (otherwise we use the one already on disk).
75  // This is called again in ThreadImport after the reindex completes.
76  if (!fReindex && !chainman.ActiveChainstate().LoadGenesisBlock()) {
78  }
79 
80  // At this point we're either in reindex or we've loaded a useful
81  // block tree into BlockIndex()!
82 
83  for (CChainState* chainstate : chainman.GetAll()) {
84  chainstate->InitCoinsDB(
85  /* cache_size_bytes */ nCoinDBCache,
86  /* in_memory */ coins_db_in_memory,
87  /* should_wipe */ fReset || fReindexChainState);
88 
89  if (coins_error_cb) {
90  chainstate->CoinsErrorCatcher().AddReadErrCallback(coins_error_cb);
91  }
92 
93  // If necessary, upgrade from older database format.
94  // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
95  if (!chainstate->CoinsDB().Upgrade()) {
97  }
98 
99  // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
100  if (!chainstate->ReplayBlocks()) {
102  }
103 
104  // The on-disk coinsdb is now in a good state, create the cache
105  chainstate->InitCoinsCache(nCoinCacheUsage);
106  assert(chainstate->CanFlushToDisk());
107 
108  if (!is_coinsview_empty(chainstate)) {
109  // LoadChainTip initializes the chain based on CoinsTip()'s best block
110  if (!chainstate->LoadChainTip()) {
112  }
113  assert(chainstate->m_chain.Tip() != nullptr);
114  }
115  }
116 
117  if (!fReset) {
118  auto chainstates{chainman.GetAll()};
119  if (std::any_of(chainstates.begin(), chainstates.end(),
120  [](const CChainState* cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return cs->NeedsRedownload(); })) {
122  }
123  }
124 
125  return std::nullopt;
126 }
127 
128 std::optional<ChainstateLoadVerifyError> VerifyLoadedChainstate(ChainstateManager& chainman,
129  bool fReset,
130  bool fReindexChainState,
131  const Consensus::Params& consensus_params,
132  unsigned int check_blocks,
133  unsigned int check_level,
134  std::function<int64_t()> get_unix_time_seconds)
135 {
136  auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
137  return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
138  };
139 
140  LOCK(cs_main);
141 
142  for (CChainState* chainstate : chainman.GetAll()) {
143  if (!is_coinsview_empty(chainstate)) {
144  const CBlockIndex* tip = chainstate->m_chain.Tip();
145  if (tip && tip->nTime > get_unix_time_seconds() + MAX_FUTURE_BLOCK_TIME) {
147  }
148 
149  if (!CVerifyDB().VerifyDB(
150  *chainstate, consensus_params, chainstate->CoinsDB(),
151  check_level,
152  check_blocks)) {
154  }
155  }
156  }
157 
158  return std::nullopt;
159 }
160 } // namespace node
MAX_FUTURE_BLOCK_TIME
static constexpr int64_t MAX_FUTURE_BLOCK_TIME
Maximum amount of time that a block timestamp is allowed to exceed the current network-adjusted time ...
Definition: chain.h:22
node::ChainstateLoadingError::ERROR_PRUNED_NEEDS_REINDEX
@ ERROR_PRUNED_NEEDS_REINDEX
node::fPruneMode
bool fPruneMode
True if we're running in -prune mode.
Definition: blockstorage.cpp:28
node::ChainstateLoadingError::ERROR_CHAINSTATE_UPGRADE_FAILED
@ ERROR_CHAINSTATE_UPGRADE_FAILED
chainstate.h
assert
assert(!tx.IsCoinBase())
node::BlockManager::LookupBlockIndex
CBlockIndex * LookupBlockIndex(const uint256 &hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Definition: blockstorage.cpp:35
CBlockIndex::nTime
uint32_t nTime
Definition: chain.h:203
ChainstateManager::m_total_coinstip_cache
int64_t m_total_coinstip_cache
The total number of bytes available for us to use across all in-memory coins caches.
Definition: validation.h:856
node::fHavePruned
bool fHavePruned
Pruning-related variables and constants.
Definition: blockstorage.cpp:27
CTxMemPool
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:429
ChainstateManager::BlockIndex
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:899
node::VerifyLoadedChainstate
std::optional< ChainstateLoadVerifyError > VerifyLoadedChainstate(ChainstateManager &chainman, bool fReset, bool fReindexChainState, const Consensus::Params &consensus_params, unsigned int check_blocks, unsigned int check_level, std::function< int64_t()> get_unix_time_seconds)
Definition: chainstate.cpp:128
ChainstateManager::ActiveChainstate
CChainState & ActiveChainstate() const
The most-work chain.
Definition: validation.cpp:4960
cs
static void pool cs
Definition: mempool_eviction.cpp:12
node::CleanupBlockRevFiles
void CleanupBlockRevFiles()
Definition: blockstorage.cpp:441
Consensus::Params
Parameters that influence chain consensus.
Definition: params.h:70
node::ChainstateLoadingError::SHUTDOWN_PROBED
@ SHUTDOWN_PROBED
node::fReindex
std::atomic_bool fReindex
CBlockTreeDB
Access to the block database (blocks/index/)
Definition: txdb.h:77
node::ChainstateLoadingError::ERROR_BAD_GENESIS_BLOCK
@ ERROR_BAD_GENESIS_BLOCK
ChainstateManager::GetAll
CChainState &InitializeChainstate(CTxMemPool *mempool, const std::optional< uint256 > &snapshot_blockhash=std::nullopt) LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(std::vector< CChainState * GetAll)()
Instantiate a new chainstate and assign it based upon whether it is from a snapshot.
Definition: validation.h:875
CChainState
CChainState stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:443
node::ChainstateLoadingError::ERROR_LOAD_GENESIS_BLOCK_FAILED
@ ERROR_LOAD_GENESIS_BLOCK_FAILED
node::ChainstateLoadingError::ERROR_REPLAYBLOCKS_FAILED
@ ERROR_REPLAYBLOCKS_FAILED
node::ChainstateLoadingError::ERROR_BLOCKS_WITNESS_INSUFFICIENTLY_VALIDATED
@ ERROR_BLOCKS_WITNESS_INSUFFICIENTLY_VALIDATED
ChainstateManager
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:761
CVerifyDB
RAII wrapper for VerifyDB: Verify consistency of the block and coin databases.
Definition: validation.h:356
Consensus::Params::hashGenesisBlock
uint256 hashGenesisBlock
Definition: params.h:71
cs_main
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: validation.cpp:138
EXCLUSIVE_LOCKS_REQUIRED
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
LOCK
#define LOCK(cs)
Definition: sync.h:226
ChainstateManager::LoadBlockIndex
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the block tree and coins database from disk, initializing state if we're running with -reindex.
Definition: validation.cpp:4016
blockstorage.h
params.h
node
Definition: init.h:22
node::ChainstateLoadingError::ERROR_LOADCHAINTIP_FAILED
@ ERROR_LOADCHAINTIP_FAILED
node::ChainstateLoadVerifyError::ERROR_BLOCK_FROM_FUTURE
@ ERROR_BLOCK_FROM_FUTURE
ChainstateManager::m_total_coinsdb_cache
int64_t m_total_coinsdb_cache
The total number of bytes available for us to use across all leveldb coins databases.
Definition: validation.h:860
node::ChainstateLoadingError::ERROR_LOADING_BLOCK_DB
@ ERROR_LOADING_BLOCK_DB
node::ChainstateLoadVerifyError::ERROR_CORRUPTED_BLOCK_DB
@ ERROR_CORRUPTED_BLOCK_DB
UnloadBlockIndex
void UnloadBlockIndex(CTxMemPool *mempool, ChainstateManager &chainman)
Unload database information.
Definition: validation.cpp:4003
CBlockIndex
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:148
CChainState::LoadGenesisBlock
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
Definition: validation.cpp:4039
node::LoadChainstate
std::optional< ChainstateLoadingError > LoadChainstate(bool fReset, ChainstateManager &chainman, CTxMemPool *mempool, bool fPruneMode, const Consensus::Params &consensus_params, bool fReindexChainState, int64_t nBlockTreeDBCache, int64_t nCoinDBCache, int64_t nCoinCacheUsage, bool block_tree_db_in_memory, bool coins_db_in_memory, std::function< bool()> shutdown_requested, std::function< void()> coins_error_cb)
This sequence can have 4 types of outcomes:
Definition: chainstate.cpp:12
ChainstateManager::m_blockman
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:831