pow.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-2022 The Bitcoin Core developers 3 // Distributed under the MIT software license, see the accompanying 4 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 6 #include <pow.h> 7 8 #include <arith_uint256.h> 9 #include <chain.h> 10 #include <primitives/block.h> 11 #include <uint256.h> 12 #include <util/check.h> 13 14 unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) 15 { 16 assert(pindexLast != nullptr); 17 unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); 18 19 // Only change once per difficulty adjustment interval 20 if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) 21 { 22 if (params.fPowAllowMinDifficultyBlocks) 23 { 24 // Special difficulty rule for testnet: 25 // If the new block's timestamp is more than 2* 10 minutes 26 // then it MUST be a min-difficulty block. 27 if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) 28 return nProofOfWorkLimit; 29 else 30 { 31 // Return the last non-special-min-difficulty-rules-block 32 const CBlockIndex* pindex = pindexLast; 33 while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) 34 pindex = pindex->pprev; 35 return pindex->nBits; 36 } 37 } 38 return pindexLast->nBits; 39 } 40 41 // Go back by what we want to be 14 days worth of blocks 42 int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); 43 assert(nHeightFirst >= 0); 44 const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); 45 assert(pindexFirst); 46 47 return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); 48 } 49 50 unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) 51 { 52 if (params.fPowNoRetargeting) 53 return pindexLast->nBits; 54 55 // Limit adjustment step 56 int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; 57 if (nActualTimespan < params.nPowTargetTimespan/4) 58 nActualTimespan = params.nPowTargetTimespan/4; 59 if (nActualTimespan > params.nPowTargetTimespan*4) 60 nActualTimespan = params.nPowTargetTimespan*4; 61 62 // Retarget 63 const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); 64 arith_uint256 bnNew; 65 66 // Special difficulty rule for Testnet4 67 if (params.enforce_BIP94) { 68 // Here we use the first block of the difficulty period. This way 69 // the real difficulty is always preserved in the first block as 70 // it is not allowed to use the min-difficulty exception. 71 int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); 72 const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); 73 bnNew.SetCompact(pindexFirst->nBits); 74 } else { 75 bnNew.SetCompact(pindexLast->nBits); 76 } 77 78 bnNew *= nActualTimespan; 79 bnNew /= params.nPowTargetTimespan; 80 81 if (bnNew > bnPowLimit) 82 bnNew = bnPowLimit; 83 84 return bnNew.GetCompact(); 85 } 86 87 // Check that on difficulty adjustments, the new difficulty does not increase 88 // or decrease beyond the permitted limits. 89 bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits) 90 { 91 if (params.fPowAllowMinDifficultyBlocks) return true; 92 93 if (height % params.DifficultyAdjustmentInterval() == 0) { 94 int64_t smallest_timespan = params.nPowTargetTimespan/4; 95 int64_t largest_timespan = params.nPowTargetTimespan*4; 96 97 const arith_uint256 pow_limit = UintToArith256(params.powLimit); 98 arith_uint256 observed_new_target; 99 observed_new_target.SetCompact(new_nbits); 100 101 // Calculate the largest difficulty value possible: 102 arith_uint256 largest_difficulty_target; 103 largest_difficulty_target.SetCompact(old_nbits); 104 largest_difficulty_target *= largest_timespan; 105 largest_difficulty_target /= params.nPowTargetTimespan; 106 107 if (largest_difficulty_target > pow_limit) { 108 largest_difficulty_target = pow_limit; 109 } 110 111 // Round and then compare this new calculated value to what is 112 // observed. 113 arith_uint256 maximum_new_target; 114 maximum_new_target.SetCompact(largest_difficulty_target.GetCompact()); 115 if (maximum_new_target < observed_new_target) return false; 116 117 // Calculate the smallest difficulty value possible: 118 arith_uint256 smallest_difficulty_target; 119 smallest_difficulty_target.SetCompact(old_nbits); 120 smallest_difficulty_target *= smallest_timespan; 121 smallest_difficulty_target /= params.nPowTargetTimespan; 122 123 if (smallest_difficulty_target > pow_limit) { 124 smallest_difficulty_target = pow_limit; 125 } 126 127 // Round and then compare this new calculated value to what is 128 // observed. 129 arith_uint256 minimum_new_target; 130 minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact()); 131 if (minimum_new_target > observed_new_target) return false; 132 } else if (old_nbits != new_nbits) { 133 return false; 134 } 135 return true; 136 } 137 138 // Bypasses the actual proof of work check during fuzz testing with a simplified validation checking whether 139 // the most significant bit of the last byte of the hash is set. 140 bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) 141 { 142 if (EnableFuzzDeterminism()) return (hash.data()[31] & 0x80) == 0; 143 return CheckProofOfWorkImpl(hash, nBits, params); 144 } 145 146 std::optional<arith_uint256> DeriveTarget(unsigned int nBits, const uint256 pow_limit) 147 { 148 bool fNegative; 149 bool fOverflow; 150 arith_uint256 bnTarget; 151 152 bnTarget.SetCompact(nBits, &fNegative, &fOverflow); 153 154 // Check range 155 if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(pow_limit)) 156 return {}; 157 158 return bnTarget; 159 } 160 161 bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params) 162 { 163 auto bnTarget{DeriveTarget(nBits, params.powLimit)}; 164 if (!bnTarget) return false; 165 166 // Check proof of work matches claimed amount 167 if (UintToArith256(hash) > bnTarget) 168 return false; 169 170 return true; 171 }