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 : 0 : unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
15 : : {
16 [ # # ]: 0 : assert(pindexLast != nullptr);
17 : 0 : unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
18 : :
19 : : // Only change once per difficulty adjustment interval
20 [ # # ]: 0 : if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
21 : : {
22 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # # # : 0 : while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
# # ]
34 : : pindex = pindex->pprev;
35 : 0 : return pindex->nBits;
36 : : }
37 : : }
38 : 0 : return pindexLast->nBits;
39 : : }
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 : : }
49 : :
50 : 0 : unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
51 : : {
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 : : } else {
75 : 0 : bnNew.SetCompact(pindexLast->nBits);
76 : : }
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 : : }
86 : :
87 : : // Check that on difficulty adjustments, the new difficulty does not increase
88 : : // or decrease beyond the permitted limits.
89 : 0 : bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits)
90 : : {
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 : : }
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 : : }
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 : : }
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 : 0 : bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
141 : : {
142 : 0 : if constexpr (G_FUZZING) return (hash.data()[31] & 0x80) == 0;
143 : : return CheckProofOfWorkImpl(hash, nBits, params);
144 : : }
145 : :
146 : 0 : bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params)
147 : : {
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(params.powLimit))
# # # # ]
156 : 0 : return false;
157 : :
158 : : // Check proof of work matches claimed amount
159 [ # # ]: 0 : if (UintToArith256(hash) > bnTarget)
160 : 0 : return false;
161 : :
162 : : return true;
163 : : }
|