/root/bitcoin/src/pow.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
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 | 0 | { |
22 | 0 | if (params.fPowAllowMinDifficultyBlocks) |
23 | 0 | { |
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 | 0 | return nProofOfWorkLimit; |
29 | 0 | else |
30 | 0 | { |
31 | | // Return the last non-special-min-difficulty-rules-block |
32 | 0 | const CBlockIndex* pindex = pindexLast; |
33 | 0 | while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) |
34 | 0 | pindex = pindex->pprev; |
35 | 0 | return pindex->nBits; |
36 | 0 | } |
37 | 0 | } |
38 | 0 | return pindexLast->nBits; |
39 | 0 | } |
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 constexpr (G_FUZZING) 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 | } |