From df852d2bcc6573a3fcb3e59f82f7ea4dfa11290e Mon Sep 17 00:00:00 2001 From: jtimon Date: Mon, 10 Mar 2014 08:46:53 -0700 Subject: Refactor proof of work related functions out of main --- src/pow.cpp | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/pow.cpp (limited to 'src/pow.cpp') diff --git a/src/pow.cpp b/src/pow.cpp new file mode 100644 index 000000000..274a5d6f9 --- /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(); +} -- cgit v1.2.3 From fd704c7b2c5ab8b24b1829f000b829d7156b8b3c Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 22 Mar 2014 18:29:34 +0100 Subject: move pow constants to chainparams --- src/pow.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'src/pow.cpp') diff --git a/src/pow.cpp b/src/pow.cpp index 274a5d6f9..952250dec 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -10,10 +10,6 @@ #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(); @@ -23,20 +19,20 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return nProofOfWorkLimit; // Only change once per interval - if ((pindexLast->nHeight+1) % nInterval != 0) + if ((pindexLast->nHeight+1) % Params().Interval() != 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) + if (pblock->nTime > pindexLast->nTime + Params().TargetSpacing()*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) + while (pindex->pprev && pindex->nHeight % Params().Interval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } @@ -46,17 +42,17 @@ 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 < nInterval-1; i++) + for (int i = 0; pindexFirst && i < Params().Interval()-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; + if (nActualTimespan < Params().TargetTimespan()/4) + nActualTimespan = Params().TargetTimespan()/4; + if (nActualTimespan > Params().TargetTimespan()*4) + nActualTimespan = Params().TargetTimespan()*4; // Retarget uint256 bnNew; @@ -64,14 +60,14 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead bnNew.SetCompact(pindexLast->nBits); bnOld = bnNew; bnNew *= nActualTimespan; - bnNew /= nTargetTimespan; + bnNew /= Params().TargetTimespan(); if (bnNew > Params().ProofOfWorkLimit()) bnNew = Params().ProofOfWorkLimit(); /// debug print LogPrintf("GetNextWorkRequired RETARGET\n"); - LogPrintf("nTargetTimespan = %d nActualTimespan = %d\n", nTargetTimespan, nActualTimespan); + LogPrintf("Params().TargetTimespan() = %d nActualTimespan = %d\n", Params().TargetTimespan(), nActualTimespan); LogPrintf("Before: %08x %s\n", pindexLast->nBits, bnOld.ToString()); LogPrintf("After: %08x %s\n", bnNew.GetCompact(), bnNew.ToString()); @@ -104,8 +100,8 @@ 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) + // after Params().TargetSpacing()*2 time between blocks: + if (Params().AllowMinDifficultyBlocks() && nTime > Params().TargetSpacing()*2) return bnLimit.GetCompact(); uint256 bnResult; @@ -115,7 +111,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) // Maximum 400% adjustment... bnResult *= 4; // ... in best-case exactly 4-times-normal target time - nTime -= nTargetTimespan*4; + nTime -= Params().TargetTimespan()*4; } if (bnResult > bnLimit) bnResult = bnLimit; -- cgit v1.2.3 From 209377a7cb5a9ea5d724faf94846ee5bacd289e7 Mon Sep 17 00:00:00 2001 From: jtimon Date: Sat, 28 Jun 2014 23:36:06 +0200 Subject: Use GetBlockTime() more --- src/pow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pow.cpp') diff --git a/src/pow.cpp b/src/pow.cpp index 952250dec..c0d0a7ca2 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -26,7 +26,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead // 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 + Params().TargetSpacing()*2) + if (pblock->GetBlockTime() > pindexLast->GetBlockTime() + Params().TargetSpacing()*2) return nProofOfWorkLimit; else { -- cgit v1.2.3