pow.cpp raw

   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  }
 172