mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-13 07:28: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:
51
src/pow.cpp
51
src/pow.cpp
@@ -71,6 +71,57 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
|
||||
return bnNew.GetCompact();
|
||||
}
|
||||
|
||||
// Check that on difficulty adjustments, the new difficulty does not increase
|
||||
// or decrease beyond the permitted limits.
|
||||
bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits)
|
||||
{
|
||||
if (params.fPowAllowMinDifficultyBlocks) return true;
|
||||
|
||||
if (height % params.DifficultyAdjustmentInterval() == 0) {
|
||||
int64_t smallest_timespan = params.nPowTargetTimespan/4;
|
||||
int64_t largest_timespan = params.nPowTargetTimespan*4;
|
||||
|
||||
const arith_uint256 pow_limit = UintToArith256(params.powLimit);
|
||||
arith_uint256 observed_new_target;
|
||||
observed_new_target.SetCompact(new_nbits);
|
||||
|
||||
// Calculate the largest difficulty value possible:
|
||||
arith_uint256 largest_difficulty_target;
|
||||
largest_difficulty_target.SetCompact(old_nbits);
|
||||
largest_difficulty_target *= largest_timespan;
|
||||
largest_difficulty_target /= params.nPowTargetTimespan;
|
||||
|
||||
if (largest_difficulty_target > pow_limit) {
|
||||
largest_difficulty_target = pow_limit;
|
||||
}
|
||||
|
||||
// Round and then compare this new calculated value to what is
|
||||
// observed.
|
||||
arith_uint256 maximum_new_target;
|
||||
maximum_new_target.SetCompact(largest_difficulty_target.GetCompact());
|
||||
if (maximum_new_target < observed_new_target) return false;
|
||||
|
||||
// Calculate the smallest difficulty value possible:
|
||||
arith_uint256 smallest_difficulty_target;
|
||||
smallest_difficulty_target.SetCompact(old_nbits);
|
||||
smallest_difficulty_target *= smallest_timespan;
|
||||
smallest_difficulty_target /= params.nPowTargetTimespan;
|
||||
|
||||
if (smallest_difficulty_target > pow_limit) {
|
||||
smallest_difficulty_target = pow_limit;
|
||||
}
|
||||
|
||||
// Round and then compare this new calculated value to what is
|
||||
// observed.
|
||||
arith_uint256 minimum_new_target;
|
||||
minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact());
|
||||
if (minimum_new_target > observed_new_target) return false;
|
||||
} else if (old_nbits != new_nbits) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
|
||||
{
|
||||
bool fNegative;
|
||||
|
||||
Reference in New Issue
Block a user