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