LCOV - code coverage report
Current view: top level - src/test/fuzz - utxo_snapshot.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 5 56 8.9 %
Date: 2023-09-26 12:08:55 Functions: 6 10 60.0 %

          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           0 :         SnapshotMetadata metadata;
      51           2 :         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           2 :         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

Generated by: LCOV version 1.14