diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt --- a/src/test/fuzz/CMakeLists.txt +++ b/src/test/fuzz/CMakeLists.txt @@ -104,6 +104,7 @@ parse_numbers parse_script parse_univalue + pow process_message process_messages protocol diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp new file mode 100644 --- /dev/null +++ b/src/test/fuzz/pow.cpp @@ -0,0 +1,114 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +void initialize() { + SelectParams(CBaseChainParams::MAIN); +} + +void test_one_input(const std::vector &buffer) { + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const Config &config = GetConfig(); + const CChainParams &chainparams = config.GetChainParams(); + const Consensus::Params &consensus_params = chainparams.GetConsensus(); + std::vector blocks; + const uint32_t fixed_time = + fuzzed_data_provider.ConsumeIntegral(); + const uint32_t fixed_bits = + fuzzed_data_provider.ConsumeIntegral(); + while (fuzzed_data_provider.remaining_bytes() > 0) { + const std::optional block_header = + ConsumeDeserializable(fuzzed_data_provider); + if (!block_header) { + continue; + } + CBlockIndex current_block{*block_header}; + { + CBlockIndex *previous_block = + !blocks.empty() + ? &blocks[fuzzed_data_provider.ConsumeIntegralInRange< + size_t>(0, blocks.size() - 1)] + : nullptr; + const int current_height = + (previous_block != nullptr && + previous_block->nHeight != std::numeric_limits::max()) + ? previous_block->nHeight + 1 + : 0; + if (fuzzed_data_provider.ConsumeBool()) { + current_block.pprev = previous_block; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nHeight = current_height; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nTime = + fixed_time + + current_height * consensus_params.nPowTargetSpacing; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nBits = fixed_bits; + } + if (fuzzed_data_provider.ConsumeBool()) { + current_block.nChainWork = + previous_block != nullptr + ? previous_block->nChainWork + + GetBlockProof(*previous_block) + : arith_uint256{0}; + } else { + current_block.nChainWork = + ConsumeArithUInt256(fuzzed_data_provider); + } + blocks.push_back(current_block); + } + { + (void)GetBlockProof(current_block); + if (current_block.nHeight != std::numeric_limits::max() && + current_block.nHeight - + (consensus_params.DifficultyAdjustmentInterval() - 1) >= + 0) { + (void)GetNextWorkRequired(¤t_block, &(*block_header), + chainparams); + } + } + { + const CBlockIndex *to = + &blocks[fuzzed_data_provider.ConsumeIntegralInRange( + 0, blocks.size() - 1)]; + const CBlockIndex *from = + &blocks[fuzzed_data_provider.ConsumeIntegralInRange( + 0, blocks.size() - 1)]; + const CBlockIndex *tip = + &blocks[fuzzed_data_provider.ConsumeIntegralInRange( + 0, blocks.size() - 1)]; + try { + (void)GetBlockProofEquivalentTime(*to, *from, *tip, + consensus_params); + } catch (const uint_error &) { + } + } + { + const std::optional hash = + ConsumeDeserializable(fuzzed_data_provider); + if (hash) { + (void)CheckProofOfWork( + *hash, fuzzed_data_provider.ConsumeIntegral(), + consensus_params); + } + } + } +} diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -6,6 +6,7 @@ #define BITCOIN_TEST_FUZZ_UTIL_H #include +#include #include #include