/root/bitcoin/src/pow.cpp
| Line | Count | Source | 
| 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 |  | unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) | 
| 15 | 2.60k | { | 
| 16 | 2.60k |     assert(pindexLast != nullptr); | 
| 17 | 2.60k |     unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); | 
| 18 |  |  | 
| 19 |  |     // Only change once per difficulty adjustment interval | 
| 20 | 2.60k |     if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) | 
| 21 | 2.60k |     { | 
| 22 | 2.60k |         if (params.fPowAllowMinDifficultyBlocks) | 
| 23 | 2.60k |         { | 
| 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 | 2.60k |             if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) | 
| 28 | 2.55k |                 return nProofOfWorkLimit; | 
| 29 | 45 |             else | 
| 30 | 45 |             { | 
| 31 |  |                 // Return the last non-special-min-difficulty-rules-block | 
| 32 | 45 |                 const CBlockIndex* pindex = pindexLast; | 
| 33 | 2.56k |                 while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) | 
| 34 | 2.52k |                     pindex = pindex->pprev; | 
| 35 | 45 |                 return pindex->nBits; | 
| 36 | 45 |             } | 
| 37 | 2.60k |         } | 
| 38 | 0 |         return pindexLast->nBits; | 
| 39 | 2.60k |     } | 
| 40 |  |  | 
| 41 |  |     // Go back by what we want to be 14 days worth of blocks | 
| 42 | 0 |     int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); | 
| 43 | 0 |     assert(nHeightFirst >= 0); | 
| 44 | 0 |     const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); | 
| 45 | 0 |     assert(pindexFirst); | 
| 46 |  |  | 
| 47 | 0 |     return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); | 
| 48 | 0 | } | 
| 49 |  |  | 
| 50 |  | unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) | 
| 51 | 0 | { | 
| 52 | 0 |     if (params.fPowNoRetargeting) | 
| 53 | 0 |         return pindexLast->nBits; | 
| 54 |  |  | 
| 55 |  |     // Limit adjustment step | 
| 56 | 0 |     int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; | 
| 57 | 0 |     if (nActualTimespan < params.nPowTargetTimespan/4) | 
| 58 | 0 |         nActualTimespan = params.nPowTargetTimespan/4; | 
| 59 | 0 |     if (nActualTimespan > params.nPowTargetTimespan*4) | 
| 60 | 0 |         nActualTimespan = params.nPowTargetTimespan*4; | 
| 61 |  |  | 
| 62 |  |     // Retarget | 
| 63 | 0 |     const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); | 
| 64 | 0 |     arith_uint256 bnNew; | 
| 65 |  |  | 
| 66 |  |     // Special difficulty rule for Testnet4 | 
| 67 | 0 |     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 | 0 |     } else { | 
| 75 | 0 |         bnNew.SetCompact(pindexLast->nBits); | 
| 76 | 0 |     } | 
| 77 |  | 
 | 
| 78 | 0 |     bnNew *= nActualTimespan; | 
| 79 | 0 |     bnNew /= params.nPowTargetTimespan; | 
| 80 |  | 
 | 
| 81 | 0 |     if (bnNew > bnPowLimit) | 
| 82 | 0 |         bnNew = bnPowLimit; | 
| 83 |  | 
 | 
