LCOV - code coverage report
Current view: top level - src - pow.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 19 79 24.1 %
Date: 2025-02-23 09:33:43 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2014-2015 The Dash developers
       4             : // Copyright (c) 2015-2021 The PIVX Core developers
       5             : // Distributed under the MIT/X11 software license, see the accompanying
       6             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       7             : 
       8             : #include "pow.h"
       9             : 
      10             : #include "chain.h"
      11             : #include "chainparams.h"
      12             : #include "primitives/block.h"
      13             : #include "uint256.h"
      14             : #include "util/system.h"
      15             : 
      16             : #include <math.h>
      17             : 
      18             : 
      19       71945 : unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader* pblock)
      20             : {
      21       71945 :     const Consensus::Params& consensus = Params().GetConsensus();
      22             : 
      23       71945 :     if (consensus.fPowNoRetargeting)
      24       71945 :         return pindexLast->nBits;
      25             : 
      26             :     /* current difficulty formula, pivx - DarkGravity v3, written by Evan Duffield - evan@dashpay.io */
      27           0 :     const CBlockIndex* BlockLastSolved = pindexLast;
      28           0 :     const CBlockIndex* BlockReading = pindexLast;
      29           0 :     int64_t nActualTimespan = 0;
      30           0 :     int64_t LastBlockTime = 0;
      31           0 :     int64_t PastBlocksMin = 24;
      32           0 :     int64_t PastBlocksMax = 24;
      33           0 :     int64_t CountBlocks = 0;
      34           0 :     arith_uint256 PastDifficultyAverage;
      35           0 :     arith_uint256 PastDifficultyAveragePrev;
      36           0 :     const arith_uint256& powLimit = UintToArith256(consensus.powLimit);
      37             : 
      38           0 :     if (BlockLastSolved == nullptr || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
      39           0 :         return powLimit.GetCompact();
      40             :     }
      41             : 
      42           0 :     if (consensus.NetworkUpgradeActive(pindexLast->nHeight + 1, Consensus::UPGRADE_POS)) {
      43           0 :         const bool fTimeV2 = !Params().IsRegTestNet() && consensus.IsTimeProtocolV2(pindexLast->nHeight+1);
      44           0 :         const arith_uint256& bnTargetLimit = UintToArith256(consensus.ProofOfStakeLimit(fTimeV2));
      45           0 :         const int64_t& nTargetTimespan = consensus.TargetTimespan(fTimeV2);
      46             : 
      47           0 :         int64_t nActualSpacing = 0;
      48           0 :         if (pindexLast->nHeight != 0)
      49           0 :             nActualSpacing = pindexLast->GetBlockTime() - pindexLast->pprev->GetBlockTime();
      50           0 :         if (nActualSpacing < 0)
      51           0 :             nActualSpacing = 1;
      52           0 :         if (fTimeV2 && nActualSpacing > consensus.nTargetSpacing*10)
      53           0 :             nActualSpacing = consensus.nTargetSpacing*10;
      54             : 
      55             :         // ppcoin: target change every block
      56             :         // ppcoin: retarget with exponential moving toward target spacing
      57           0 :         arith_uint256 bnNew;
      58           0 :         bnNew.SetCompact(pindexLast->nBits);
      59             : 
      60             :         // on first block with V2 time protocol, reduce the difficulty by a factor 16
      61           0 :         if (fTimeV2 && !consensus.IsTimeProtocolV2(pindexLast->nHeight))
      62           0 :             bnNew <<= 4;
      63             : 
      64           0 :         int64_t nInterval = nTargetTimespan / consensus.nTargetSpacing;
      65           0 :         bnNew *= ((nInterval - 1) * consensus.nTargetSpacing + nActualSpacing + nActualSpacing);
      66           0 :         bnNew /= ((nInterval + 1) * consensus.nTargetSpacing);
      67             : 
      68           0 :         if (bnNew <= 0 || bnNew > bnTargetLimit)
      69           0 :             bnNew = bnTargetLimit;
      70             : 
      71           0 :         return bnNew.GetCompact();
      72             :     }
      73             : 
      74           0 :     for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
      75           0 :         if (PastBlocksMax > 0 && i > PastBlocksMax) {
      76             :             break;
      77             :         }
      78           0 :         CountBlocks++;
      79             : 
      80           0 :         if (CountBlocks <= PastBlocksMin) {
      81           0 :             if (CountBlocks == 1) {
      82           0 :                 PastDifficultyAverage.SetCompact(BlockReading->nBits);
      83             :             } else {
      84           0 :                 PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (arith_uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1);
      85             :             }
      86           0 :             PastDifficultyAveragePrev = PastDifficultyAverage;
      87             :         }
      88             : 
      89           0 :         if (LastBlockTime > 0) {
      90           0 :             int64_t Diff = (LastBlockTime - BlockReading->GetBlockTime());
      91           0 :             nActualTimespan += Diff;
      92             :         }
      93           0 :         LastBlockTime = BlockReading->GetBlockTime();
      94             : 
      95           0 :         if (BlockReading->pprev == nullptr) {
      96             :             assert(BlockReading);
      97             :             break;
      98             :         }
      99           0 :         BlockReading = BlockReading->pprev;
     100             :     }
     101             : 
     102           0 :     arith_uint256 bnNew(PastDifficultyAverage);
     103             : 
     104           0 :     int64_t _nTargetTimespan = CountBlocks * consensus.nTargetSpacing;
     105             : 
     106           0 :     if (nActualTimespan < _nTargetTimespan / 3)
     107           0 :         nActualTimespan = _nTargetTimespan / 3;
     108           0 :     if (nActualTimespan > _nTargetTimespan * 3)
     109           0 :         nActualTimespan = _nTargetTimespan * 3;
     110             : 
     111             :     // Retarget
     112           0 :     bnNew *= nActualTimespan;
     113           0 :     bnNew /= _nTargetTimespan;
     114             : 
     115           0 :     if (bnNew > powLimit) {
     116           0 :         bnNew = powLimit;
     117             :     }
     118             : 
     119           0 :     return bnNew.GetCompact();
     120             : }
     121             : 
     122      179272 : bool CheckProofOfWork(uint256 hash, unsigned int nBits)
     123             : {
     124      179272 :     bool fNegative;
     125      179272 :     bool fOverflow;
     126      179272 :     arith_uint256 bnTarget;
     127             : 
     128      179272 :     bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
     129             : 
     130             :     // Check range
     131      537816 :     if (fNegative || bnTarget.IsNull() || fOverflow || bnTarget > UintToArith256(Params().GetConsensus().powLimit))
     132           0 :         return error("CheckProofOfWork() : nBits below minimum work");
     133             : 
     134             :     // Check proof of work matches claimed amount
     135      358544 :     if (UintToArith256(hash) > bnTarget)
     136       13295 :         return error("CheckProofOfWork() : hash doesn't match nBits");
     137             : 
     138             :     return true;
     139             : }
     140             : 
     141       74923 : arith_uint256 GetBlockProof(const CBlockIndex& block)
     142             : {
     143       74923 :     arith_uint256 bnTarget;
     144       74923 :     bool fNegative;
     145       74923 :     bool fOverflow;
     146       74923 :     bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow);
     147      149846 :     if (fNegative || fOverflow || bnTarget.IsNull())
     148           0 :         return ARITH_UINT256_ZERO;
     149             :     // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
     150             :     // as it's too large for a uint256. However, as 2**256 is at least as large
     151             :     // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
     152             :     // or ~bnTarget / (nTarget+1) + 1.
     153     1123845 :     return (~bnTarget / (bnTarget + 1)) + 1;
     154             : }

Generated by: LCOV version 1.14