LCOV - code coverage report
Current view: top level - src - pow.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 21 77 27.3 %
Date: 2023-09-26 12:08:55 Functions: 3 5 60.0 %

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

Generated by: LCOV version 1.14