1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 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.
8 #include "arith_uint256.h"
10 #include "primitives/block.h"
14 unsigned int GetNextWorkRequired(const CBlockIndex
* pindexLast
, const CBlockHeader
*pblock
, const Consensus::Params
& params
)
16 unsigned int nProofOfWorkLimit
= UintToArith256(params
.powLimit
).GetCompact();
19 if (pindexLast
== NULL
)
20 return nProofOfWorkLimit
;
22 // Only change once per difficulty adjustment interval
23 if ((pindexLast
->nHeight
+1) % params
.DifficultyAdjustmentInterval() != 0)
25 if (params
.fPowAllowMinDifficultyBlocks
)
27 // Special difficulty rule for testnet:
28 // If the new block's timestamp is more than 2* 10 minutes
29 // then allow mining of a min-difficulty block.
30 if (pblock
->GetBlockTime() > pindexLast
->GetBlockTime() + params
.nPowTargetSpacing
*2)
31 return nProofOfWorkLimit
;
34 // Return the last non-special-min-difficulty-rules-block
35 const CBlockIndex
* pindex
= pindexLast
;
36 while (pindex
->pprev
&& pindex
->nHeight
% params
.DifficultyAdjustmentInterval() != 0 && pindex
->nBits
== nProofOfWorkLimit
)
37 pindex
= pindex
->pprev
;
41 return pindexLast
->nBits
;
44 // Go back by what we want to be 14 days worth of blocks
45 int nHeightFirst
= pindexLast
->nHeight
- (params
.DifficultyAdjustmentInterval()-1);
46 assert(nHeightFirst
>= 0);
47 const CBlockIndex
* pindexFirst
= pindexLast
->GetAncestor(nHeightFirst
);
50 return CalculateNextWorkRequired(pindexLast
, pindexFirst
->GetBlockTime(), params
);
53 unsigned int CalculateNextWorkRequired(const CBlockIndex
* pindexLast
, int64_t nFirstBlockTime
, const Consensus::Params
& params
)
55 // Limit adjustment step
56 int64_t nActualTimespan
= pindexLast
->GetBlockTime() - nFirstBlockTime
;
57 LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan
);
58 if (nActualTimespan
< params
.nPowTargetTimespan
/4)
59 nActualTimespan
= params
.nPowTargetTimespan
/4;
60 if (nActualTimespan
> params
.nPowTargetTimespan
*4)
61 nActualTimespan
= params
.nPowTargetTimespan
*4;
64 const arith_uint256 bnPowLimit
= UintToArith256(params
.powLimit
);
67 bnNew
.SetCompact(pindexLast
->nBits
);
69 bnNew
*= nActualTimespan
;
70 bnNew
/= params
.nPowTargetTimespan
;
72 if (bnNew
> bnPowLimit
)
76 LogPrintf("GetNextWorkRequired RETARGET\n");
77 LogPrintf("params.nPowTargetTimespan = %d nActualTimespan = %d\n", params
.nPowTargetTimespan
, nActualTimespan
);
78 LogPrintf("Before: %08x %s\n", pindexLast
->nBits
, bnOld
.ToString());
79 LogPrintf("After: %08x %s\n", bnNew
.GetCompact(), bnNew
.ToString());
81 return bnNew
.GetCompact();
84 bool CheckProofOfWork(uint256 hash
, unsigned int nBits
, const Consensus::Params
& params
)
88 arith_uint256 bnTarget
;
90 bnTarget
.SetCompact(nBits
, &fNegative
, &fOverflow
);
93 if (fNegative
|| bnTarget
== 0 || fOverflow
|| bnTarget
> UintToArith256(params
.powLimit
))
94 return error("CheckProofOfWork(): nBits below minimum work");
96 // Check proof of work matches claimed amount
97 if (UintToArith256(hash
) > bnTarget
)
98 return error("CheckProofOfWork(): hash doesn't match nBits");
103 arith_uint256
GetBlockProof(const CBlockIndex
& block
)
105 arith_uint256 bnTarget
;
108 bnTarget
.SetCompact(block
.nBits
, &fNegative
, &fOverflow
);
109 if (fNegative
|| fOverflow
|| bnTarget
== 0)
111 // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256
112 // as it's too large for a arith_uint256. However, as 2**256 is at least as large
113 // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1,
114 // or ~bnTarget / (nTarget+1) + 1.
115 return (~bnTarget
/ (bnTarget
+ 1)) + 1;
118 int64_t GetBlockProofEquivalentTime(const CBlockIndex
& to
, const CBlockIndex
& from
, const CBlockIndex
& tip
, const Consensus::Params
& params
)
122 if (to
.nChainWork
> from
.nChainWork
) {
123 r
= to
.nChainWork
- from
.nChainWork
;
125 r
= from
.nChainWork
- to
.nChainWork
;
128 r
= r
* arith_uint256(params
.nPowTargetSpacing
) / GetBlockProof(tip
);
130 return sign
* std::numeric_limits
<int64_t>::max();
132 return sign
* r
.GetLow64();