From acf269e1463c84d51f2eef695089cbf9d03b547f Mon Sep 17 00:00:00 2001 From: practicalswift Date: Sun, 22 Mar 2020 14:16:40 +0000 Subject: tests: Add proof-of-work fuzzing harness --- src/Makefile.test.include | 7 ++++ src/test/fuzz/pow.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++ src/test/fuzz/util.h | 6 ++++ 3 files changed, 94 insertions(+) create mode 100644 src/test/fuzz/pow.cpp (limited to 'src') diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 45077ccbd9..2978e5a2ec 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -57,6 +57,7 @@ FUZZ_TARGETS = \ test/fuzz/parse_univalue \ test/fuzz/partial_merkle_tree_deserialize \ test/fuzz/partially_signed_transaction_deserialize \ + test/fuzz/pow \ test/fuzz/prefilled_transaction_deserialize \ test/fuzz/process_message \ test/fuzz/process_message_addr \ @@ -610,6 +611,12 @@ test_fuzz_partially_signed_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMO test_fuzz_partially_signed_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_partially_signed_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp +test_fuzz_pow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_pow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_pow_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_pow_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_pow_SOURCES = $(FUZZ_SUITE) test/fuzz/pow.cpp + test_fuzz_prefilled_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPREFILLED_TRANSACTION_DESERIALIZE=1 test_fuzz_prefilled_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_prefilled_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp new file mode 100644 index 0000000000..0343d33401 --- /dev/null +++ b/src/test/fuzz/pow.cpp @@ -0,0 +1,81 @@ +// 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 + +void initialize() +{ + SelectParams(CBaseChainParams::MAIN); +} + +void test_one_input(const std::vector& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const Consensus::Params& consensus_params = Params().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 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(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); + (void)CalculateNextWorkRequired(¤t_block, fuzzed_data_provider.ConsumeIntegralInRange(0, std::numeric_limits::max()), consensus_params); + if (current_block.nHeight != std::numeric_limits::max() && current_block.nHeight - (consensus_params.DifficultyAdjustmentInterval() - 1) >= 0) { + (void)GetNextWorkRequired(¤t_block, &(*block_header), consensus_params); + } + } + { + 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 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 index 10be2ebaf7..6b22601d29 100644 --- 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 #include