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