Bitcoin Core  31.0.0
P2P Digital Currency
chainstate.h
Go to the documentation of this file.
1 // Copyright (c) 2021-present 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.chainman->ActiveChainstate(),
52  std::move(auto_outfile), // Will close auto_outfile.
53  snapshot_path,
54  snapshot_path);
55  LogInfo("Wrote UTXO snapshot to %s: %s",
56  fs::PathToString(snapshot_path.make_preferred()), result.write());
57 
58  // Read the written snapshot in and then activate it.
59  //
60  FILE* infile{fsbridge::fopen(snapshot_path, "rb")};
61  AutoFile auto_infile{infile};
62  node::SnapshotMetadata metadata{node.chainman->GetParams().MessageStart()};
63  auto_infile >> metadata;
64 
65  malleation(auto_infile, metadata);
66 
67  if (reset_chainstate) {
68  {
69  // What follows is code to selectively reset chainstate data without
70  // disturbing the existing BlockManager instance, which is needed to
71  // recognize the headers chain previously generated by the chainstate we're
72  // removing. Without those headers, we can't activate the snapshot below.
73  //
74  // This is a stripped-down version of node::LoadChainstate which
75  // preserves the block index.
76  LOCK(::cs_main);
77  CBlockIndex *orig_tip = node.chainman->ActiveChainstate().m_chain.Tip();
78  uint256 gen_hash = node.chainman->ActiveChainstate().m_chain[0]->GetBlockHash();
79  node.chainman->ResetChainstates();
80  node.chainman->InitializeChainstate(node.mempool.get());
81  Chainstate& chain = node.chainman->ActiveChainstate();
82  Assert(chain.LoadGenesisBlock());
83  // These cache values will be corrected shortly in `MaybeRebalanceCaches`.
84  chain.InitCoinsDB(1 << 20, /*in_memory=*/true, /*should_wipe=*/false);
85  chain.InitCoinsCache(1 << 20);
86  chain.CoinsTip().SetBestBlock(gen_hash);
87  chain.LoadChainTip();
88  node.chainman->MaybeRebalanceCaches();
89 
90  // Reset the HAVE_DATA flags below the snapshot height, simulating
91  // never-having-downloaded them in the first place.
92  // TODO: perhaps we could improve this by using pruning to delete
93  // these blocks instead
94  CBlockIndex *pindex = orig_tip;
95  while (pindex && pindex != chain.m_chain.Tip()) {
96  // Remove all data and validity flags by just setting
97  // BLOCK_VALID_TREE. Also reset transaction counts and sequence
98  // ids that are set when blocks are received, to make test setup
99  // more realistic and satisfy consistency checks in
100  // CheckBlockIndex().
102  pindex->nStatus = BlockStatus::BLOCK_VALID_TREE;
103  pindex->nTx = 0;
104  pindex->m_chain_tx_count = 0;
105  pindex->nSequenceId = 0;
106  pindex = pindex->pprev;
107  }
108  chain.PopulateBlockIndexCandidates();
109  }
110  BlockValidationState state;
111  if (!node.chainman->ActiveChainstate().ActivateBestChain(state)) {
112  throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
113  }
114  Assert(
115  0 == WITH_LOCK(node.chainman->GetMutex(), return node.chainman->ActiveHeight()));
116  }
117 
118  auto& new_active = node.chainman->ActiveChainstate();
119  auto* tip = new_active.m_chain.Tip();
120 
121  // Disconnect a block so that the snapshot chainstate will be ahead, otherwise
122  // it will refuse to activate.
123  //
124  // TODO this is a unittest-specific hack, and we should probably rethink how to
125  // better generate/activate snapshots in unittests.
126  if (tip->pprev) {
127  new_active.m_chain.SetTip(*(tip->pprev));
128  }
129 
130  auto res = node.chainman->ActivateSnapshot(auto_infile, metadata, in_memory_chainstate);
131 
132  // Restore the old tip.
133  new_active.m_chain.SetTip(*tip);
134  return !!res;
135 }
136 
137 
138 #endif // BITCOIN_TEST_UTIL_CHAINSTATE_H
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:686
int32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
Definition: chain.h:149
assert(!tx.IsCoinBase())
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:100
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
All parent headers found, difficulty matches, timestamp >= median previous.
Definition: chain.h:51
fs::path m_path_root
Definition: setup_common.h:79
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:625
void format(std::ostream &out, FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1079
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:372
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:204
UniValue CreateUTXOSnapshot(node::NodeContext &node, Chainstate &chainstate, AutoFile &&afile, const fs::path &path, const fs::path &tmppath)
Test-only helper to create UTXO snapshots given a chainstate and a file handle.
NodeContext struct containing references to chain state and connection state.
Definition: context.h:56
Chainstate stores and provides an API to update our local knowledge of the current best chain...
Definition: validation.h:550
uint64_t m_chain_tx_count
(memory only) Number of transactions in the chain up to and including this block. ...
Definition: chain.h:129
#define LOCK(cs)
Definition: sync.h:258
#define LogInfo(...)
Definition: log.h:95
std::string ToString() const
Definition: validation.h:111
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:289
Definition: messages.h:21
256-bit opaque blob.
Definition: uint256.h:195
auto result
Definition: common-types.h:74
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:93
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:396
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:157
bool IsValid(enum BlockStatus nUpTo) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
Definition: chain.h:250
static path u8path(std::string_view utf8_str)
Definition: fs.h:81
const auto NoMalleation
Definition: chainstate.h:19
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:33
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:66
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:123
Testing setup that configures a complete environment.
Definition: setup_common.h:121
#define Assert(val)
Identity function.
Definition: check.h:113
Metadata describing a serialized version of a UTXO set from which an assumeutxo Chainstate can be con...
Definition: utxo_snapshot.h:37