LCOV - code coverage report
Current view: top level - src/test/fuzz - pow.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 3 84 3.6 %
Date: 2023-09-26 12:08:55 Functions: 5 8 62.5 %

          Line data    Source code
       1             : // Copyright (c) 2020-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 <chain.h>
       6             : #include <chainparams.h>
       7             : #include <pow.h>
       8             : #include <primitives/block.h>
       9             : #include <test/fuzz/FuzzedDataProvider.h>
      10             : #include <test/fuzz/fuzz.h>
      11             : #include <test/fuzz/util.h>
      12             : #include <util/chaintype.h>
      13             : #include <util/check.h>
      14             : #include <util/overflow.h>
      15             : 
      16             : #include <cstdint>
      17             : #include <optional>
      18             : #include <string>
      19             : #include <vector>
      20             : 
      21           0 : void initialize_pow()
      22             : {
      23           0 :     SelectParams(ChainType::MAIN);
      24           0 : }
      25             : 
      26           4 : FUZZ_TARGET(pow, .init = initialize_pow)
      27             : {
      28           0 :     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
      29           0 :     const Consensus::Params& consensus_params = Params().GetConsensus();
      30           0 :     std::vector<std::unique_ptr<CBlockIndex>> blocks;
      31           0 :     const uint32_t fixed_time = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
      32           0 :     const uint32_t fixed_bits = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
      33           0 :     LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 10000) {
      34           0 :         const std::optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
      35           0 :         if (!block_header) {
      36           0 :             continue;
      37             :         }
      38           0 :         CBlockIndex& current_block{
      39           0 :             *blocks.emplace_back(std::make_unique<CBlockIndex>(*block_header))};
      40             :         {
      41           0 :             CBlockIndex* previous_block = blocks.empty() ? nullptr : PickValue(fuzzed_data_provider, blocks).get();
      42           0 :             const int current_height = (previous_block != nullptr && previous_block->nHeight != std::numeric_limits<int>::max()) ? previous_block->nHeight + 1 : 0;
      43           0 :             if (fuzzed_data_provider.ConsumeBool()) {
      44           0 :                 current_block.pprev = previous_block;
      45           0 :             }
      46           0 :             if (fuzzed_data_provider.ConsumeBool()) {
      47           0 :                 current_block.nHeight = current_height;
      48           0 :             }
      49           0 :             if (fuzzed_data_provider.ConsumeBool()) {
      50           0 :                 const uint32_t seconds = current_height * consensus_params.nPowTargetSpacing;
      51           0 :                 if (!AdditionOverflow(fixed_time, seconds)) {
      52           0 :                     current_block.nTime = fixed_time + seconds;
      53           0 :                 }
      54           0 :             }
      55           0 :             if (fuzzed_data_provider.ConsumeBool()) {
      56           0 :                 current_block.nBits = fixed_bits;
      57           0 :             }
      58           0 :             if (fuzzed_data_provider.ConsumeBool()) {
      59           0 :                 current_block.nChainWork = previous_block != nullptr ? previous_block->nChainWork + GetBlockProof(*previous_block) : arith_uint256{0};
      60           0 :             } else {
      61           0 :                 current_block.nChainWork = ConsumeArithUInt256(fuzzed_data_provider);
      62             :             }
      63             :         }
      64             :         {
      65           0 :             (void)GetBlockProof(current_block);
      66           0 :             (void)CalculateNextWorkRequired(&current_block, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, std::numeric_limits<int64_t>::max()), consensus_params);
      67           0 :             if (current_block.nHeight != std::numeric_limits<int>::max() && current_block.nHeight - (consensus_params.DifficultyAdjustmentInterval() - 1) >= 0) {
      68           0 :                 (void)GetNextWorkRequired(&current_block, &(*block_header), consensus_params);
      69           0 :             }
      70             :         }
      71             :         {
      72           0 :             const auto& to = PickValue(fuzzed_data_provider, blocks);
      73           0 :             const auto& from = PickValue(fuzzed_data_provider, blocks);
      74           2 :             const auto& tip = PickValue(fuzzed_data_provider, blocks);
      75             :             try {
      76           0 :                 (void)GetBlockProofEquivalentTime(*to, *from, *tip, consensus_params);
      77           0 :             } catch (const uint_error&) {
      78           0 :             }
      79             :         }
      80             :         {
      81           0 :             const std::optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider);
      82           0 :             if (hash) {
      83           0 :                 (void)CheckProofOfWork(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params);
      84           0 :             }
      85             :         }
      86           0 :     }
      87           0 : }
      88             : 
      89             : 
      90           4 : FUZZ_TARGET(pow_transition, .init = initialize_pow)
      91             : {
      92           0 :     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
      93           0 :     const Consensus::Params& consensus_params{Params().GetConsensus()};
      94           0 :     std::vector<std::unique_ptr<CBlockIndex>> blocks;
      95             : 
      96           0 :     const uint32_t old_time{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
      97           0 :     const uint32_t new_time{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
      98           0 :     const int32_t version{fuzzed_data_provider.ConsumeIntegral<int32_t>()};
      99           0 :     uint32_t nbits{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
     100             : 
     101           0 :     const arith_uint256 pow_limit = UintToArith256(consensus_params.powLimit);
     102           0 :     arith_uint256 old_target;
     103           0 :     old_target.SetCompact(nbits);
     104           0 :     if (old_target > pow_limit) {
     105           0 :         nbits = pow_limit.GetCompact();
     106           0 :     }
     107             :     // Create one difficulty adjustment period worth of headers
     108           0 :     for (int height = 0; height < consensus_params.DifficultyAdjustmentInterval(); ++height) {
     109           0 :         CBlockHeader header;
     110           0 :         header.nVersion = version;
     111           0 :         header.nTime = old_time;
     112           0 :         header.nBits = nbits;
     113           0 :         if (height == consensus_params.DifficultyAdjustmentInterval() - 1) {
     114           0 :             header.nTime = new_time;
     115           0 :         }
     116           0 :         auto current_block{std::make_unique<CBlockIndex>(header)};
     117           0 :         current_block->pprev = blocks.empty() ? nullptr : blocks.back().get();
     118           0 :         current_block->nHeight = height;
     119           0 :         blocks.emplace_back(std::move(current_block));
     120           0 :     }
     121           0 :     auto last_block{blocks.back().get()};
     122           0 :     unsigned int new_nbits{GetNextWorkRequired(last_block, nullptr, consensus_params)};
     123           0 :     Assert(PermittedDifficultyTransition(consensus_params, last_block->nHeight + 1, last_block->nBits, new_nbits));
     124           0 : }

Generated by: LCOV version 1.14