Bitcoin Core 22.99.0
P2P Digital Currency
utxo_snapshot.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 <chainparams.h>
9#include <test/fuzz/fuzz.h>
10#include <test/fuzz/util.h>
11#include <test/util/mining.h>
13#include <validation.h>
14#include <validationinterface.h>
15
16namespace {
17
18const std::vector<std::shared_ptr<CBlock>>* g_chain;
19
20void initialize_chain()
21{
23 static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)};
24 g_chain = &chain;
25}
26
27FUZZ_TARGET_INIT(utxo_snapshot, initialize_chain)
28{
29 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
30 std::unique_ptr<const TestingSetup> setup{MakeNoLogFileContext<const TestingSetup>()};
31 const auto& node = setup->m_node;
32 auto& chainman{*node.chainman};
33
34 const auto snapshot_path = gArgs.GetDataDirNet() / "fuzzed_snapshot.dat";
35
36 Assert(!chainman.SnapshotBlockhash());
37
38 {
39 CAutoFile outfile{fsbridge::fopen(snapshot_path, "wb"), SER_DISK, CLIENT_VERSION};
40 const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
41 outfile << Span<const uint8_t>{file_data};
42 }
43
44 const auto ActivateFuzzedSnapshot{[&] {
45 CAutoFile infile{fsbridge::fopen(snapshot_path, "rb"), SER_DISK, CLIENT_VERSION};
46 SnapshotMetadata metadata;
47 try {
48 infile >> metadata;
49 } catch (const std::ios_base::failure&) {
50 return false;
51 }
52 return chainman.ActivateSnapshot(infile, metadata, /* in_memory */ true);
53 }};
54
55 if (fuzzed_data_provider.ConsumeBool()) {
56 for (const auto& block : *g_chain) {
58 bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy, ::Params())};
59 Assert(processed);
60 const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
61 Assert(index);
62 }
63 }
64
65 if (ActivateFuzzedSnapshot()) {
66 LOCK(::cs_main);
67 Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash->IsNull());
68 Assert(*chainman.ActiveChainstate().m_from_snapshot_blockhash ==
69 *chainman.SnapshotBlockhash());
70 const auto& coinscache{chainman.ActiveChainstate().CoinsTip()};
71 int64_t chain_tx{};
72 for (const auto& block : *g_chain) {
73 Assert(coinscache.HaveCoin(COutPoint{block->vtx.at(0)->GetHash(), 0}));
74 const auto* index{chainman.m_blockman.LookupBlockIndex(block->GetHash())};
75 const auto num_tx{Assert(index)->nTx};
76 Assert(num_tx == 1);
77 chain_tx += num_tx;
78 }
79 Assert(g_chain->size() == coinscache.GetCacheSize());
80 Assert(chain_tx == chainman.ActiveTip()->nChainTx);
81 } else {
82 Assert(!chainman.SnapshotBlockhash());
83 Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash);
84 }
85 // Snapshot should refuse to load a second time regardless of validity
86 Assert(!ActivateFuzzedSnapshot());
87}
88} // namespace
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: validation.cpp:118
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const std::string &chain)
Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
Definition: check.h:57
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: system.h:288
Non-refcounted RAII wrapper for FILE*.
Definition: streams.h:565
static const std::string REGTEST
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:27
Metadata describing a serialized version of a UTXO set from which an assumeutxo CChainState can be co...
Definition: utxo_snapshot.h:15
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:33
static const int COINBASE_MATURITY
Coinbase transaction outputs can only be spent after this number of new blocks (network rule)
Definition: consensus.h:19
#define FUZZ_TARGET_INIT(name, init_fun)
Definition: fuzz.h:34
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:25
@ SER_DISK
Definition: serialize.h:139
#define LOCK(cs)
Definition: sync.h:226
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:270
std::vector< uint8_t > ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, const std::optional< size_t > &max_length=std::nullopt) noexcept
Definition: util.h:61
std::vector< std::shared_ptr< CBlock > > CreateBlockChain(size_t total_height, const CChainParams &params)
Create a blockchain, starting from genesis.
Definition: mining.cpp:28
ArgsManager gArgs
Definition: system.cpp:85