aboutsummaryrefslogtreecommitdiff
path: root/src/pow.cpp
diff options
context:
space:
mode:
authorjtimon <jtimon@monetize.io>2014-03-10 08:46:53 -0700
committerjtimon <jtimon@monetize.io>2014-06-23 23:10:24 +0200
commitdf852d2bcc6573a3fcb3e59f82f7ea4dfa11290e (patch)
treef8651a97cf4617ce0a867f964f5c70b0f2bf8090 /src/pow.cpp
parent36db6633c314b0f41aeee856f74a8d5d59334dbb (diff)
downloadbitcoin-df852d2bcc6573a3fcb3e59f82f7ea4dfa11290e.tar.xz
Refactor proof of work related functions out of main
Diffstat (limited to 'src/pow.cpp')
-rw-r--r--src/pow.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/pow.cpp b/src/pow.cpp
new file mode 100644
index 0000000000..274a5d6f98
--- /dev/null
+++ b/src/pow.cpp
@@ -0,0 +1,123 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "pow.h"
+
+#include "chainparams.h"
+#include "core.h"
+#include "main.h"
+#include "uint256.h"
+
+static const int64_t nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
+static const int64_t nTargetSpacing = 10 * 60;
+static const int64_t nInterval = nTargetTimespan / nTargetSpacing;
+
+unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
+{
+ unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact();
+
+ // Genesis block
+ if (pindexLast == NULL)
+ return nProofOfWorkLimit;
+
+ // Only change once per interval
+ if ((pindexLast->nHeight+1) % nInterval != 0)
+ {
+ if (Params().AllowMinDifficultyBlocks())
+ {
+ // 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->nTime > pindexLast->nTime + nTargetSpacing*2)
+ return nProofOfWorkLimit;
+ else
+ {
+ // Return the last non-special-min-difficulty-rules-block
+ const CBlockIndex* pindex = pindexLast;
+ while (pindex->pprev && pindex->nHeight % nInterval != 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
+ const CBlockIndex* pindexFirst = pindexLast;
+ for (int i = 0; pindexFirst && i < nInterval-1; i++)
+ pindexFirst = pindexFirst->pprev;
+ assert(pindexFirst);
+
+ // Limit adjustment step
+ int64_t nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
+ LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
+ if (nActualTimespan < nTargetTimespan/4)
+ nActualTimespan = nTargetTimespan/4;
+ if (nActualTimespan > nTargetTimespan*4)
+ nActualTimespan = nTargetTimespan*4;
+
+ // Retarget
+ uint256 bnNew;
+ uint256 bnOld;
+ bnNew.SetCompact(pindexLast->nBits);
+ bnOld = bnNew;
+ bnNew *= nActualTimespan;
+ bnNew /= nTargetTimespan;
+
+ if (bnNew > Params().ProofOfWorkLimit())
+ bnNew = Params().ProofOfWorkLimit();
+
+ /// debug print
+ LogPrintf("GetNextWorkRequired RETARGET\n");
+ LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, 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 fNegative;
+ bool fOverflow;
+ uint256 bnTarget;
+ bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
+
+ // Check range
+ if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit())
+ 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");
+
+ return true;
+}
+
+//
+// minimum amount of work that could possibly be required nTime after
+// minimum work required was nBase
+//
+unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
+{
+ const uint256 &bnLimit = Params().ProofOfWorkLimit();
+ // Testnet has min-difficulty blocks
+ // after nTargetSpacing*2 time between blocks:
+ if (Params().AllowMinDifficultyBlocks() && nTime > nTargetSpacing*2)
+ return bnLimit.GetCompact();
+
+ uint256 bnResult;
+ bnResult.SetCompact(nBase);
+ while (nTime > 0 && bnResult < bnLimit)
+ {
+ // Maximum 400% adjustment...
+ bnResult *= 4;
+ // ... in best-case exactly 4-times-normal target time
+ nTime -= nTargetTimespan*4;
+ }
+ if (bnResult > bnLimit)
+ bnResult = bnLimit;
+ return bnResult.GetCompact();
+}