/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 | | |
13 | | unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) |
14 | 0 | { |
15 | 0 | assert(pindexLast != nullptr); |
16 | 0 | unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); |
17 | | |
18 | | // Only change once per difficulty adjustment interval |
19 | 0 | if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) |
20 | 0 | { |
21 | 0 | if (params.fPowAllowMinDifficultyBlocks) |
22 | 0 | { |
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 | 0 | if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) |
27 | 0 | return nProofOfWorkLimit; |
28 | 0 | else |
29 | 0 | { |
30 | | // Return the last non-special-min-difficulty-rules-block |
31 | 0 | const CBlockIndex* pindex = pindexLast; |
32 | 0 | while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) |
33 | 0 | pindex = pindex->pprev; |
34 | 0 | return pindex->nBits; |
35 | 0 | } |
36 | 0 | } |
37 | 0 | return pindexLast->nBits; |
38 | 0 | } |
39 | | |
40 | | // Go back by what we want to be 14 days worth of blocks |
41 | 0 | int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); |
42 | 0 | assert(nHeightFirst >= 0); |
43 | 0 | const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); |
44 | 0 | assert(pindexFirst); |
45 | | |
46 | 0 | return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); |
47 | 0 | } |
48 | | |
49 | | unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) |
50 | 0 | { |
51 | 0 | if (params.fPowNoRetargeting) |
52 | 0 | return pindexLast->nBits; |
53 | | |
54 | | // Limit adjustment step |
55 | 0 | int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; |
56 | 0 | if (nActualTimespan < params.nPowTargetTimespan/4) |
57 | 0 | nActualTimespan = params.nPowTargetTimespan/4; |
58 | 0 | if (nActualTimespan > params.nPowTargetTimespan*4) |
59 | 0 | nActualTimespan = params.nPowTargetTimespan*4; |
60 | | |
61 | | // Retarget |
62 | 0 | const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); |
63 | 0 | arith_uint256 bnNew; |
64 | | |
65 | | // Special difficulty rule for Testnet4 |
66 | 0 | 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 | 0 | } else { |
74 | 0 | bnNew.SetCompact(pindexLast->nBits); |
75 | 0 | } |
76 | |
|
77 | 0 | bnNew *= nActualTimespan; |
78 | 0 | bnNew /= params.nPowTargetTimespan; |
79 | |
|
80 | 0 | if (bnNew > bnPowLimit) |
81 | 0 | bnNew = bnPowLimit; |
82 | |
|
83 | 0 | return bnNew.GetCompact(); |
84 | 0 | } |
85 | | |
86 | | // Check that on difficulty adjustments, the new difficulty does not increase |
87 | | // or decrease beyond the permitted limits. |
88 | | bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits) |
89 | 0 | { |
90 | 0 | if (params.fPowAllowMinDifficultyBlocks) return true; |
91 | | |
92 | 0 | if (height % params.DifficultyAdjustmentInterval() == 0) { |
93 | 0 | int64_t smallest_timespan = params.nPowTargetTimespan/4; |
94 | 0 | int64_t largest_timespan = params.nPowTargetTimespan*4; |
95 | |
|
96 | 0 | const arith_uint256 pow_limit = UintToArith256(params.powLimit); |
97 | 0 | arith_uint256 observed_new_target; |
98 | 0 | observed_new_target.SetCompact(new_nbits); |
99 | | |
100 | | // Calculate the largest difficulty value possible: |
101 | 0 | arith_uint256 largest_difficulty_target; |
102 | 0 | largest_difficulty_target.SetCompact(old_nbits); |
103 | 0 | largest_difficulty_target *= largest_timespan; |
104 | 0 | largest_difficulty_target /= params.nPowTargetTimespan; |
105 | |
|
106 | 0 | if (largest_difficulty_target > pow_limit) { |
107 | 0 | largest_difficulty_target = pow_limit; |
108 | 0 | } |
109 | | |
110 | | // Round and then compare this new calculated value to what is |
111 | | // observed. |
112 | 0 | arith_uint256 maximum_new_target; |
113 | 0 | maximum_new_target.SetCompact(largest_difficulty_target.GetCompact()); |
114 | 0 | if (maximum_new_target < observed_new_target) return false; |
115 | | |
116 | | // Calculate the smallest difficulty value possible: |
117 | 0 | arith_uint256 smallest_difficulty_target; |
118 | 0 | smallest_difficulty_target.SetCompact(old_nbits); |
119 | 0 | smallest_difficulty_target *= smallest_timespan; |
120 | 0 | smallest_difficulty_target /= params.nPowTargetTimespan; |
121 | |
|
122 | 0 | if (smallest_difficulty_target > pow_limit) { |
123 | 0 | smallest_difficulty_target = pow_limit; |
124 | 0 | } |
125 | | |
126 | | // Round and then compare this new calculated value to what is |
127 | | // observed. |
128 | 0 | arith_uint256 minimum_new_target; |
129 | 0 | minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact()); |
130 | 0 | if (minimum_new_target > observed_new_target) return false; |
131 | 0 | } else if (old_nbits != new_nbits) { |
132 | 0 | return false; |
133 | 0 | } |
134 | 0 | return true; |
135 | 0 | } |
136 | | |
137 | | // Bypasses the actual proof of work check during fuzz testing with a simplified validation checking whether |
138 | | // the most signficant bit of the last byte of the hash is set. |
139 | | bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) |
140 | 0 | { |
141 | 0 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
142 | 0 | return (hash.data()[31] & 0x80) == 0; |
143 | | #else |
144 | | return CheckProofOfWorkImpl(hash, nBits, params); |
145 | | #endif |
146 | 0 | } |
147 | | |
148 | | bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params) |
149 | 0 | { |
150 | 0 | bool fNegative; |
151 | 0 | bool fOverflow; |
152 | 0 | arith_uint256 bnTarget; |
153 | |
|
154 | 0 | bnTarget.SetCompact(nBits, &fNegative, &fOverflow); |
155 | | |
156 | | // Check range |
157 | 0 | if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) |
158 | 0 | return false; |
159 | | |
160 | | // Check proof of work matches claimed amount |
161 | 0 | if (UintToArith256(hash) > bnTarget) |
162 | 0 | return false; |
163 | | |
164 | 0 | return true; |
165 | 0 | } |