| 84 | 0 |     return bnNew.GetCompact(); | 
| 85 | 0 | } | 
| 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 | 0 | { | 
| 91 | 0 |     if (params.fPowAllowMinDifficultyBlocks) return true; | 
| 92 |  |  | 
| 93 | 0 |     if (height % params.DifficultyAdjustmentInterval() == 0) { | 
| 94 | 0 |         int64_t smallest_timespan = params.nPowTargetTimespan/4; | 
| 95 | 0 |         int64_t largest_timespan = params.nPowTargetTimespan*4; | 
| 96 |  | 
 | 
| 97 | 0 |         const arith_uint256 pow_limit = UintToArith256(params.powLimit); | 
| 98 | 0 |         arith_uint256 observed_new_target; | 
| 99 | 0 |         observed_new_target.SetCompact(new_nbits); | 
| 100 |  |  | 
| 101 |  |         // Calculate the largest difficulty value possible: | 
| 102 | 0 |         arith_uint256 largest_difficulty_target; | 
| 103 | 0 |         largest_difficulty_target.SetCompact(old_nbits); | 
| 104 | 0 |         largest_difficulty_target *= largest_timespan; | 
| 105 | 0 |         largest_difficulty_target /= params.nPowTargetTimespan; | 
| 106 |  | 
 | 
| 107 | 0 |         if (largest_difficulty_target > pow_limit) { | 
| 108 | 0 |             largest_difficulty_target = pow_limit; | 
| 109 | 0 |         } | 
| 110 |  |  | 
| 111 |  |         // Round and then compare this new calculated value to what is | 
| 112 |  |         // observed. | 
| 113 | 0 |         arith_uint256 maximum_new_target; | 
| 114 | 0 |         maximum_new_target.SetCompact(largest_difficulty_target.GetCompact()); | 
| 115 | 0 |         if (maximum_new_target < observed_new_target) return false; | 
| 116 |  |  | 
| 117 |  |         // Calculate the smallest difficulty value possible: | 
| 118 | 0 |         arith_uint256 smallest_difficulty_target; | 
| 119 | 0 |         smallest_difficulty_target.SetCompact(old_nbits); | 
| 120 | 0 |         smallest_difficulty_target *= smallest_timespan; | 
| 121 | 0 |         smallest_difficulty_target /= params.nPowTargetTimespan; | 
| 122 |  | 
 | 
| 123 | 0 |         if (smallest_difficulty_target > pow_limit) { | 
| 124 | 0 |             smallest_difficulty_target = pow_limit; | 
| 125 | 0 |         } | 
| 126 |  |  | 
| 127 |  |         // Round and then compare this new calculated value to what is | 
| 128 |  |         // observed. | 
| 129 | 0 |         arith_uint256 minimum_new_target; | 
| 130 | 0 |         minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact()); | 
| 131 | 0 |         if (minimum_new_target > observed_new_target) return false; | 
| 132 | 0 |     } else if (old_nbits != new_nbits) { | 
| 133 | 0 |         return false; | 
| 134 | 0 |     } | 
| 135 | 0 |     return true; | 
| 136 | 0 | } | 
| 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 | 0 | { | 
| 142 | 0 |     if (EnableFuzzDeterminism()) return (hash.data()[31] & 0x80) == 0; | 
| 143 | 0 |     return CheckProofOfWorkImpl(hash, nBits, params); | 
| 144 | 0 | } | 
| 145 |  |  | 
| 146 |  | std::optional<arith_uint256> DeriveTarget(unsigned int nBits, const uint256 pow_limit) | 
| 147 | 0 | { | 
| 148 | 0 |     bool fNegative; | 
| 149 | 0 |     bool fOverflow; | 
| 150 | 0 |     arith_uint256 bnTarget; | 
| 151 |  | 
 | 
| 152 | 0 |     bnTarget.SetCompact(nBits, &fNegative, &fOverflow); | 
| 153 |  |  | 
| 154 |  |     // Check range | 
| 155 | 0 |     if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(pow_limit)) | 
| 156 | 0 |         return {}; | 
| 157 |  |  | 
| 158 | 0 |     return bnTarget; | 
| 159 | 0 | } | 
| 160 |  |  | 
| 161 |  | bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params) | 
| 162 | 0 | { | 
| 163 | 0 |     auto bnTarget{DeriveTarget(nBits, params.powLimit)}; | 
| 164 | 0 |     if (!bnTarget) return false; | 
| 165 |  |  | 
| 166 |  |     // Check proof of work matches claimed amount | 
| 167 | 0 |     if (UintToArith256(hash) > bnTarget) | 
| 168 | 0 |         return false; | 
| 169 |  |  | 
| 170 | 0 |     return true; | 
| 171 | 0 | } |