diff options
Diffstat (limited to 'src/pow.cpp')
-rw-r--r-- | src/pow.cpp | 123 |
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(); +} |