Bitcoin ABC  0.26.3
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 <config.h>
8 #include <consensus/params.h>
9 #include <node/blockstorage.h>
10 #include <validation.h>
11 
12 namespace node {
13 std::optional<ChainstateLoadingError>
14 LoadChainstate(bool fReset, ChainstateManager &chainman, CTxMemPool *mempool,
15  bool fPruneMode_, const Consensus::Params &consensus_params,
16  bool fReindexChainState, int64_t nBlockTreeDBCache,
17  int64_t nCoinDBCache, int64_t nCoinCacheUsage,
18  bool block_tree_db_in_memory, bool coins_db_in_memory,
19  std::function<bool()> shutdown_requested,
20  std::function<void()> coins_error_cb) {
21  auto is_coinsview_empty =
22  [&](Chainstate *chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
23  return fReset || fReindexChainState ||
24  chainstate->CoinsTip().GetBestBlock().IsNull();
25  };
26 
27  LOCK(cs_main);
28  chainman.InitializeChainstate(mempool);
29  chainman.m_total_coinstip_cache = nCoinCacheUsage;
30  chainman.m_total_coinsdb_cache = nCoinDBCache;
31 
32  auto &pblocktree{chainman.m_blockman.m_block_tree_db};
33  // new CBlockTreeDB tries to delete the existing file, which
34  // fails if it's still open from the previous loop. Close it first:
35  pblocktree.reset();
36  pblocktree.reset(
37  new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset));
38 
39  if (fReset) {
40  pblocktree->WriteReindexing(true);
41  // If we're reindexing in prune mode, wipe away unusable block
42  // files and all undo data files
43  if (fPruneMode_) {
45  }
46  }
47 
48  // If necessary, upgrade from older database format.
49  // This is a no-op if we cleared the block tree db with -reindex
50  // or -reindex-chainstate
51  if (!pblocktree->Upgrade(consensus_params)) {
53  }
54 
55  if (shutdown_requested && shutdown_requested()) {
57  }
58 
59  // LoadBlockIndex will load m_have_pruned if we've ever removed a
60  // block file from disk.
61  // Note that it also sets fReindex based on the disk flag!
62  // From here on out fReindex and fReset mean something different!
63  if (!chainman.LoadBlockIndex()) {
64  if (shutdown_requested && shutdown_requested()) {
66  }
68  }
69 
70  if (!chainman.BlockIndex().empty() &&
71  !chainman.m_blockman.LookupBlockIndex(
72  consensus_params.hashGenesisBlock)) {
74  }
75 
76  // Check for changed -prune state. What we are concerned about is a
77  // user who has pruned blocks in the past, but is now trying to run
78  // unpruned.
79  if (chainman.m_blockman.m_have_pruned && !fPruneMode_) {
81  }
82 
83  // At this point blocktree args are consistent with what's on disk.
84  // If we're not mid-reindex (based on disk + args), add a genesis
85  // block on disk (otherwise we use the one already on disk). This is
86  // called again in ThreadImport after the reindex completes.
87  if (!fReindex && !chainman.ActiveChainstate().LoadGenesisBlock()) {
89  }
90 
91  // At this point we're either in reindex or we've loaded a useful
92  // block tree into BlockIndex()!
93 
94  for (Chainstate *chainstate : chainman.GetAll()) {
95  chainstate->InitCoinsDB(
96  /* cache_size_bytes */ nCoinDBCache,
97  /* in_memory */ coins_db_in_memory,
98  /* should_wipe */ fReset || fReindexChainState);
99 
100  if (coins_error_cb) {
101  chainstate->CoinsErrorCatcher().AddReadErrCallback(coins_error_cb);
102  }
103 
104  // If necessary, upgrade from older database format.
105  // This is a no-op if we cleared the coinsviewdb with -reindex
106  // or -reindex-chainstate
107  if (!chainstate->CoinsDB().Upgrade()) {
109  }
110 
111  // ReplayBlocks is a no-op if we cleared the coinsviewdb with
112  // -reindex or -reindex-chainstate
113  if (!chainstate->ReplayBlocks()) {
115  }
116 
117  // The on-disk coinsdb is now in a good state, create the cache
118  chainstate->InitCoinsCache(nCoinCacheUsage);
119  assert(chainstate->CanFlushToDisk());
120 
121  if (!is_coinsview_empty(chainstate)) {
122  // LoadChainTip initializes the chain based on CoinsTip()'s
123  // best block
124  if (!chainstate->LoadChainTip()) {
126  }
127  assert(chainstate->m_chain.Tip() != nullptr);
128  }
129  }
130 
131  return std::nullopt;
132 }
133 
134 std::optional<ChainstateLoadVerifyError>
136  bool fReindexChainState, const Config &config,
137  unsigned int check_blocks, unsigned int check_level,
138  std::function<int64_t()> get_unix_time_seconds) {
139  auto is_coinsview_empty =
140  [&](Chainstate *chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
141  return fReset || fReindexChainState ||
142  chainstate->CoinsTip().GetBestBlock().IsNull();
143  };
144 
145  LOCK(cs_main);
146 
147  for (Chainstate *chainstate : chainman.GetAll()) {
148  if (!is_coinsview_empty(chainstate)) {
149  const CBlockIndex *tip = chainstate->m_chain.Tip();
150  if (tip &&
151  tip->nTime > get_unix_time_seconds() + MAX_FUTURE_BLOCK_TIME) {
153  }
154 
155  if (!CVerifyDB().VerifyDB(*chainstate, config,
156  chainstate->CoinsDB(), check_level,
157  check_blocks)) {
159  }
160  }
161  }
162 
163  return std::nullopt;
164 }
165 } // namespace node
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:113
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:28
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:26
uint32_t nTime
Definition: blockindex.h:93
Access to the block database (blocks/index/)
Definition: txdb.h:106
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:355
RAII wrapper for VerifyDB: Verify consistency of the block and coin databases.
Definition: validation.h:573
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:647
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1062
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:1160
int64_t m_total_coinsdb_cache
The total number of bytes available for us to use across all leveldb coins databases.
Definition: validation.h:1164
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:1205
Chainstate & ActiveChainstate() const
The most-work chain.
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the block tree and coins database from disk, initializing state if we're running with -reindex.
Chainstate &InitializeChainstate(CTxMemPool *mempool, const std::optional< BlockHash > &snapshot_blockhash=std::nullopt) LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(std::vector< Chainstate * GetAll)()
Instantiate a new chainstate and assign it based upon whether it is from a snapshot.
Definition: validation.h:1180
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1129
Definition: config.h:17
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool m_have_pruned
True if any block files have ever been pruned.
Definition: blockstorage.h:193
Definition: init.h:28
const CBlockIndex *GetFirstStoredBlock(const CBlockIndex *start_block) EXCLUSIVE_LOCKS_REQUIRED(voi CleanupBlockRevFiles)()
Find the first block that is not pruned.
Definition: blockstorage.h:205
std::optional< ChainstateLoadVerifyError > VerifyLoadedChainstate(ChainstateManager &chainman, bool fReset, bool fReindexChainState, const Config &config, unsigned int check_blocks, unsigned int check_level, std::function< int64_t()> get_unix_time_seconds)
Definition: chainstate.cpp:135
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:14
std::atomic_bool fReindex
Parameters that influence chain consensus.
Definition: params.h:33
BlockHash hashGenesisBlock
Definition: params.h:34
#define LOCK(cs)
Definition: sync.h:243
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
assert(!tx.IsCoinBase())