diff options
Diffstat (limited to 'src/pow.cpp')
| -rw-r--r-- | src/pow.cpp | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/src/pow.cpp b/src/pow.cpp index e91e3d893..bb53ad204 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -5,35 +5,35 @@ #include "pow.h" +#include "arith_uint256.h" #include "chain.h" -#include "chainparams.h" #include "primitives/block.h" #include "uint256.h" #include "util.h" -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock) +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params) { - unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact(); + unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact(); // Genesis block if (pindexLast == NULL) return nProofOfWorkLimit; - // Only change once per interval - if ((pindexLast->nHeight+1) % Params().Interval() != 0) + // Only change once per difficulty adjustment interval + if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0) { - if (Params().AllowMinDifficultyBlocks()) + if (params.fPowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. - if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + Params().TargetSpacing()*2) + if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + params.nPowTargetSpacing*2) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block const CBlockIndex* pindex = pindexLast; - while (pindex->pprev && pindex->nHeight % Params().Interval() != 0 && pindex->nBits == nProofOfWorkLimit) + while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } @@ -42,72 +42,92 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead } // Go back by what we want to be 14 days worth of blocks - const CBlockIndex* pindexFirst = pindexLast; - for (int i = 0; pindexFirst && i < Params().Interval()-1; i++) - pindexFirst = pindexFirst->pprev; + int nHeightFirst = pindexLast->nHeight - (params.DifficultyAdjustmentInterval()-1); + assert(nHeightFirst >= 0); + const CBlockIndex* pindexFirst = pindexLast->GetAncestor(nHeightFirst); assert(pindexFirst); + return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); +} + +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) +{ // Limit adjustment step - int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime(); + int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan); - if (nActualTimespan < Params().TargetTimespan()/4) - nActualTimespan = Params().TargetTimespan()/4; - if (nActualTimespan > Params().TargetTimespan()*4) - nActualTimespan = Params().TargetTimespan()*4; + if (nActualTimespan < params.nPowTargetTimespan/4) + nActualTimespan = params.nPowTargetTimespan/4; + if (nActualTimespan > params.nPowTargetTimespan*4) + nActualTimespan = params.nPowTargetTimespan*4; // Retarget - uint256 bnNew; - uint256 bnOld; + const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); + arith_uint256 bnNew; + arith_uint256 bnOld; bnNew.SetCompact(pindexLast->nBits); bnOld = bnNew; bnNew *= nActualTimespan; - bnNew /= Params().TargetTimespan(); + bnNew /= params.nPowTargetTimespan; - if (bnNew > Params().ProofOfWorkLimit()) - bnNew = Params().ProofOfWorkLimit(); + if (bnNew > bnPowLimit) + bnNew = bnPowLimit; /// debug print LogPrintf("GetNextWorkRequired RETARGET\n"); - LogPrintf("Params().TargetTimespan() = %d nActualTimespan = %d\n", Params().TargetTimespan(), nActualTimespan); + LogPrintf("params.nPowTargetTimespan = %d nActualTimespan = %d\n", params.nPowTargetTimespan, nActualTimespan); LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); return bnNew.GetCompact(); } -bool CheckProofOfWork(uint256 hash, unsigned int nBits) +bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) { bool fNegative; bool fOverflow; - uint256 bnTarget; - - if (Params().SkipProofOfWorkCheck()) - return true; + arith_uint256 bnTarget; bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range - if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) - return error("CheckProofOfWork() : nBits below minimum work"); + if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) + return error("CheckProofOfWork(): nBits below minimum work"); // Check proof of work matches claimed amount - if (hash > bnTarget) - return error("CheckProofOfWork() : hash doesn't match nBits"); + if (UintToArith256(hash) > bnTarget) + return error("CheckProofOfWork(): hash doesn't match nBits"); return true; } -uint256 GetBlockProof(const CBlockIndex& block) +arith_uint256 GetBlockProof(const CBlockIndex& block) { - uint256 bnTarget; + arith_uint256 bnTarget; bool fNegative; bool fOverflow; bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); if (fNegative || fOverflow || bnTarget == 0) return 0; // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 - // as it's too large for a uint256. However, as 2**256 is at least as large + // as it's too large for a arith_uint256. However, as 2**256 is at least as large // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1, // or ~bnTarget / (nTarget+1) + 1. return (~bnTarget / (bnTarget + 1)) + 1; } + +int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params) +{ + arith_uint256 r; + int sign = 1; + if (to.nChainWork > from.nChainWork) { + r = to.nChainWork - from.nChainWork; + } else { + r = from.nChainWork - to.nChainWork; + sign = -1; + } + r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip); + if (r.bits() > 63) { + return sign * std::numeric_limits<int64_t>::max(); + } + return sign * r.GetLow64(); +} |