/ src / pow.cpp
pow.cpp
  1  // Copyright (c) 2009-2010 Satoshi Nakamoto
  2  // Copyright (c) 2009-present 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  }