Bitcoin Core  27.99.0
P2P Digital Currency
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
4 //
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>
17 #include <univalue.h>
19 const auto NoMalleation = [](AutoFile& file, node::SnapshotMetadata& meta){};
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;
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};
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());
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{node.chainman->GetParams().MessageStart()};
60  auto_infile >> metadata;
62  malleation(auto_infile, metadata);
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();
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  // Remove all data and validity flags by just setting
95  // BLOCK_VALID_TREE. Also reset transaction counts and sequence
96  // ids that are set when blocks are received, to make test setup
97  // more realistic and satisfy consistency checks in
98  // CheckBlockIndex().
100  pindex->nStatus = BlockStatus::BLOCK_VALID_TREE;
101  pindex->nTx = 0;
102  pindex->nChainTx = 0;
103  pindex->nSequenceId = 0;
104  pindex = pindex->pprev;
105  }
106  }
107  BlockValidationState state;
108  if (!node.chainman->ActiveChainstate().ActivateBestChain(state)) {
109  throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
110  }
111  Assert(
112  0 == WITH_LOCK(node.chainman->GetMutex(), return node.chainman->ActiveHeight()));
113  }
115  auto& new_active = node.chainman->ActiveChainstate();
116  auto* tip = new_active.m_chain.Tip();
118  // Disconnect a block so that the snapshot chainstate will be ahead, otherwise
119  // it will refuse to activate.
120  //
121  // TODO this is a unittest-specific hack, and we should probably rethink how to
122  // better generate/activate snapshots in unittests.
123  if (tip->pprev) {
124  new_active.m_chain.SetTip(*(tip->pprev));
125  }
127  bool res = node.chainman->ActivateSnapshot(auto_infile, metadata, in_memory_chainstate);
129  // Restore the old tip.
130  new_active.m_chain.SetTip(*tip);
131  return res;
132 }
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.
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
Definition: chain.h:97
#define Assert(val)
Identity function.
Definition: check.h:77
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:389
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:141
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:147
int32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
Definition: chain.h:195
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:170
Check whether this block index entry is valid up to the passed validity level.
Definition: chain.h:296
unsigned int nChainTx
(memory only) Number of transactions in the chain up to and including this block.
Definition: chain.h:177
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:434
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:177
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:490
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:584
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:570
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Update the chain tip based on database information, i.e.
bool LoadGenesisBlock()
Ensures we have a genesis block in the block tree, possibly writing one to disk.
Definition: validation.h:596
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
std::string ToString() const
Definition: validation.h:128
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:33
path & make_preferred()
Definition: fs.h:71
Metadata describing a serialized version of a UTXO set from which an assumeutxo Chainstate can be con...
Definition: utxo_snapshot.h:32
256-bit opaque blob.
Definition: uint256.h:106
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:8
#define LogPrintf(...)
Definition: logging.h:244
static path u8path(const std::string &utf8_str)
Definition: fs.h:75
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:151
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:26
Definition: messages.h:20
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
fs::path m_path_root
Definition: setup_common.h:61
node::NodeContext m_node
Definition: setup_common.h:56
Testing setup that configures a complete environment.
Definition: setup_common.h:85
NodeContext struct containing references to chain state and connection state.
Definition: context.h:53
#define LOCK(cs)
Definition: sync.h:257
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
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
const auto NoMalleation
Definition: chainstate.h:19
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162