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 [ + - ]: 173 : 18 [ + - ]: 173 : using node::SnapshotMetadata; 19 : : 20 : : namespace { 21 : : 22 : : const std::vector<std::shared_ptr<CBlock>>* g_chain; 23 : : 24 : 1 : void initialize_chain() 25 : : { 26 [ + - ]: 1 : const auto params{CreateChainParams(ArgsManager{}, ChainType::REGTEST)}; 27 [ + - - + : 1 : static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)}; + - + - ] 28 : 1 : g_chain = &chain; 29 : 1 : } 30 : : 31 [ + - - + ]: 554 : FUZZ_TARGET(utxo_snapshot, .init = initialize_chain) 32 : : { 33 : 208 : FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); 34 [ + - ]: 208 : std::unique_ptr<const TestingSetup> setup{MakeNoLogFileContext<const TestingSetup>()}; 35 : 208 : const auto& node = setup->m_node; 36 [ + - ]: 208 : auto& chainman{*node.chainman}; 37 : : 38 [ + - + - : 208 : const auto snapshot_path = gArgs.GetDataDirNet() / "fuzzed_snapshot.dat"; + - ] 39 : : 40 [ + - + - ]: 208 : Assert(!chainman.SnapshotBlockhash()); 41 : : 42 : : { 43 [ + - - + ]: 208 : AutoFile outfile{fsbridge::fopen(snapshot_path, "wb")}; 44 : 208 : const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)}; 45 [ + - + - ]: 208 : outfile << Span{file_data}; 46 : 208 : } 47 : : 48 : 624 : const auto ActivateFuzzedSnapshot{[&] { 49 [ + - ]: 416 : AutoFile infile{fsbridge::fopen(snapshot_path, "rb")}; 50 [ + - ]: 416 : SnapshotMetadata metadata; 51 : 173 : try { 52 [ + + ]: 416 : infile >> metadata; 53 [ + - ]: 416 : } catch (const std::ios_base::failure&) { 54 : 106 : return false; 55 [ + - ]: 106 : } 56 [ + - ]: 310 : return chainman.ActivateSnapshot(infile, metadata, /*in_memory=*/true); 57 : 522 : }}; 58 : : 59 [ + - + + ]: 208 : if (fuzzed_data_provider.ConsumeBool()) { 60 [ + + ]: 37386 : for (const auto& block : *g_chain) { 61 : 37200 : BlockValidationState dummy; 62 [ + - + - ]: 37200 : bool processed{chainman.ProcessNewBlockHeaders({*block}, true, dummy)}; 63 [ + - ]: 37200 : Assert(processed); 64 [ + - + - : 74400 : const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))}; + - + - ] 65 [ + - ]: 37200 : Assert(index); 66 : 37200 : } 67 : 186 : } 68 : : 69 [ + - - + ]: 208 : 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 [ # # # # ]: 173 : 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 [ + - + - ]: 208 : Assert(!chainman.SnapshotBlockhash()); 87 [ + - + - ]: 208 : Assert(!chainman.ActiveChainstate().m_from_snapshot_blockhash); 88 : : } 89 : : // Snapshot should refuse to load a second time regardless of validity 90 [ + - + - ]: 208 : Assert(!ActivateFuzzedSnapshot()); 91 : 208 : } 92 : : } // namespace