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 : 0 : unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
14 : : {
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 : : {
21 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # # # : 0 : while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
# # ]
33 : : pindex = pindex->pprev;
34 : 0 : return pindex->nBits;
35 : : }
36 : : }
37 : 0 : return pindexLast->nBits;
38 : : }
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 : : }
48 : :
49 : 0 : unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
50 : : {
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 : : } else {
74 : 0 : bnNew.SetCompact(pindexLast->nBits);
75 : : }
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 : : }
85 : :
86 : : // Check that on difficulty adjustments, the new difficulty does not increase
87 : : // or decrease beyond the permitted limits.
88 : 0 : bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits)
89 : : {
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 : : }
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 : : }
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 : : }
134 : : return true;
135 : : }
136 : :
137 : 2 : bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
138 : : {
139 : 2 : bool fNegative;
140 : 2 : bool fOverflow;
141 : 2 : arith_uint256 bnTarget;
142 : :
143 : 2 : bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
144 : :
145 : : // Check range
146 [ + - + - : 4 : if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
+ - - + ]
147 : 0 : return false;
148 : :
149 : : // Check proof of work matches claimed amount
150 [ - + ]: 2 : if (UintToArith256(hash) > bnTarget)
151 : 0 : return false;
152 : :
153 : : return true;
154 : : }
|