From d698ef690f62c08676dcf9ddc0988e23aa81cbff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Sun, 15 Feb 2015 02:21:42 +0100 Subject: [PATCH] Consensus: Refactor: Decouple pow.o from chainparams.o --- src/main.cpp | 6 +++--- src/main.h | 1 - src/miner.cpp | 4 ++-- src/pow.cpp | 39 +++++++++++++++++++-------------------- src/pow.h | 8 +++++--- src/rpcmining.cpp | 2 +- src/test/pow_tests.cpp | 13 +++++++++---- src/txdb.cpp | 4 +++- 8 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0ffacc338e..1d78eedc1a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1158,7 +1158,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) } // Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits)) + if (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); return true; @@ -2462,7 +2462,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW) { // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits)) + if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) return state.DoS(50, error("CheckBlockHeader(): proof of work failed"), REJECT_INVALID, "high-hash"); @@ -2545,7 +2545,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta int nHeight = pindexPrev->nHeight+1; // Check proof of work - if ((block.nBits != GetNextWorkRequired(pindexPrev, &block))) + if (block.nBits != GetNextWorkRequired(pindexPrev, &block, Params().GetConsensus())) return state.DoS(100, error("%s: incorrect proof of work", __func__), REJECT_INVALID, "bad-diffbits"); diff --git a/src/main.h b/src/main.h index b0bab6f7bf..09ffc4d28b 100644 --- a/src/main.h +++ b/src/main.h @@ -17,7 +17,6 @@ #include "primitives/block.h" #include "primitives/transaction.h" #include "net.h" -#include "pow.h" #include "script/script.h" #include "script/sigcache.h" #include "script/standard.h" diff --git a/src/miner.cpp b/src/miner.cpp index 01212b19c4..cf08b78229 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -84,7 +84,7 @@ void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev) // Updating time can change work required on testnet: if (Params().AllowMinDifficultyBlocks()) - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); } CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -326,7 +326,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); UpdateTime(pblock, pindexPrev); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); pblock->nNonce = 0; pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); diff --git a/src/pow.cpp b/src/pow.cpp index eb899ffc94..3c5a8d9d96 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -7,34 +7,33 @@ #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 = 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 ((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().DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) + while (pindex->pprev && pindex->nHeight % params.DifficultyAdjustmentInterval() != 0 && pindex->nBits == nProofOfWorkLimit) pindex = pindex->pprev; return pindex->nBits; } @@ -44,22 +43,22 @@ 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().DifficultyAdjustmentInterval()-1; i++) + for (int i = 0; pindexFirst && i < params.DifficultyAdjustmentInterval()-1; i++) pindexFirst = pindexFirst->pprev; assert(pindexFirst); - return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime()); + return CalculateNextWorkRequired(pindexLast, pindexFirst->GetBlockTime(), params); } -unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime) +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) { // Limit adjustment step 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 arith_uint256 bnNew; @@ -67,21 +66,21 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF bnNew.SetCompact(pindexLast->nBits); bnOld = bnNew; bnNew *= nActualTimespan; - bnNew /= Params().TargetTimespan(); + bnNew /= params.nPowTargetTimespan; - if (bnNew > Params().ProofOfWorkLimit()) - bnNew = Params().ProofOfWorkLimit(); + if (bnNew > params.powLimit) + bnNew = params.powLimit; /// 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; @@ -90,7 +89,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range - if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit()) + if (fNegative || bnTarget == 0 || fOverflow || bnTarget > params.powLimit) return error("CheckProofOfWork(): nBits below minimum work"); // Check proof of work matches claimed amount diff --git a/src/pow.h b/src/pow.h index a5fbba6236..a5d32db178 100644 --- a/src/pow.h +++ b/src/pow.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_POW_H #define BITCOIN_POW_H +#include "consensus/params.h" + #include class CBlockHeader; @@ -13,11 +15,11 @@ class CBlockIndex; class uint256; class arith_uint256; -unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock); -unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime); +unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params&); +unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params&); /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ -bool CheckProofOfWork(uint256 hash, unsigned int nBits); +bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&); arith_uint256 GetBlockProof(const CBlockIndex& block); #endif // BITCOIN_POW_H diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 17db221cb4..fcba7e222d 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -181,7 +181,7 @@ Value setgenerate(const Array& params, bool fHelp) LOCK(cs_main); IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); } - while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits)) { + while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) { // Yes, there is a chance every nonce could fail to satisfy the -regtest // target -- 1 in 2^(2^32). That ain't gonna happen. ++pblock->nNonce; diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 7b197c527d..4ce1591c35 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -17,51 +17,56 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(get_next_work) { SelectParams(CBaseChainParams::MAIN); + const Consensus::Params& params = Params().GetConsensus(); int64_t nLastRetargetTime = 1261130161; // Block #30240 CBlockIndex pindexLast; pindexLast.nHeight = 32255; pindexLast.nTime = 1262152739; // Block #32255 pindexLast.nBits = 0x1d00ffff; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00d86a); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00d86a); } /* Test the constraint on the upper bound for next work */ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) { SelectParams(CBaseChainParams::MAIN); + const Consensus::Params& params = Params().GetConsensus(); int64_t nLastRetargetTime = 1231006505; // Block #0 CBlockIndex pindexLast; pindexLast.nHeight = 2015; pindexLast.nTime = 1233061996; // Block #2015 pindexLast.nBits = 0x1d00ffff; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00ffff); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00ffff); } /* Test the constraint on the lower bound for actual time taken */ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) { SelectParams(CBaseChainParams::MAIN); + const Consensus::Params& params = Params().GetConsensus(); int64_t nLastRetargetTime = 1279008237; // Block #66528 CBlockIndex pindexLast; pindexLast.nHeight = 68543; pindexLast.nTime = 1279297671; // Block #68543 pindexLast.nBits = 0x1c05a3f4; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1c0168fd); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1c0168fd); } /* Test the constraint on the upper bound for actual time taken */ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) { SelectParams(CBaseChainParams::MAIN); + const Consensus::Params& params = Params().GetConsensus(); + int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time CBlockIndex pindexLast; pindexLast.nHeight = 46367; pindexLast.nTime = 1269211443; // Block #46367 pindexLast.nBits = 0x1c387f6f; - BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime), 0x1d00e1fd); + BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/txdb.cpp b/src/txdb.cpp index f328150289..df9ff8d8c9 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -5,6 +5,8 @@ #include "txdb.h" +#include "chainparams.h" +#include "hash.h" #include "main.h" #include "pow.h" #include "uint256.h" @@ -223,7 +225,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; - if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits)) + if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus())) return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString()); pcursor->Next();