Bitcoin Core  24.1.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 <chain.h>
8 #include <coins.h>
9 #include <consensus/params.h>
10 #include <node/blockstorage.h>
11 #include <node/caches.h>
12 #include <sync.h>
13 #include <threadsafety.h>
14 #include <tinyformat.h>
15 #include <txdb.h>
16 #include <uint256.h>
17 #include <util/time.h>
18 #include <util/translation.h>
19 #include <validation.h>
20 
21 #include <algorithm>
22 #include <atomic>
23 #include <cassert>
24 #include <memory>
25 #include <vector>
26 
27 namespace node {
29  const ChainstateLoadOptions& options)
30 {
31  auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
32  return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
33  };
34 
35  if (!hashAssumeValid.IsNull()) {
36  LogPrintf("Assuming ancestors of block %s have valid signatures.\n", hashAssumeValid.GetHex());
37  } else {
38  LogPrintf("Validating signatures for all blocks.\n");
39  }
40  LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
42  LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex());
43  }
44  if (nPruneTarget == std::numeric_limits<uint64_t>::max()) {
45  LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
46  } else if (nPruneTarget) {
47  LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
48  }
49 
50  LOCK(cs_main);
51  chainman.InitializeChainstate(options.mempool);
52  chainman.m_total_coinstip_cache = cache_sizes.coins;
53  chainman.m_total_coinsdb_cache = cache_sizes.coins_db;
54 
55  auto& pblocktree{chainman.m_blockman.m_block_tree_db};
56  // new CBlockTreeDB tries to delete the existing file, which
57  // fails if it's still open from the previous loop. Close it first:
58  pblocktree.reset();
59  pblocktree.reset(new CBlockTreeDB(cache_sizes.block_tree_db, options.block_tree_db_in_memory, options.reindex));
60 
61  if (options.reindex) {
62  pblocktree->WriteReindexing(true);
63  //If we're reindexing in prune mode, wipe away unusable block files and all undo data files
64  if (options.prune) {
66  }
67  }
68 
69  if (options.check_interrupt && options.check_interrupt()) return {ChainstateLoadStatus::INTERRUPTED, {}};
70 
71  // LoadBlockIndex will load m_have_pruned if we've ever removed a
72  // block file from disk.
73  // Note that it also sets fReindex global based on the disk flag!
74  // From here on, fReindex and options.reindex values may be different!
75  if (!chainman.LoadBlockIndex()) {
76  if (options.check_interrupt && options.check_interrupt()) return {ChainstateLoadStatus::INTERRUPTED, {}};
77  return {ChainstateLoadStatus::FAILURE, _("Error loading block database")};
78  }
79 
80  if (!chainman.BlockIndex().empty() &&
82  // If the loaded chain has a wrong genesis, bail out immediately
83  // (we're likely using a testnet datadir, or the other way around).
84  return {ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB, _("Incorrect or no genesis block found. Wrong datadir for network?")};
85  }
86 
87  // Check for changed -prune state. What we are concerned about is a user who has pruned blocks
88  // in the past, but is now trying to run unpruned.
89  if (chainman.m_blockman.m_have_pruned && !options.prune) {
90  return {ChainstateLoadStatus::FAILURE, _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain")};
91  }
92 
93  // At this point blocktree args are consistent with what's on disk.
94  // If we're not mid-reindex (based on disk + args), add a genesis block on disk
95  // (otherwise we use the one already on disk).
96  // This is called again in ThreadImport after the reindex completes.
97  if (!fReindex && !chainman.ActiveChainstate().LoadGenesisBlock()) {
98  return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
99  }
100 
101  // At this point we're either in reindex or we've loaded a useful
102  // block tree into BlockIndex()!
103 
104  for (Chainstate* chainstate : chainman.GetAll()) {
105  chainstate->InitCoinsDB(
106  /*cache_size_bytes=*/cache_sizes.coins_db,
107  /*in_memory=*/options.coins_db_in_memory,
108  /*should_wipe=*/options.reindex || options.reindex_chainstate);
109 
110  if (options.coins_error_cb) {
111  chainstate->CoinsErrorCatcher().AddReadErrCallback(options.coins_error_cb);
112  }
113 
114  // Refuse to load unsupported database format.
115  // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
116  if (chainstate->CoinsDB().NeedsUpgrade()) {
117  return {ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB, _("Unsupported chainstate database format found. "
118  "Please restart with -reindex-chainstate. This will "
119  "rebuild the chainstate database.")};
120  }
121 
122  // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
123  if (!chainstate->ReplayBlocks()) {
124  return {ChainstateLoadStatus::FAILURE, _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.")};
125  }
126 
127  // The on-disk coinsdb is now in a good state, create the cache
128  chainstate->InitCoinsCache(cache_sizes.coins);
129  assert(chainstate->CanFlushToDisk());
130 
131  if (!is_coinsview_empty(chainstate)) {
132  // LoadChainTip initializes the chain based on CoinsTip()'s best block
133  if (!chainstate->LoadChainTip()) {
134  return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
135  }
136  assert(chainstate->m_chain.Tip() != nullptr);
137  }
138  }
139 
140  if (!options.reindex) {
141  auto chainstates{chainman.GetAll()};
142  if (std::any_of(chainstates.begin(), chainstates.end(),
143  [](const Chainstate* cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return cs->NeedsRedownload(); })) {
144  return {ChainstateLoadStatus::FAILURE, strprintf(_("Witness data for blocks after height %d requires validation. Please restart with -reindex."),
145  chainman.GetConsensus().SegwitHeight)};
146  };
147  }
148 
149  return {ChainstateLoadStatus::SUCCESS, {}};
150 }
151 
153 {
154  auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
155  return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
156  };
157 
158  LOCK(cs_main);
159 
160  for (Chainstate* chainstate : chainman.GetAll()) {
161  if (!is_coinsview_empty(chainstate)) {
162  const CBlockIndex* tip = chainstate->m_chain.Tip();
163  if (tip && tip->nTime > GetTime() + MAX_FUTURE_BLOCK_TIME) {
164  return {ChainstateLoadStatus::FAILURE, _("The block database contains a block which appears to be from the future. "
165  "This may be due to your computer's date and time being set incorrectly. "
166  "Only rebuild the block database if you are sure that your computer's date and time are correct")};
167  }
168 
169  if (!CVerifyDB().VerifyDB(
170  *chainstate, chainman.GetConsensus(), chainstate->CoinsDB(),
171  options.check_level,
172  options.check_blocks)) {
173  return {ChainstateLoadStatus::FAILURE, _("Corrupted block database detected")};
174  }
175  }
176  }
177 
178  return {ChainstateLoadStatus::SUCCESS, {}};
179 }
180 } // namespace node
void CleanupBlockRevFiles()
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:898
assert(!tx.IsCoinBase())
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
std::atomic_bool fReindex
int64_t block_tree_db
Definition: caches.h:15
ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager &chainman, const ChainstateLoadOptions &options)
Definition: chainstate.cpp:152
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:799
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
static void pool cs
arith_uint256 nMinimumChainWork
Minimum work we will assume exists on some valid chain.
Definition: validation.cpp:132
uint32_t nTime
Definition: chain.h:206
std::function< bool()> check_interrupt
Definition: chainstate.h:30
bool IsNull() const
Definition: uint256.h:34
arith_uint256 UintToArith256(const uint256 &a)
uint64_t nPruneTarget
Number of bytes of block files that we&#39;re trying to stay below.
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:437
Access to the block database (blocks/index/)
Definition: txdb.h:78
#define LOCK(cs)
Definition: sync.h:261
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:65
bool LoadBlockIndex() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Load the block tree and coins database from disk, initializing state if we&#39;re running with -reindex...
RAII wrapper for VerifyDB: Verify consistency of the block and coin databases.
Definition: validation.h:350
const Consensus::Params & GetConsensus() const
Definition: validation.h:879
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Chainstate &InitializeChainstate(CTxMemPool *mempool, const std::optional< uint256 > &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:945
int64_t coins
Definition: caches.h:17
uint256 hashAssumeValid
Block hash whose ancestors we will assume to have valid scripts without checking them.
Definition: validation.cpp:131
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:926
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:969
Definition: init.h:25
std::function< void()> coins_error_cb
Definition: chainstate.h:31
uint256 nMinimumChainWork
The best chain should have at least this much work.
Definition: params.h:119
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
const CBlockIndex *GetFirstStoredBlock(const CBlockIndex &start_block LIFETIMEBOUND) EXCLUSIVE_LOCKS_REQUIRED(bool m_have_pruned
Find the first block that is not pruned.
Definition: blockstorage.h:186
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:151
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: validation.cpp:121
std::string GetHex() const
Definition: uint256.cpp:20
int SegwitHeight
Block height at which Segwit (BIP141, BIP143 and BIP147) becomes active.
Definition: params.h:95
std::string GetHex() const
std::tuple< ChainstateLoadStatus, bilingual_str > ChainstateLoadResult
Chainstate load status code and optional error string.
Definition: chainstate.h:41
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:23
ChainstateLoadResult LoadChainstate(ChainstateManager &chainman, const CacheSizes &cache_sizes, const ChainstateLoadOptions &options)
This sequence can have 4 types of outcomes:
Definition: chainstate.cpp:28
Chainstate & ActiveChainstate() const
The most-work chain.
int64_t m_total_coinsdb_cache
The total number of bytes available for us to use across all leveldb coins databases.
Definition: validation.h:930
int64_t coins_db
Definition: caches.h:16
#define LogPrintf(...)
Definition: logging.h:234
int64_t GetTime()
DEPRECATED, see GetTime.
Definition: time.cpp:117
uint256 hashGenesisBlock
Definition: params.h:74