LCOV - code coverage report
Current view: top level - src/test/fuzz - block_index.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 76 77 98.7 %
Date: 2024-01-03 14:54:42 Functions: 7 9 77.8 %
Branches: 66 124 53.2 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (c) 2023 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 <chain.h>
       6                 :            : #include <chainparams.h>
       7                 :            : #include <node/blockstorage.h>
       8                 :            : #include <txdb.h>
       9                 :            : #include <validation.h>
      10                 :            : #include <test/fuzz/FuzzedDataProvider.h>
      11                 :            : #include <test/fuzz/fuzz.h>
      12                 :            : #include <test/fuzz/util.h>
      13                 :            : #include <test/util/setup_common.h>
      14                 :            : 
      15                 :            : namespace {
      16                 :            : 
      17                 :            : const BasicTestingSetup* g_setup;
      18                 :            : 
      19                 :            : // Hardcoded block hash and nBits to make sure the blocks we store pass the pow check.
      20                 :          2 : const uint256 g_block_hash{uint256S("000000002c05cc2e78923c34df87fd108b22221ac6076c18f3ade378a4d915e9")};
      21                 :            : uint32_t g_bits{0x1d00ffff};
      22                 :            : 
      23                 :       4392 : bool operator==(const CBlockFileInfo& a, const CBlockFileInfo& b)
      24                 :            : {
      25         [ +  - ]:       8784 :     return a.nBlocks == b.nBlocks &&
      26         [ +  - ]:       4392 :         a.nSize == b.nSize &&
      27         [ +  - ]:       4392 :         a.nUndoSize == b.nUndoSize &&
      28         [ +  - ]:       4392 :         a.nHeightFirst == b.nHeightFirst &&
      29         [ +  - ]:       4392 :         a.nHeightLast == b.nHeightLast &&
      30         [ -  + ]:       4392 :         a.nTimeFirst == b.nTimeFirst &&
      31                 :       4392 :         a.nTimeLast == b.nTimeLast;
      32                 :            : }
      33                 :            : 
      34                 :     326521 : CBlockHeader ConsumeBlockHeader(FuzzedDataProvider& provider)
      35                 :            : {
      36                 :     326521 :     CBlockHeader header;
      37                 :     326521 :     header.nVersion = provider.ConsumeIntegral<decltype(header.nVersion)>();
      38                 :     326521 :     header.hashPrevBlock = g_block_hash;
      39                 :     326521 :     header.hashMerkleRoot = g_block_hash;
      40                 :     326521 :     header.nTime = provider.ConsumeIntegral<decltype(header.nTime)>();
      41                 :     326521 :     header.nBits = g_bits;
      42                 :     326521 :     header.nNonce = provider.ConsumeIntegral<decltype(header.nNonce)>();
      43                 :     326521 :     return header;
      44                 :            : }
      45                 :            : 
      46                 :        154 : } // namespace
      47                 :            : 
      48                 :          1 : void init_block_index()
      49                 :            : {
      50 [ +  - ][ -  + ]:          1 :     static const auto testing_setup = MakeNoLogFileContext<>(ChainType::MAIN);
                 [ +  - ]
      51                 :          1 :     g_setup = testing_setup.get();
      52                 :          1 : }
      53                 :            : 
      54         [ +  - ]:        158 : FUZZ_TARGET(block_index, .init = init_block_index)
      55                 :            : {
      56                 :        154 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
      57 [ +  - ][ +  - ]:        462 :     auto block_index = kernel::BlockTreeDB(DBParams{
                 [ +  - ]
      58                 :        154 :         .path = "", // Memory only.
      59                 :            :         .cache_bytes = 1 << 20, // 1MB.
      60                 :            :         .memory_only = true,
      61                 :            :     });
      62                 :            : 
      63                 :            :     // Generate a number of block files to be stored in the index.
      64         [ +  - ]:        154 :     int files_count = fuzzed_data_provider.ConsumeIntegralInRange(1, 100);
      65                 :        154 :     std::vector<std::unique_ptr<CBlockFileInfo>> files;
      66         [ +  - ]:        154 :     files.reserve(files_count);
      67                 :        154 :     std::vector<std::pair<int, const CBlockFileInfo*>> files_info;
      68         [ +  - ]:        154 :     files_info.reserve(files_count);
      69         [ +  + ]:       4558 :     for (int i = 0; i < files_count; i++) {
      70         [ +  + ]:       4421 :         if (auto file_info = ConsumeDeserializable<CBlockFileInfo>(fuzzed_data_provider)) {
      71 [ +  - ][ +  - ]:       4404 :             files.push_back(std::make_unique<CBlockFileInfo>(std::move(*file_info)));
      72         [ +  - ]:       4404 :             files_info.emplace_back(i, files.back().get());
      73                 :       4404 :         } else {
      74                 :         17 :             return;
      75                 :            :         }
      76                 :       4404 :     }
      77                 :            : 
      78                 :            :     // Generate a number of block headers to be stored in the index.
      79         [ +  - ]:        137 :     int blocks_count = fuzzed_data_provider.ConsumeIntegralInRange(files_count * 10, files_count * 100);
      80                 :        137 :     std::vector<std::unique_ptr<CBlockIndex>> blocks;
      81         [ +  - ]:        137 :     blocks.reserve(blocks_count);
      82                 :        137 :     std::vector<const CBlockIndex*> blocks_info;
      83         [ +  - ]:        137 :     blocks_info.reserve(blocks_count);
      84         [ +  + ]:     326658 :     for (int i = 0; i < blocks_count; i++) {
      85         [ +  - ]:     326521 :         CBlockHeader header{ConsumeBlockHeader(fuzzed_data_provider)};
      86 [ +  - ][ +  - ]:     326521 :         blocks.push_back(std::make_unique<CBlockIndex>(std::move(header)));
      87                 :     326521 :         blocks.back()->phashBlock = &g_block_hash;
      88         [ +  - ]:     326521 :         blocks_info.push_back(blocks.back().get());
      89                 :     326521 :     }
      90                 :            : 
      91                 :            :     // Store these files and blocks in the block index. It should not fail.
      92 [ +  - ][ +  - ]:        137 :     assert(block_index.WriteBatchSync(files_info, files_count - 1, blocks_info));
      93                 :            : 
      94                 :            :     // We should be able to read every block file info we stored. Its value should correspond to
      95                 :            :     // what we stored above.
      96         [ +  - ]:        137 :     CBlockFileInfo info;
      97         [ +  + ]:       8921 :     for (const auto& [n, file_info]: files_info) {
      98 [ +  - ][ -  + ]:       4392 :         assert(block_index.ReadBlockFileInfo(n, info));
      99 [ +  - ][ +  - ]:       4392 :         assert(info == *file_info);
     100                 :            :     }
     101                 :            : 
     102                 :            :     // We should be able to read the last block file number. Its value should be consistent.
     103                 :            :     int last_block_file;
     104 [ +  - ][ +  - ]:        137 :     assert(block_index.ReadLastBlockFile(last_block_file));
     105         [ +  - ]:        137 :     assert(last_block_file == files_count - 1);
     106                 :            : 
     107                 :            :     // We should be able to flip and read the reindexing flag.
     108                 :            :     bool reindexing;
     109         [ +  - ]:        137 :     block_index.WriteReindexing(true);
     110         [ +  - ]:        137 :     block_index.ReadReindexing(reindexing);
     111         [ +  - ]:        137 :     assert(reindexing);
     112         [ +  - ]:        137 :     block_index.WriteReindexing(false);
     113         [ +  - ]:        137 :     block_index.ReadReindexing(reindexing);
     114         [ +  - ]:        137 :     assert(!reindexing);
     115                 :            : 
     116                 :            :     // We should be able to set and read the value of any random flag.
     117         [ +  - ]:        137 :     int flag_size = fuzzed_data_provider.ConsumeIntegralInRange(0, 100);
     118         [ +  - ]:        137 :     const std::string flag_name = fuzzed_data_provider.ConsumeBytesAsString(flag_size);
     119                 :            :     bool flag_value;
     120         [ +  - ]:        137 :     block_index.WriteFlag(flag_name, true);
     121         [ +  - ]:        137 :     block_index.ReadFlag(flag_name, flag_value);
     122         [ +  - ]:        137 :     assert(flag_value);
     123         [ +  - ]:        137 :     block_index.WriteFlag(flag_name, false);
     124         [ +  - ]:        137 :     block_index.ReadFlag(flag_name, flag_value);
     125         [ +  - ]:        137 :     assert(!flag_value);
     126                 :            : 
     127                 :            :     // We should be able to load everything we've previously stored. Note to assert on the
     128                 :            :     // return value we need to make sure all blocks pass the pow check.
     129 [ +  - ][ +  - ]:        137 :     const auto params{Params().GetConsensus()};
                 [ +  - ]
     130                 :        411 :     const auto inserter = [&](const uint256&) {
     131                 :        274 :         return blocks.back().get();
     132                 :            :     };
     133 [ +  - ][ +  - ]:        274 :     WITH_LOCK(::cs_main, assert(block_index.LoadBlockIndexGuts(params, inserter, g_setup->m_interrupt)));
         [ +  - ][ +  - ]
     134         [ -  + ]:        154 : }

Generated by: LCOV version 1.14