mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 15:09:59 +01:00
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.
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user