aboutsummaryrefslogtreecommitdiff
path: root/src/pow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pow.cpp')
-rw-r--r--src/pow.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/pow.cpp b/src/pow.cpp
new file mode 100644
index 0000000000..5ace3fbc9b
--- /dev/null
+++ b/src/pow.cpp
@@ -0,0 +1,136 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "pow.h"
+
+#include "arith_uint256.h"
+#include "chain.h"
+#include "primitives/block.h"
+#include "uint256.h"
+#include "util.h"
+
+unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
+{
+ unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
+
+ // Genesis block
+ if (pindexLast == NULL)
+ return nProofOfWorkLimit;
+
+ // Only change once per difficulty adjustment interval
+ if ((pindexLast->nHeight+1) % params.DifficultyAdjustmentInterval() != 0)
+ {
+ 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.nPowTargetSpacing*2)
+ return nProofOfWorkLimit;
+ else
+ {
+ // Return the last non-special-min-difficulty-rules-block
+ const CBlockIndex* pindex = pindexLast;
+ while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit)
+ pindex = pindex->pprev;
+ return pindex->nBits;
+ }
+ }
+ return pindexLast->nBits;
+ }
+
+ // Go back by what we want to be 14 days worth of blocks
+ 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)
+{
+ if (params.fPowNoRetargeting)
+ return pindexLast->nBits;
+
+ // Limit adjustment step
+ int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
+ LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
+ if (nActualTimespan < params.nPowTargetTimespan/4)
+ nActualTimespan = params.nPowTargetTimespan/4;
+ if (nActualTimespan > params.nPowTargetTimespan*4)
+ nActualTimespan = params.nPowTargetTimespan*4;
+
+ // Retarget
+ const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
+ arith_uint256 bnNew;
+ arith_uint256 bnOld;
+ bnNew.SetCompact(pindexLast->nBits);
+ bnOld = bnNew;
+ bnNew *= nActualTimespan;
+ bnNew /= params.nPowTargetTimespan;
+
+ if (bnNew > bnPowLimit)
+ bnNew = bnPowLimit;
+
+ /// debug print
+ LogPrintf("GetNextWorkRequired RETARGET\n");
+ 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, const Consensus::Params& params)
+{
+ bool fNegative;
+ bool fOverflow;
+ arith_uint256 bnTarget;
+
+ bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
+
+ // Check range
+ if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
+ return error("CheckProofOfWork(): nBits below minimum work");
+
+ // Check proof of work matches claimed amount
+ if (UintToArith256(hash) > bnTarget)
+ return error("CheckProofOfWork(): hash doesn't match nBits");
+
+ return true;
+}
+
+arith_uint256 GetBlockProof(const CBlockIndex& block)
+{
+ 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 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();
+}