aboutsummaryrefslogtreecommitdiff
path: root/src/test/fuzz/pow.cpp
diff options
context:
space:
mode:
authorSuhas Daftuar <sdaftuar@gmail.com>2022-05-25 10:16:56 -0400
committerSuhas Daftuar <sdaftuar@gmail.com>2022-08-23 11:34:10 -0400
commit1d4cfa4272cf2c8b980cc8762c1ff2220d3e8d51 (patch)
tree4d1338b17702e4ed0998ece0f00f2d4b8b9ba062 /src/test/fuzz/pow.cpp
parent2bd9aa5a44b88c866c4d98f8a7bf7154049cba31 (diff)
downloadbitcoin-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/pow.cpp')
-rw-r--r--src/test/fuzz/pow.cpp37
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));
+}