LCOV - code coverage report
Current view: top level - src - pow.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 95.9 % 73 70
Test Date: 2024-12-02 12:23:29 Functions: 100.0 % 5 5
Branches: 87.0 % 54 47

             Branch data     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                 :             : #include <util/check.h>
      13                 :             : 
      14                 :      577998 : unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
      15                 :             : {
      16         [ -  + ]:      577998 :     assert(pindexLast != nullptr);
      17                 :      577998 :     unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
      18                 :             : 
      19                 :             :     // Only change once per difficulty adjustment interval
      20         [ +  + ]:      577998 :     if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
      21                 :             :     {
      22         [ +  + ]:      576086 :         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 allow mining of a min-difficulty block.
      27         [ +  + ]:      572887 :             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   [ +  +  +  +  :    10890622 :                 while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
                   +  - ]
      34                 :             :                     pindex = pindex->pprev;
      35                 :      203909 :                 return pindex->nBits;
      36                 :             :             }
      37                 :             :         }
      38                 :        3199 :         return pindexLast->nBits;
      39                 :             :     }
      40                 :             : 
      41                 :             :     // Go back by what we want to be 14 days worth of blocks
      42                 :        1912 :     int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
      43         [ -  + ]:        1912 :     assert(nHeightFirst >= 0);
      44                 :        1912 :     const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
      45         [ -  + ]:        1912 :     assert(pindexFirst);
      46                 :             : 
      47                 :        1912 :     return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params);
      48                 :             : }
      49                 :             : 
      50                 :      105874 : unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
      51                 :             : {
      52         [ +  + ]:      105874 :     if (params.fPowNoRetargeting)
      53                 :        1754 :         return pindexLast->nBits;
      54                 :             : 
      55                 :             :     // Limit adjustment step
      56         [ +  + ]:      104120 :     int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
      57         [ +  + ]:      104120 :     if (nActualTimespan < params.nPowTargetTimespan/4)
      58                 :       94416 :         nActualTimespan = params.nPowTargetTimespan/4;
      59         [ +  + ]:      104120 :     if (nActualTimespan > params.nPowTargetTimespan*4)
      60                 :        7765 :         nActualTimespan = params.nPowTargetTimespan*4;
      61                 :             : 
      62                 :             :     // Retarget
      63                 :      104120 :     const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
      64                 :      104120 :     arith_uint256 bnNew;
      65                 :             : 
      66                 :             :     // Special difficulty rule for Testnet4
      67         [ -  + ]:      104120 :     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                 :           0 :         int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1);
      72                 :           0 :         const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst);
      73                 :           0 :         bnNew.SetCompact(pindexFirst->nBits);
      74                 :             :     } else {
      75                 :      104120 :         bnNew.SetCompact(pindexLast->nBits);
      76                 :             :     }
      77                 :             : 
      78                 :      104120 :     bnNew *= nActualTimespan;
      79                 :      208240 :     bnNew /= params.nPowTargetTimespan;
      80                 :             : 
      81         [ +  + ]:      104120 :     if (bnNew > bnPowLimit)
      82                 :      104120 :         bnNew = bnPowLimit;
      83                 :             : 
      84                 :      104120 :     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                 :      248987 : bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits)
      90                 :             : {
      91         [ +  - ]:      248987 :     if (params.fPowAllowMinDifficultyBlocks) return true;
      92                 :             : 
      93         [ +  + ]:      248987 :     if (height % params.DifficultyAdjustmentInterval() == 0) {
      94                 :         248 :         int64_t smallest_timespan = params.nPowTargetTimespan/4;
      95                 :         248 :         int64_t largest_timespan = params.nPowTargetTimespan*4;
      96                 :             : 
      97                 :         248 :         const arith_uint256 pow_limit = UintToArith256(params.powLimit);
      98                 :         248 :         arith_uint256 observed_new_target;
      99                 :         248 :         observed_new_target.SetCompact(new_nbits);
     100                 :             : 
     101                 :             :         // Calculate the largest difficulty value possible:
     102                 :         248 :         arith_uint256 largest_difficulty_target;
     103                 :         248 :         largest_difficulty_target.SetCompact(old_nbits);
     104                 :         248 :         largest_difficulty_target *= largest_timespan;
     105                 :         496 :         largest_difficulty_target /= params.nPowTargetTimespan;
     106                 :             : 
     107         [ +  + ]:         248 :         if (largest_difficulty_target > pow_limit) {
     108                 :         248 :             largest_difficulty_target = pow_limit;
     109                 :             :         }
     110                 :             : 
     111                 :             :         // Round and then compare this new calculated value to what is
     112                 :             :         // observed.
     113                 :         248 :         arith_uint256 maximum_new_target;
     114                 :         248 :         maximum_new_target.SetCompact(largest_difficulty_target.GetCompact());
     115         [ +  + ]:         248 :         if (maximum_new_target < observed_new_target) return false;
     116                 :             : 
     117                 :             :         // Calculate the smallest difficulty value possible:
     118                 :         243 :         arith_uint256 smallest_difficulty_target;
     119                 :         243 :         smallest_difficulty_target.SetCompact(old_nbits);
     120                 :         243 :         smallest_difficulty_target *= smallest_timespan;
     121                 :         486 :         smallest_difficulty_target /= params.nPowTargetTimespan;
     122                 :             : 
     123         [ -  + ]:         243 :         if (smallest_difficulty_target > pow_limit) {
     124                 :         243 :             smallest_difficulty_target = pow_limit;
     125                 :             :         }
     126                 :             : 
     127                 :             :         // Round and then compare this new calculated value to what is
     128                 :             :         // observed.
     129                 :         243 :         arith_uint256 minimum_new_target;
     130                 :         243 :         minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact());
     131         [ +  + ]:         243 :         if (minimum_new_target > observed_new_target) return false;
     132         [ +  + ]:      248739 :     } else if (old_nbits != new_nbits) {
     133                 :         282 :         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                 :      800976 : bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
     141                 :             : {
     142                 :      800976 :     if constexpr (G_FUZZING) return (hash.data()[31] & 0x80) == 0;
     143                 :             :     return CheckProofOfWorkImpl(hash, nBits, params);
     144                 :             : }
     145                 :             : 
     146                 :       45603 : bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params)
     147                 :             : {
     148                 :       45603 :     bool fNegative;
     149                 :       45603 :     bool fOverflow;
     150                 :       45603 :     arith_uint256 bnTarget;
     151                 :             : 
     152                 :       45603 :     bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
     153                 :             : 
     154                 :             :     // Check range
     155   [ +  +  +  +  :       74348 :     if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
             +  +  +  + ]
     156                 :       40592 :         return false;
     157                 :             : 
     158                 :             :     // Check proof of work matches claimed amount
     159         [ +  + ]:        5011 :     if (UintToArith256(hash) > bnTarget)
     160                 :        3726 :         return false;
     161                 :             : 
     162                 :             :     return true;
     163                 :             : }
        

Generated by: LCOV version 2.0-1