Bitcoin Core 28.99.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>
14#include <util/fs.h>
15#include <validation.h>
16
17#include <univalue.h>
18
19const auto NoMalleation = [](AutoFile& file, node::SnapshotMetadata& meta){};
20
31template<typename F = decltype(NoMalleation)>
32static 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);
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{node.chainman->GetParams().MessageStart()};
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.
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 // 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->m_chain_tx_count = 0;
103 pindex->nSequenceId = 0;
104 pindex = pindex->pprev;
105 }
106 }
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 }
114
115 auto& new_active = node.chainman->ActiveChainstate();
116 auto* tip = new_active.m_chain.Tip();
117
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 }
126
127 auto res = node.chainman->ActivateSnapshot(auto_infile, metadata, in_memory_chainstate);
128
129 // Restore the old tip.
130 new_active.m_chain.SetTip(*tip);
131 return !!res;
132}
133
134
135#endif // BITCOIN_TEST_UTIL_CHAINSTATE_H
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.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
Definition: chain.h:97
#define Assert(val)
Identity function.
Definition: check.h:85
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:392
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
uint64_t m_chain_tx_count
(memory only) Number of transactions in the chain up to and including this block.
Definition: chain.h:176
int32_t nSequenceId
(memory only) Sequential id assigned to distinguish order in which blocks are received.
Definition: chain.h:194
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:170
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
Definition: chain.h:295
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:433
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:179
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:505
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:599
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:585
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Definition: validation.h:611
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.
ChainstateRole GetRole() const EXCLUSIVE_LOCKS_REQUIRED(void InitCoinsDB(size_t cache_size_bytes, bool in_memory, bool should_wipe, fs::path leveldb_name="chainstate")
Return the current role of the chainstate.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
std::string ToString() const
Definition: validation.h:112
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:34
256-bit opaque blob.
Definition: uint256.h:190
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:266
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, FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1072
fs::path m_path_root
Definition: setup_common.h:78
node::NodeContext m_node
Definition: setup_common.h:65
Testing setup that configures a complete environment.
Definition: setup_common.h:120
NodeContext struct containing references to chain state and connection state.
Definition: context.h:56
#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:1165
assert(!tx.IsCoinBase())