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