diff options
author | Suhas Daftuar <sdaftuar@gmail.com> | 2022-05-25 10:16:56 -0400 |
---|---|---|
committer | Suhas Daftuar <sdaftuar@gmail.com> | 2022-08-23 11:34:10 -0400 |
commit | 1d4cfa4272cf2c8b980cc8762c1ff2220d3e8d51 (patch) | |
tree | 4d1338b17702e4ed0998ece0f00f2d4b8b9ba062 /src/test/fuzz | |
parent | 2bd9aa5a44b88c866c4d98f8a7bf7154049cba31 (diff) | |
download | bitcoin-1d4cfa4272cf2c8b980cc8762c1ff2220d3e8d51.tar.xz |
Add function to validate difficulty changes
The rule against difficulty adjustments changing by more than a factor of 4 can
be helpful for anti-DoS measures in contexts where we lack a full headers
chain, so expose this functionality separately and in the narrow case where we
only know the height, new value, and old value.
Includes fuzz test by Martin Zumsande.
Diffstat (limited to 'src/test/fuzz')
-rw-r--r-- | src/test/fuzz/pow.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp index 0004d82d66..507ce57ec0 100644 --- a/src/test/fuzz/pow.cpp +++ b/src/test/fuzz/pow.cpp @@ -83,3 +83,40 @@ FUZZ_TARGET_INIT(pow, initialize_pow) } } } + + +FUZZ_TARGET_INIT(pow_transition, initialize_pow) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const Consensus::Params& consensus_params{Params().GetConsensus()}; + std::vector<std::unique_ptr<CBlockIndex>> blocks; + + const uint32_t old_time{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; + const uint32_t new_time{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; + const int32_t version{fuzzed_data_provider.ConsumeIntegral<int32_t>()}; + uint32_t nbits{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; + + const arith_uint256 pow_limit = UintToArith256(consensus_params.powLimit); + arith_uint256 old_target; + old_target.SetCompact(nbits); + if (old_target > pow_limit) { + nbits = pow_limit.GetCompact(); + } + // Create one difficulty adjustment period worth of headers + for (int height = 0; height < consensus_params.DifficultyAdjustmentInterval(); ++height) { + CBlockHeader header; + header.nVersion = version; + header.nTime = old_time; + header.nBits = nbits; + if (height == consensus_params.DifficultyAdjustmentInterval() - 1) { + header.nTime = new_time; + } + auto current_block{std::make_unique<CBlockIndex>(header)}; + current_block->pprev = blocks.empty() ? nullptr : blocks.back().get(); + current_block->nHeight = height; + blocks.emplace_back(std::move(current_block)).get(); + } + auto last_block{blocks.back().get()}; + unsigned int new_nbits{GetNextWorkRequired(last_block, nullptr, consensus_params)}; + Assert(PermittedDifficultyTransition(consensus_params, last_block->nHeight + 1, last_block->nBits, new_nbits)); +} |