/ src / pow.cpp
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  }