Skip to content

Commit 63b534f

Browse files
committed
fuzz: sanity check hardcoded snapshot in utxo_snapshot target
The assumeutxo data for the fuzz target could change and invalidate the hash silently, preventing the fuzz target from reaching some code paths. Fix this by sanity checking the snapshot values during initialization.
1 parent 3b85eba commit 63b534f

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

src/test/fuzz/utxo_snapshot.cpp

+30-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <coins.h>
88
#include <consensus/consensus.h>
99
#include <consensus/validation.h>
10+
#include <kernel/coinstats.h>
1011
#include <node/blockstorage.h>
1112
#include <node/utxo_snapshot.h>
1213
#include <primitives/block.h>
@@ -39,14 +40,42 @@ using node::SnapshotMetadata;
3940
namespace {
4041

4142
const std::vector<std::shared_ptr<CBlock>>* g_chain;
42-
TestingSetup* g_setup;
43+
TestingSetup* g_setup{nullptr};
44+
45+
/** Sanity check the assumeutxo values hardcoded in chainparams for the fuzz target. */
46+
void sanity_check_snapshot()
47+
{
48+
Assert(g_chain && g_setup == nullptr);
49+
50+
// Create a temporary chainstate manager to connect the chain to.
51+
const auto tmp_setup{MakeNoLogFileContext<TestingSetup>(ChainType::REGTEST, TestOpts{.setup_net = false})};
52+
const auto& node{tmp_setup->m_node};
53+
for (auto& block: *g_chain) {
54+
ProcessBlock(node, block);
55+
}
56+
57+
// Connect the chain to the tmp chainman and sanity check the chainparams snapshot values.
58+
LOCK(cs_main);
59+
auto& cs{node.chainman->ActiveChainstate()};
60+
cs.ForceFlushStateToDisk();
61+
const auto stats{*Assert(kernel::ComputeUTXOStats(kernel::CoinStatsHashType::HASH_SERIALIZED, &cs.CoinsDB(), node.chainman->m_blockman))};
62+
const auto cp_au_data{*Assert(node.chainman->GetParams().AssumeutxoForHeight(2 * COINBASE_MATURITY))};
63+
Assert(stats.nHeight == cp_au_data.height);
64+
Assert(stats.nTransactions + 1 == cp_au_data.m_chain_tx_count); // +1 for the genesis tx.
65+
Assert(stats.hashBlock == cp_au_data.blockhash);
66+
Assert(AssumeutxoHash{stats.hashSerialized} == cp_au_data.hash_serialized);
67+
}
4368

4469
template <bool INVALID>
4570
void initialize_chain()
4671
{
4772
const auto params{CreateChainParams(ArgsManager{}, ChainType::REGTEST)};
4873
static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)};
4974
g_chain = &chain;
75+
76+
// Make sure we can generate a valid snapshot.
77+
sanity_check_snapshot();
78+
5079
static const auto setup{
5180
MakeNoLogFileContext<TestingSetup>(ChainType::REGTEST,
5281
TestOpts{

0 commit comments

Comments
 (0)