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 13 unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) 14 { 15 assert(pindexLast != nullptr); 16 unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); 17 18 // Only change once per difficulty adjustment interval 19 if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) 20 { 21 if (params.fPowAllowMinDifficultyBlocks) 22 { 23 // Special difficulty rule for testnet: 24 // If the new block's timestamp is more than 2* 10 minutes 25 // then allow mining of a min-difficulty block. 26 if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) 27 return nProofOfWorkLimit; 28 else 29 { 30 // Return the last non-special-min-difficulty-rules-block 31 const CBlockIndex* pindex = pindexLast; 32 while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) 33 pindex = pindex->pprev; 34 return pindex->nBits; 35 } 36 } 37 return pindexLast->nBits; 38 } 39 40 // Go back by what we want to be 14 days worth of blocks 41 int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); 42 assert(nHeightFirst >= 0); 43 const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); 44 assert(pindexFirst); 45 46 return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); 47 } 48 49 unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) 50 { 51 if (params.fPowNoRetargeting) 52 return pindexLast->nBits; 53 54 // Limit adjustment step 55 int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; 56 if (nActualTimespan < params.nPowTargetTimespan/4) 57 nActualTimespan = params.nPowTargetTimespan/4; 58 if (nActualTimespan > params.nPowTargetTimespan*4) 59 nActualTimespan = params.nPowTargetTimespan*4; 60 61 // Retarget 62 const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); 63 arith_uint256 bnNew; 64 bnNew.SetCompact(pindexLast->nBits); 65 bnNew *= nActualTimespan; 66 bnNew /= params.nPowTargetTimespan; 67 68 if (bnNew > bnPowLimit) 69 bnNew = bnPowLimit; 70 71 return bnNew.GetCompact(); 72 } 73 74 // Check that on difficulty adjustments, the new difficulty does not increase 75 // or decrease beyond the permitted limits. 76 bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits) 77 { 78 if (params.fPowAllowMinDifficultyBlocks) return true; 79 80 if (height % params.DifficultyAdjustmentInterval() == 0) { 81 int64_t smallest_timespan = params.nPowTargetTimespan/4; 82 int64_t largest_timespan = params.nPowTargetTimespan*4; 83 84 const arith_uint256 pow_limit = UintToArith256(params.powLimit); 85 arith_uint256 observed_new_target; 86 observed_new_target.SetCompact(new_nbits); 87 88 // Calculate the largest difficulty value possible: 89 arith_uint256 largest_difficulty_target; 90 largest_difficulty_target.SetCompact(old_nbits); 91 largest_difficulty_target *= largest_timespan; 92 largest_difficulty_target /= params.nPowTargetTimespan; 93 94 if (largest_difficulty_target > pow_limit) { 95 largest_difficulty_target = pow_limit; 96 } 97 98 // Round and then compare this new calculated value to what is 99 // observed. 100 arith_uint256 maximum_new_target; 101 maximum_new_target.SetCompact(largest_difficulty_target.GetCompact()); 102 if (maximum_new_target < observed_new_target) return false; 103 104 // Calculate the smallest difficulty value possible: 105 arith_uint256 smallest_difficulty_target; 106 smallest_difficulty_target.SetCompact(old_nbits); 107 smallest_difficulty_target *= smallest_timespan; 108 smallest_difficulty_target /= params.nPowTargetTimespan; 109 110 if (smallest_difficulty_target > pow_limit) { 111 smallest_difficulty_target = pow_limit; 112 } 113 114 // Round and then compare this new calculated value to what is 115 // observed. 116 arith_uint256 minimum_new_target; 117 minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact()); 118 if (minimum_new_target > observed_new_target) return false; 119 } else if (old_nbits != new_nbits) { 120 return false; 121 } 122 return true; 123 } 124 125 bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) 126 { 127 bool fNegative; 128 bool fOverflow; 129 arith_uint256 bnTarget; 130 131 bnTarget.SetCompact(nBits, &fNegative, &fOverflow); 132 133 // Check range 134 if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) 135 return false; 136 137 // Check proof of work matches claimed amount 138 if (UintToArith256(hash) > bnTarget) 139 return false; 140 141 return true; 142 }