diff --git a/src/chain.h b/src/chain.h --- a/src/chain.h +++ b/src/chain.h @@ -7,6 +7,7 @@ #define BITCOIN_CHAIN_H #include "arith_uint256.h" +#include "consensus/params.h" #include "pow.h" #include "primitives/block.h" #include "tinyformat.h" diff --git a/src/miner.h b/src/miner.h --- a/src/miner.h +++ b/src/miner.h @@ -22,10 +22,6 @@ class CScript; class CWallet; -namespace Consensus { -struct Params; -}; - static const bool DEFAULT_PRINTPRIORITY = false; struct CBlockTemplate { diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -74,8 +74,7 @@ // Updating time can change work required on testnet: if (consensusParams.fPowAllowMinDifficultyBlocks) { - pblock->nBits = - GetNextWorkRequired(pindexPrev, pblock, consensusParams); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, config); } return nNewTime - nOldTime; @@ -212,8 +211,7 @@ // Fill in header. pblock->hashPrevBlock = pindexPrev->GetBlockHash(); UpdateTime(pblock, *config, pindexPrev); - pblock->nBits = - GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, *config); pblock->nNonce = 0; pblocktemplate->vTxSigOpsCount[0] = GetSigOpCountWithoutP2SH(*pblock->vtx[0]); diff --git a/src/pow.h b/src/pow.h --- a/src/pow.h +++ b/src/pow.h @@ -6,32 +6,30 @@ #ifndef BITCOIN_POW_H #define BITCOIN_POW_H -#include "consensus/params.h" - #include class CBlockHeader; class CBlockIndex; +class Config; class uint256; uint32_t GetNextWorkRequired(const CBlockIndex *pindexPrev, - const CBlockHeader *pblock, - const Consensus::Params &); + const CBlockHeader *pblock, const Config &config); uint32_t CalculateNextWorkRequired(const CBlockIndex *pindexPrev, int64_t nFirstBlockTime, - const Consensus::Params &); + const Config &config); /** * Check whether a block hash satisfies the proof-of-work requirement specified * by nBits */ -bool CheckProofOfWork(uint256 hash, uint32_t nBits, const Consensus::Params &); +bool CheckProofOfWork(uint256 hash, uint32_t nBits, const Config &config); /** * Bitcoin cash's difficulty adjustment mechanism. */ uint32_t GetNextCashWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, - const Consensus::Params ¶ms); + const Config &config); #endif // BITCOIN_POW_H diff --git a/src/pow.cpp b/src/pow.cpp --- a/src/pow.cpp +++ b/src/pow.cpp @@ -8,6 +8,9 @@ #include "arith_uint256.h" #include "chain.h" +#include "chainparams.h" +#include "config.h" +#include "consensus/params.h" #include "primitives/block.h" #include "uint256.h" #include "util.h" @@ -18,7 +21,9 @@ */ static uint32_t GetNextEDAWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, - const Consensus::Params ¶ms) { + const Config &config) { + const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); + // Only change once per difficulty adjustment interval uint32_t nHeight = pindexPrev->nHeight + 1; if (nHeight % params.DifficultyAdjustmentInterval() == 0) { @@ -29,7 +34,7 @@ assert(pindexFirst); return CalculateNextWorkRequired(pindexPrev, - pindexFirst->GetBlockTime(), params); + pindexFirst->GetBlockTime(), config); } const uint32_t nProofOfWorkLimit = @@ -87,8 +92,9 @@ } uint32_t GetNextWorkRequired(const CBlockIndex *pindexPrev, - const CBlockHeader *pblock, - const Consensus::Params ¶ms) { + const CBlockHeader *pblock, const Config &config) { + const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); + // Genesis block if (pindexPrev == nullptr) { return UintToArith256(params.powLimit).GetCompact(); @@ -100,15 +106,17 @@ } if (pindexPrev->GetMedianTimePast() >= params.cashHardForkActivationTime) { - return GetNextCashWorkRequired(pindexPrev, pblock, params); + return GetNextCashWorkRequired(pindexPrev, pblock, config); } - return GetNextEDAWorkRequired(pindexPrev, pblock, params); + return GetNextEDAWorkRequired(pindexPrev, pblock, config); } uint32_t CalculateNextWorkRequired(const CBlockIndex *pindexPrev, int64_t nFirstBlockTime, - const Consensus::Params ¶ms) { + const Config &config) { + const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); + if (params.fPowNoRetargeting) { return pindexPrev->nBits; } @@ -135,8 +143,7 @@ return bnNew.GetCompact(); } -bool CheckProofOfWork(uint256 hash, uint32_t nBits, - const Consensus::Params ¶ms) { +bool CheckProofOfWork(uint256 hash, uint32_t nBits, const Config &config) { bool fNegative; bool fOverflow; arith_uint256 bnTarget; @@ -145,7 +152,8 @@ // Check range if (fNegative || bnTarget == 0 || fOverflow || - bnTarget > UintToArith256(params.powLimit)) { + bnTarget > + UintToArith256(config.GetChainParams().GetConsensus().powLimit)) { return false; } @@ -239,7 +247,9 @@ */ uint32_t GetNextCashWorkRequired(const CBlockIndex *pindexPrev, const CBlockHeader *pblock, - const Consensus::Params ¶ms) { + const Config &config) { + const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); + // This cannot handle the genesis block and early blocks in general. assert(pindexPrev); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -132,26 +132,32 @@ std::unique_ptr pblocktemplate( BlockAssembler(config, Params()) .CreateNewBlock(coinbaseScript->reserveScript)); + if (!pblocktemplate.get()) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); } + CBlock *pblock = &pblocktemplate->block; + { LOCK(cs_main); IncrementExtraNonce(config, pblock, chainActive.Tip(), nExtraNonce); } + while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && - !CheckProofOfWork(pblock->GetHash(), pblock->nBits, - Params().GetConsensus())) { + !CheckProofOfWork(pblock->GetHash(), pblock->nBits, config)) { ++pblock->nNonce; --nMaxTries; } + if (nMaxTries == 0) { break; } + if (pblock->nNonce == nInnerLoopCount) { continue; } + std::shared_ptr shared_pblock = std::make_shared(*pblock); if (!ProcessNewBlock(config, shared_pblock, true, nullptr)) { @@ -669,8 +675,11 @@ // Need to update only after we know CreateNewBlock succeeded pindexPrev = pindexPrevNew; } - CBlock *pblock = &pblocktemplate->block; // pointer for convenience - const Consensus::Params &consensusParams = Params().GetConsensus(); + + // pointer for convenience + CBlock *pblock = &pblocktemplate->block; + const Consensus::Params &consensusParams = + config.GetChainParams().GetConsensus(); // Update nTime UpdateTime(pblock, config, pindexPrev); diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -48,9 +48,12 @@ bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); - while (!CheckProofOfWork(block.GetHash(), block.nBits, - Params().GetConsensus())) + + GlobalConfig config; + while (!CheckProofOfWork(block.GetHash(), block.nBits, config)) { ++block.nNonce; + } + return block; } @@ -328,9 +331,11 @@ bool mutated; block.hashMerkleRoot = BlockMerkleRoot(block, &mutated); assert(!mutated); - while (!CheckProofOfWork(block.GetHash(), block.nBits, - Params().GetConsensus())) + + GlobalConfig config; + while (!CheckProofOfWork(block.GetHash(), block.nBits, config)) { ++block.nNonce; + } // Test simple header round-trip with only coinbase { diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -5,6 +5,7 @@ #include "pow.h" #include "chain.h" #include "chainparams.h" +#include "config.h" #include "random.h" #include "test/test_bitcoin.h" #include "util.h" @@ -16,7 +17,7 @@ /* Test calculation of next difficulty target with no constraints applying */ BOOST_AUTO_TEST_CASE(get_next_work) { SelectParams(CBaseChainParams::MAIN); - const Consensus::Params ¶ms = Params().GetConsensus(); + GlobalConfig config; int64_t nLastRetargetTime = 1261130161; // Block #30240 CBlockIndex pindexLast; @@ -24,14 +25,14 @@ pindexLast.nTime = 1262152739; // Block #32255 pindexLast.nBits = 0x1d00ffff; BOOST_CHECK_EQUAL( - CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), + CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, config), 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 ¶ms = Params().GetConsensus(); + GlobalConfig config; int64_t nLastRetargetTime = 1231006505; // Block #0 CBlockIndex pindexLast; @@ -39,14 +40,14 @@ pindexLast.nTime = 1233061996; // Block #2015 pindexLast.nBits = 0x1d00ffff; BOOST_CHECK_EQUAL( - CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), + CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, config), 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 ¶ms = Params().GetConsensus(); + GlobalConfig config; int64_t nLastRetargetTime = 1279008237; // Block #66528 CBlockIndex pindexLast; @@ -54,14 +55,14 @@ pindexLast.nTime = 1279297671; // Block #68543 pindexLast.nBits = 0x1c05a3f4; BOOST_CHECK_EQUAL( - CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), + CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, config), 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 ¶ms = Params().GetConsensus(); + GlobalConfig config; int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time CBlockIndex pindexLast; @@ -69,7 +70,7 @@ pindexLast.nTime = 1269211443; // Block #46367 pindexLast.nBits = 0x1c387f6f; BOOST_CHECK_EQUAL( - CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), + CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, config), 0x1d00e1fd); } @@ -112,10 +113,11 @@ BOOST_AUTO_TEST_CASE(retargeting_test) { SelectParams(CBaseChainParams::MAIN); - const Consensus::Params ¶ms = Params().GetConsensus(); + GlobalConfig config; std::vector blocks(115); + const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); const arith_uint256 powLimit = UintToArith256(params.powLimit); arith_uint256 currentPow = powLimit >> 1; uint32_t initialBits = currentPow.GetCompact(); @@ -142,7 +144,7 @@ for (size_t i = 100; i < 110; i++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 2 * 3600, initialBits); BOOST_CHECK_EQUAL( - GetNextWorkRequired(&blocks[i], &blkHeaderDummy, params), + GetNextWorkRequired(&blocks[i], &blkHeaderDummy, config), initialBits); } @@ -151,7 +153,7 @@ currentPow.SetCompact(currentPow.GetCompact()); currentPow += (currentPow >> 2); BOOST_CHECK_EQUAL( - GetNextWorkRequired(&blocks[110], &blkHeaderDummy, params), + GetNextWorkRequired(&blocks[110], &blkHeaderDummy, config), currentPow.GetCompact()); // As we continue with 2h blocks, difficulty continue to decrease. @@ -160,7 +162,7 @@ currentPow.SetCompact(currentPow.GetCompact()); currentPow += (currentPow >> 2); BOOST_CHECK_EQUAL( - GetNextWorkRequired(&blocks[111], &blkHeaderDummy, params), + GetNextWorkRequired(&blocks[111], &blkHeaderDummy, config), currentPow.GetCompact()); // We decrease again. @@ -169,7 +171,7 @@ currentPow.SetCompact(currentPow.GetCompact()); currentPow += (currentPow >> 2); BOOST_CHECK_EQUAL( - GetNextWorkRequired(&blocks[112], &blkHeaderDummy, params), + GetNextWorkRequired(&blocks[112], &blkHeaderDummy, config), currentPow.GetCompact()); // We check that we do not go below the minimal difficulty. @@ -179,23 +181,24 @@ currentPow += (currentPow >> 2); BOOST_CHECK(powLimit.GetCompact() != currentPow.GetCompact()); BOOST_CHECK_EQUAL( - GetNextWorkRequired(&blocks[113], &blkHeaderDummy, params), + GetNextWorkRequired(&blocks[113], &blkHeaderDummy, config), powLimit.GetCompact()); // Once we reached the minimal difficulty, we stick with it. blocks[114] = GetBlockIndex(&blocks[113], 2 * 3600, powLimit.GetCompact()); BOOST_CHECK(powLimit.GetCompact() != currentPow.GetCompact()); BOOST_CHECK_EQUAL( - GetNextWorkRequired(&blocks[114], &blkHeaderDummy, params), + GetNextWorkRequired(&blocks[114], &blkHeaderDummy, config), powLimit.GetCompact()); } BOOST_AUTO_TEST_CASE(cash_difficulty_test) { SelectParams(CBaseChainParams::MAIN); - const Consensus::Params ¶ms = Params().GetConsensus(); + GlobalConfig config; std::vector blocks(3000); + const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); const arith_uint256 powLimit = UintToArith256(params.powLimit); uint32_t powLimitBits = powLimit.GetCompact(); arith_uint256 currentPow = powLimit >> 4; @@ -219,13 +222,13 @@ CBlockHeader blkHeaderDummy; uint32_t nBits = - GetNextCashWorkRequired(&blocks[2049], &blkHeaderDummy, params); + GetNextCashWorkRequired(&blocks[2049], &blkHeaderDummy, config); // Difficulty stays the same as long as we produce a block every 10 mins. for (size_t j = 0; j < 10; i++, j++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 600, nBits); BOOST_CHECK_EQUAL( - GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, params), + GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, config), nBits); } @@ -234,30 +237,30 @@ // expected timestamp. blocks[i] = GetBlockIndex(&blocks[i - 1], 6000, nBits); BOOST_CHECK_EQUAL( - GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, params), nBits); + GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, config), nBits); blocks[i] = GetBlockIndex(&blocks[i - 1], 2 * 600 - 6000, nBits); BOOST_CHECK_EQUAL( - GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, params), nBits); + GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, config), nBits); // The system should continue unaffected by the block with a bogous // timestamps. for (size_t j = 0; j < 20; i++, j++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 600, nBits); BOOST_CHECK_EQUAL( - GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, params), + GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, config), nBits); } // We start emitting blocks slightly faster. The first block has no impact. blocks[i] = GetBlockIndex(&blocks[i - 1], 550, nBits); BOOST_CHECK_EQUAL( - GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, params), nBits); + GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, config), nBits); // Now we should see difficulty increase slowly. for (size_t j = 0; j < 10; i++, j++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 550, nBits); const uint32_t nextBits = - GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, params); + GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, config); arith_uint256 currentTarget; currentTarget.SetCompact(nBits); @@ -278,7 +281,7 @@ for (size_t j = 0; j < 20; i++, j++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 10, nBits); const uint32_t nextBits = - GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, params); + GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, config); arith_uint256 currentTarget; currentTarget.SetCompact(nBits); @@ -298,7 +301,7 @@ // We start to emit blocks significantly slower. The first block has no // impact. blocks[i] = GetBlockIndex(&blocks[i - 1], 6000, nBits); - nBits = GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, params); + nBits = GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, config); // Check the actual value. BOOST_CHECK_EQUAL(nBits, 0x1c0d9222); @@ -307,7 +310,7 @@ for (size_t j = 0; j < 93; i++, j++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 6000, nBits); const uint32_t nextBits = - GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, params); + GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, config); arith_uint256 currentTarget; currentTarget.SetCompact(nBits); @@ -328,7 +331,7 @@ // Due to the window of time being bounded, next block's difficulty actually // gets harder. blocks[i] = GetBlockIndex(&blocks[i - 1], 6000, nBits); - nBits = GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, params); + nBits = GetNextCashWorkRequired(&blocks[i++], &blkHeaderDummy, config); BOOST_CHECK_EQUAL(nBits, 0x1c2ee9bf); // And goes down again. It takes a while due to the window being bounded and @@ -336,7 +339,7 @@ for (size_t j = 0; j < 192; i++, j++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 6000, nBits); const uint32_t nextBits = - GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, params); + GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, config); arith_uint256 currentTarget; currentTarget.SetCompact(nBits); @@ -359,7 +362,7 @@ for (size_t j = 0; j < 5; i++, j++) { blocks[i] = GetBlockIndex(&blocks[i - 1], 6000, nBits); const uint32_t nextBits = - GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, params); + GetNextCashWorkRequired(&blocks[i], &blkHeaderDummy, config); // Check the difficulty stays constant. BOOST_CHECK_EQUAL(nextBits, powLimitBits); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -26,12 +26,10 @@ #include "test/testutil.h" -#include -#include - #include #include #include +#include #include #include #include @@ -149,8 +147,7 @@ unsigned int extraNonce = 0; IncrementExtraNonce(config, &block, chainActive.Tip(), extraNonce); - while (!CheckProofOfWork(block.GetHash(), block.nBits, - chainparams.GetConsensus())) { + while (!CheckProofOfWork(block.GetHash(), block.nBits, config)) { ++block.nNonce; } diff --git a/src/txdb.cpp b/src/txdb.cpp --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -6,6 +6,7 @@ #include "txdb.h" #include "chainparams.h" +#include "config.h" #include "hash.h" #include "pow.h" #include "uint256.h" @@ -221,6 +222,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts( std::function insertBlockIndex) { + const Config &config = GetConfig(); + std::unique_ptr pcursor(NewIterator()); pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256())); @@ -254,9 +257,10 @@ pindexNew->nTx = diskindex.nTx; if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, - Params().GetConsensus())) + config)) { return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString()); + } pcursor->Next(); } diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1147,8 +1147,7 @@ } // Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits, - config.GetChainParams().GetConsensus())) { + if (!CheckProofOfWork(block.GetHash(), block.nBits, config)) { return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); } @@ -3195,12 +3194,8 @@ static bool CheckBlockHeader(const Config &config, const CBlockHeader &block, CValidationState &state, bool fCheckPOW = true) { - const Consensus::Params &consensusParams = - config.GetChainParams().GetConsensus(); - // Check proof of work matches claimed amount - if (fCheckPOW && - !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) { + if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, config)) { return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed"); } @@ -3354,8 +3349,7 @@ const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; // Check proof of work - if (block.nBits != - GetNextWorkRequired(pindexPrev, &block, consensusParams)) { + if (block.nBits != GetNextWorkRequired(pindexPrev, &block, config)) { return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work"); }