From 63b534f97e591d4e107fd5148909852eb2965d27 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Thu, 20 Feb 2025 10:19:18 -0500 Subject: [PATCH] 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. --- src/test/fuzz/utxo_snapshot.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp index 5a9df1e48a4..825fada9dda 100644 --- a/src/test/fuzz/utxo_snapshot.cpp +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,31 @@ using node::SnapshotMetadata; namespace { const std::vector>* g_chain; -TestingSetup* g_setup; +TestingSetup* g_setup{nullptr}; + +/** Sanity check the assumeutxo values hardcoded in chainparams for the fuzz target. */ +void sanity_check_snapshot() +{ + Assert(g_chain && g_setup == nullptr); + + // Create a temporary chainstate manager to connect the chain to. + const auto tmp_setup{MakeNoLogFileContext(ChainType::REGTEST, TestOpts{.setup_net = false})}; + const auto& node{tmp_setup->m_node}; + for (auto& block: *g_chain) { + ProcessBlock(node, block); + } + + // Connect the chain to the tmp chainman and sanity check the chainparams snapshot values. + LOCK(cs_main); + auto& cs{node.chainman->ActiveChainstate()}; + cs.ForceFlushStateToDisk(); + const auto stats{*Assert(kernel::ComputeUTXOStats(kernel::CoinStatsHashType::HASH_SERIALIZED, &cs.CoinsDB(), node.chainman->m_blockman))}; + const auto cp_au_data{*Assert(node.chainman->GetParams().AssumeutxoForHeight(2 * COINBASE_MATURITY))}; + Assert(stats.nHeight == cp_au_data.height); + Assert(stats.nTransactions + 1 == cp_au_data.m_chain_tx_count); // +1 for the genesis tx. + Assert(stats.hashBlock == cp_au_data.blockhash); + Assert(AssumeutxoHash{stats.hashSerialized} == cp_au_data.hash_serialized); +} template void initialize_chain() @@ -47,6 +72,10 @@ void initialize_chain() const auto params{CreateChainParams(ArgsManager{}, ChainType::REGTEST)}; static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)}; g_chain = &chain; + + // Make sure we can generate a valid snapshot. + sanity_check_snapshot(); + static const auto setup{ MakeNoLogFileContext(ChainType::REGTEST, TestOpts{