LCOV - code coverage report
Current view: top level - src - pow.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 73 77 94.8 %
Date: 2023-10-05 15:40:34 Functions: 5 5 100.0 %
Branches: 42 50 84.0 %

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

Generated by: LCOV version 1.14