Branch data Line data Source code
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 : : #include <chainparams.h> 6 : : #include <consensus/validation.h> 7 : : #include <node/utxo_snapshot.h> 8 : : #include <test/fuzz/FuzzedDataProvider.h> 9 : : #include <test/fuzz/fuzz.h> 10 : : #include <test/fuzz/util.h> 11 : : #include <test/util/mining.h> 12 : : #include <test/util/setup_common.h> 13 : : #include <util/chaintype.h> 14 : : #include <util/fs.h> 15 : : #include <validation.h> 16 : : #include <validationinterface.h> 17 [ + - ]: 2 : 18 [ + - ]: 2 : using node::SnapshotMetadata; 19 : : 20 : : namespace { 21 : : 22 : : const std::vector<std::shared_ptr<CBlock>>* g_chain; 23 : : 24 : 0 : void initialize_chain() 25 : : { 26 [ # # ]: 0 : const auto params{CreateChainParams(ArgsManager{}, ChainType::REGTEST)}; 27 [ # # ][ # # ]: 0 : static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)}; [ # # ] 28 : 0 : g_chain = &chain; 29 : 0 : } 30 : : 31 [ + - ]: 4 : FUZZ_TARGET(utxo_snapshot, .init = initialize_chain) 32 : : { 33 : 0 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); 34 [ # # ]: 0 : std::unique_ptr<const TestingSetup> setup{MakeNoLogFileContext<const TestingSetup>()}; 35 : 0 : const auto& node = setup->m_node; 36 : 0 : auto& chainman{*node.chainman}; 37 : : 38 [ # # ][ # # ]: 0 : const auto snapshot_path = gArgs.GetDataDirNet() / "fuzzed_snapshot.dat"; [ # # ] 39 : : 40 [ # # ][ # # ]: 0 : Assert(!chainman.SnapshotBlockhash()); 41 : : 42 : : { 43 [ # # ][ # # ]: 0 : AutoFile outfile{fsbridge::fopen(snapshot_path, "wb")}; 44 : 0 : const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)}; 45 [ # # ][ # # ]: 0 : outfile << Span{file_data}; 46 : 0 : } 47 : : 48 : 0 : const auto ActivateFuzzedSnapshot{[&] { 49 [ # # ]: 0 : AutoFile infile{fsbridge::fopen(snapshot_path, "rb")}; 50 [ # # ]: 2 : SnapshotMetadata metadata; 51 : : try { 52 [ # # ]: 0 : infile >> metadata; 53 [ # # ]: 0 : } catch (const std::ios_base::failure&) { 54 : 0 : return false; 55 [ # # ]: 0 : } 56 [ # # ]: 0 : return chainman.ActivateSnapshot(infile, metadata, /*in_memory=*/true); 57 : 0 : }}; 58 : : 59 [ # # ][ # # ]: 0 : if (fuzzed_data_provider.ConsumeBool()) { 60 [ # # ]: 0 : for (const auto& block : *g_chain) { 61 : 0 : BlockValidationState dummy; 62 [ # # ][ # # ]: 0 : bool processed{chainman.ProcessNewBlockHeaders({*block}, true, dummy)}; 63 [ # # ]: 0 : Assert(processed); 64 [ # # ][ # # ]: 0 : const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))}; [ # # ][ # # ] 65 [ # # ]: 0 : Assert(index); 66 : 0 : } 67 : 0 : } 68 : : 69 [ # # ][ # # ]: 0 : if (ActivateFuzzedSnapshot()) { 70 [ # # ][ # # ]: 0 : LOCK(::cs_main); 71 [ # # ][ # # ]: 0 : Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash->IsNull()); [ # # ] 72 [ # # ][ # # ]: 0 : Assert(*chainman.ActiveChainstate().m_from_snapshot_blockhash == [ # # ][ # # ] 73 : : *chainman.SnapshotBlockhash()); 74 [ # # ][ # # ]: 0 : const auto& coinscache{chainman.ActiveChainstate().CoinsTip()}; 75 : 0 : int64_t chain_tx{}; 76 [ # # ]: 0 : for (const auto& block : *g_chain) { 77 [ # # ][ # # ]: 0 : Assert(coinscache.HaveCoin(COutPoint{block->vtx.at(0)->GetHash(), 0})); [ # # ][ # # ] [ # # ][ # # ] 78 [ # # ][ # # ]: 0 : const auto* index{chainman.m_blockman.LookupBlockIndex(block->GetHash())}; 79 [ # # ]: 0 : const auto num_tx{Assert(index)->nTx}; 80 [ # # ]: 0 : Assert(num_tx == 1); 81 : 0 : chain_tx += num_tx; 82 : : } 83 [ # # ][ # # ]: 0 : Assert(g_chain->size() == coinscache.GetCacheSize()); 84 [ # # ][ # # ]: 0 : Assert(chain_tx == chainman.ActiveTip()->nChainTx); 85 : 0 : } else { 86 [ # # ][ # # ]: 0 : Assert(!chainman.SnapshotBlockhash()); 87 [ # # ][ # # ]: 0 : Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash); 88 : : } 89 : : // Snapshot should refuse to load a second time regardless of validity 90 [ # # ][ # # ]: 0 : Assert(!ActivateFuzzedSnapshot()); 91 : 0 : } 92 : : } // namespace