Bitcoin Core  26.1.0
P2P Digital Currency
chainstate.h
Go to the documentation of this file.
1 // Copyright (c) 2021-2022 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 #ifndef BITCOIN_TEST_UTIL_CHAINSTATE_H
6 #define BITCOIN_TEST_UTIL_CHAINSTATE_H
7 
8 #include <clientversion.h>
9 #include <logging.h>
10 #include <node/context.h>
11 #include <node/utxo_snapshot.h>
12 #include <rpc/blockchain.h>
13 #include <test/util/setup_common.h>
14 #include <util/fs.h>
15 #include <validation.h>
16 
17 #include <univalue.h>
18 
19 const auto NoMalleation = [](AutoFile& file, node::SnapshotMetadata& meta){};
20 
31 template<typename F = decltype(NoMalleation)>
32 static bool
34  TestingSetup* fixture,
35  F malleation = NoMalleation,
36  bool reset_chainstate = false,
37  bool in_memory_chainstate = false)
38 {
39  node::NodeContext& node = fixture->m_node;
40  fs::path root = fixture->m_path_root;
41 
42  // Write out a snapshot to the test's tempdir.
43  //
44  int height;
45  WITH_LOCK(::cs_main, height = node.chainman->ActiveHeight());
46  fs::path snapshot_path = root / fs::u8path(tfm::format("test_snapshot.%d.dat", height));
47  FILE* outfile{fsbridge::fopen(snapshot_path, "wb")};
48  AutoFile auto_outfile{outfile};
49 
51  node, node.chainman->ActiveChainstate(), auto_outfile, snapshot_path, snapshot_path);
52  LogPrintf(
53  "Wrote UTXO snapshot to %s: %s\n", fs::PathToString(snapshot_path.make_preferred()), result.write());
54 
55  // Read the written snapshot in and then activate it.
56  //
57  FILE* infile{fsbridge::fopen(snapshot_path, "rb")};
58  AutoFile auto_infile{infile};
59  node::SnapshotMetadata metadata;
60  auto_infile >> metadata;
61 
62  malleation(auto_infile, metadata);
63 
64  if (reset_chainstate) {
65  {
66  // What follows is code to selectively reset chainstate data without
67  // disturbing the existing BlockManager instance, which is needed to
68  // recognize the headers chain previously generated by the chainstate we're
69  // removing. Without those headers, we can't activate the snapshot below.
70  //
71  // This is a stripped-down version of node::LoadChainstate which
72  // preserves the block index.
73  LOCK(::cs_main);
74  CBlockIndex *orig_tip = node.chainman->ActiveChainstate().m_chain.Tip();
75  uint256 gen_hash = node.chainman->ActiveChainstate().m_chain[0]->GetBlockHash();
76  node.chainman->ResetChainstates();
77  node.chainman->InitializeChainstate(node.mempool.get());
78  Chainstate& chain = node.chainman->ActiveChainstate();
79  Assert(chain.LoadGenesisBlock());
80  // These cache values will be corrected shortly in `MaybeRebalanceCaches`.
81  chain.InitCoinsDB(1 << 20, true, false, "");
82  chain.InitCoinsCache(1 << 20);
83  chain.CoinsTip().SetBestBlock(gen_hash);
84  chain.setBlockIndexCandidates.insert(node.chainman->m_blockman.LookupBlockIndex(gen_hash));
85  chain.LoadChainTip();
86  node.chainman->MaybeRebalanceCaches();
87 
88  // Reset the HAVE_DATA flags below the snapshot height, simulating
89  // never-having-downloaded them in the first place.
90  // TODO: perhaps we could improve this by using pruning to delete
91  // these blocks instead
92  CBlockIndex *pindex = orig_tip;
93  while (pindex && pindex != chain.m_chain.Tip()) {
94  pindex->nStatus &= ~BLOCK_HAVE_DATA;
95  pindex->nStatus &= ~BLOCK_HAVE_UNDO;
96  // We have to set the ASSUMED_VALID flag, because otherwise it
97  // would not be possible to have a block index entry without HAVE_DATA
98  // and with nTx > 0 (since we aren't setting the pruned flag);
99  // see CheckBlockIndex().
100  pindex->nStatus |= BLOCK_ASSUMED_VALID;
101  pindex = pindex->pprev;
102  }
103  }
104  BlockValidationState state;
105  if (!node.chainman->ActiveChainstate().ActivateBestChain(state)) {
106  throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
107  }
108  Assert(
109  0 == WITH_LOCK(node.chainman->GetMutex(), return node.chainman->ActiveHeight()));
110  }
111 
112  auto& new_active = node.chainman->ActiveChainstate();
113  auto* tip = new_active.m_chain.Tip();
114 
115  // Disconnect a block so that the snapshot chainstate will be ahead, otherwise
116  // it will refuse to activate.
117  //
118  // TODO this is a unittest-specific hack, and we should probably rethink how to
119  // better generate/activate snapshots in unittests.
120  if (tip->pprev) {
121  new_active.m_chain.SetTip(*(tip->pprev));
122  }
123 
124  bool res = node.chainman->ActivateSnapshot(auto_infile, metadata, in_memory_chainstate);
125 
126  // Restore the old tip.
127  new_active.m_chain.SetTip(*tip);
128  return res;
129 }
130 
131 
132 #endif // BITCOIN_TEST_UTIL_CHAINSTATE_H
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:575
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:25
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:151
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162
UniValue CreateUTXOSnapshot(NodeContext &node, Chainstate &chainstate, AutoFile &afile, const fs::path &path, const fs::path &temppath)
Helper to create UTXO snapshots given a chainstate and a file handle.
undo data available in rev*.dat
Definition: chain.h:113
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:550
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:470
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:178
NodeContext struct containing references to chain state and connection state.
Definition: context.h:48
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:150
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:469
#define LOCK(cs)
Definition: sync.h:258
std::string ToString() const
Definition: validation.h:127
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1060
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Update the chain tip based on database information, i.e.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:302
Definition: init.h:25
const CBlockIndex *SnapshotBase() EXCLUSIVE_LOCKS_REQUIRED(std::set< CBlockIndex *, node::CBlockIndexWorkComparator > setBlockIndexCandidates
The base of the snapshot this chainstate was created from.
Definition: validation.h:564
256-bit opaque blob.
Definition: uint256.h:106
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:144
static bool CreateAndActivateUTXOSnapshot(TestingSetup *fixture, F malleation=NoMalleation, bool reset_chainstate=false, bool in_memory_chainstate=false)
Create and activate a UTXO snapshot, optionally providing a function to malleate the snapshot...
Definition: chainstate.h:33
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:458
const auto NoMalleation
Definition: chainstate.h:19
full block available in blk*.dat
Definition: chain.h:112
static path u8path(const std::string &utf8_str)
Definition: fs.h:70
#define LogPrintf(...)
Definition: logging.h:237
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
If ASSUMED_VALID is set, it means that this block has not been validated and has validity status less...
Definition: chain.h:136
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: cs_main.cpp:8
node::NodeContext m_node
Definition: setup_common.h:50
Testing setup that configures a complete environment.
Definition: setup_common.h:77
#define Assert(val)
Identity function.
Definition: check.h:73
Metadata describing a serialized version of a UTXO set from which an assumeutxo Chainstate can be con...
Definition: utxo_snapshot.h:24
const fs::path m_path_root
Definition: setup_common.h:55