diff --git a/src/miner.h b/src/miner.h --- a/src/miner.h +++ b/src/miner.h @@ -155,15 +155,27 @@ int nHeight; int64_t nLockTimeCutoff; int64_t nMedianTimePast; + const CChainParams &chainparams; + uint8_t nBlockPriorityPercentage; - const Config *config; const CTxMemPool *mempool; // Variables used for addPriorityTxs int lastFewTxs; public: - BlockAssembler(const Config &_config, const CTxMemPool &mempool); + struct Options { + Options(); + uint64_t nExcessiveBlockSize; + uint64_t nMaxGeneratedBlockSize; + CFeeRate blockMinFeeRate; + uint8_t nBlockPriorityPercentage; + }; + + BlockAssembler(const Config &config, const CTxMemPool &_mempool); + BlockAssembler(const CChainParams ¶ms, const CTxMemPool &_mempool, + const Options &options); + /** Construct a new block template with coinbase to scriptPubKeyIn */ std::unique_ptr CreateNewBlock(const CScript &scriptPubKeyIn); @@ -236,8 +248,8 @@ }; /** Modify the extranonce in a block */ -void IncrementExtraNonce(const Config &config, CBlock *pblock, - const CBlockIndex *pindexPrev, +void IncrementExtraNonce(CBlock *pblock, const CBlockIndex *pindexPrev, + uint64_t nExcessiveBlockSize, unsigned int &nExtraNonce); int64_t UpdateTime(CBlockHeader *pblock, const Consensus::Params ¶ms, const CBlockIndex *pindexPrev); diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -58,42 +58,54 @@ return nNewTime - nOldTime; } -static uint64_t ComputeMaxGeneratedBlockSize(const Config &config, - const CBlockIndex *pindexPrev) { +BlockAssembler::Options::Options() + : nExcessiveBlockSize(DEFAULT_MAX_BLOCK_SIZE), + nMaxGeneratedBlockSize(DEFAULT_MAX_GENERATED_BLOCK_SIZE), + blockMinFeeRate(DEFAULT_BLOCK_MIN_TX_FEE_PER_KB), + nBlockPriorityPercentage(DEFAULT_BLOCK_PRIORITY_PERCENTAGE) {} + +BlockAssembler::BlockAssembler(const CChainParams ¶ms, + const CTxMemPool &_mempool, + const Options &options) + : chainparams(params), mempool(&_mempool) { + blockMinFeeRate = options.blockMinFeeRate; + // Limit size to between 1K and options.nExcessiveBlockSize -1K for sanity: + nMaxGeneratedBlockSize = std::max( + 1000, std::min(options.nExcessiveBlockSize - 1000, + options.nMaxGeneratedBlockSize)); + // Reserve a portion of the block for high priority transactions. + nBlockPriorityPercentage = options.nBlockPriorityPercentage; +} + +static BlockAssembler::Options DefaultOptions(const Config &config) { // Block resource limits // If -blockmaxsize is not given, limit to DEFAULT_MAX_GENERATED_BLOCK_SIZE // If only one is given, only restrict the specified resource. // If both are given, restrict both. - uint64_t nMaxGeneratedBlockSize = DEFAULT_MAX_GENERATED_BLOCK_SIZE; + BlockAssembler::Options options; + + options.nExcessiveBlockSize = config.GetMaxBlockSize(); + if (gArgs.IsArgSet("-blockmaxsize")) { - nMaxGeneratedBlockSize = + options.nMaxGeneratedBlockSize = gArgs.GetArg("-blockmaxsize", DEFAULT_MAX_GENERATED_BLOCK_SIZE); } - // Limit size to between 1K and MaxBlockSize-1K for sanity: - nMaxGeneratedBlockSize = - std::max(uint64_t(1000), std::min(config.GetMaxBlockSize() - 1000, - nMaxGeneratedBlockSize)); - - return nMaxGeneratedBlockSize; -} - -BlockAssembler::BlockAssembler(const Config &_config, const CTxMemPool &mpool) - : config(&_config), mempool(&mpool) { - if (gArgs.IsArgSet("-blockmintxfee")) { Amount n = Amount::zero(); ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n); - blockMinFeeRate = CFeeRate(n); - } else { - blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE_PER_KB); + options.blockMinFeeRate = CFeeRate(n); } - LOCK(cs_main); - nMaxGeneratedBlockSize = - ComputeMaxGeneratedBlockSize(*config, chainActive.Tip()); + options.nBlockPriorityPercentage = config.GetBlockPriorityPercentage(); + + return options; } +BlockAssembler::BlockAssembler(const Config &config, const CTxMemPool &_mempool) + : BlockAssembler(config.GetChainParams(), _mempool, + DefaultOptions(config)) {} + void BlockAssembler::resetBlock() { inBlock.clear(); @@ -108,14 +120,6 @@ lastFewTxs = 0; } -static const std::vector -getExcessiveBlockSizeSig(const Config &config) { - std::string cbmsg = "/EB" + getSubVersionEB(config.GetMaxBlockSize()) + "/"; - const char *cbcstr = cbmsg.c_str(); - std::vector vec(cbcstr, cbcstr + cbmsg.size()); - return vec; -} - std::unique_ptr BlockAssembler::CreateNewBlock(const CScript &scriptPubKeyIn) { int64_t nTimeStart = GetTimeMicros(); @@ -138,7 +142,6 @@ assert(pindexPrev != nullptr); nHeight = pindexPrev->nHeight + 1; - const CChainParams &chainparams = config->GetChainParams(); pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()); // -regtest only: allow overriding block.nVersion with @@ -148,8 +151,6 @@ } pblock->nTime = GetAdjustedTime(); - nMaxGeneratedBlockSize = ComputeMaxGeneratedBlockSize(*config, pindexPrev); - nMedianTimePast = pindexPrev->GetMedianTimePast(); nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) @@ -224,8 +225,8 @@ } CValidationState state; - if (!TestBlockValidity(state, config->GetChainParams(), *pblock, pindexPrev, - BlockValidationOptions(*config) + if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, + BlockValidationOptions(nMaxGeneratedBlockSize) .withCheckPoW(false) .withCheckMerkleRoot(false))) { throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", @@ -290,9 +291,9 @@ uint64_t nPotentialBlockSize = nBlockSize; for (CTxMemPool::txiter it : package) { CValidationState state; - if (!ContextualCheckTransaction(config->GetChainParams().GetConsensus(), - it->GetTx(), state, nHeight, - nLockTimeCutoff, nMedianTimePast)) { + if (!ContextualCheckTransaction(chainparams.GetConsensus(), it->GetTx(), + state, nHeight, nLockTimeCutoff, + nMedianTimePast)) { return false; } @@ -343,9 +344,9 @@ // Must check that lock times are still valid. This can be removed once MTP // is always enforced as long as reorgs keep the mempool consistent. CValidationState state; - if (!ContextualCheckTransaction(config->GetChainParams().GetConsensus(), - it->GetTx(), state, nHeight, - nLockTimeCutoff, nMedianTimePast)) { + if (!ContextualCheckTransaction(chainparams.GetConsensus(), it->GetTx(), + state, nHeight, nLockTimeCutoff, + nMedianTimePast)) { return TestForBlockResult::TXCantFit; } @@ -589,12 +590,12 @@ void BlockAssembler::addPriorityTxs() { // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay. - if (config->GetBlockPriorityPercentage() == 0) { + if (nBlockPriorityPercentage == 0) { return; } uint64_t nBlockPrioritySize = - nMaxGeneratedBlockSize * config->GetBlockPriorityPercentage() / 100; + nMaxGeneratedBlockSize * nBlockPriorityPercentage / 100; // This vector will be sorted into a priority queue: std::vector vecPriority; @@ -680,8 +681,15 @@ } } -void IncrementExtraNonce(const Config &config, CBlock *pblock, - const CBlockIndex *pindexPrev, +static const std::vector +getExcessiveBlockSizeSig(uint64_t nExcessiveBlockSize) { + std::string cbmsg = "/EB" + getSubVersionEB(nExcessiveBlockSize) + "/"; + std::vector vec(cbmsg.begin(), cbmsg.end()); + return vec; +} + +void IncrementExtraNonce(CBlock *pblock, const CBlockIndex *pindexPrev, + uint64_t nExcessiveBlockSize, unsigned int &nExtraNonce) { // Update nExtraNonce static uint256 hashPrevBlock; @@ -696,7 +704,7 @@ CMutableTransaction txCoinbase(*pblock->vtx[0]); txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce) - << getExcessiveBlockSizeSig(config)) + + << getExcessiveBlockSizeSig(nExcessiveBlockSize)) + COINBASE_FLAGS; // Make sure the coinbase is big enough. diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -141,7 +141,8 @@ { LOCK(cs_main); - IncrementExtraNonce(config, pblock, chainActive.Tip(), nExtraNonce); + IncrementExtraNonce(pblock, chainActive.Tip(), + config.GetMaxBlockSize(), nExtraNonce); } while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -228,7 +228,8 @@ // IncrementExtraNonce creates a valid coinbase and merkleRoot unsigned int extraNonce = 0; - IncrementExtraNonce(config, pblock, chainActive.Tip(), extraNonce); + IncrementExtraNonce(pblock, chainActive.Tip(), config.GetMaxBlockSize(), + extraNonce); unsigned int nHeight = chainActive.Tip()->nHeight + 1; std::vector vec(cbmsg.begin(), cbmsg.end()); BOOST_CHECK(pblock->vtx[0]->vin[0].scriptSig == 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 @@ -178,7 +178,8 @@ { LOCK(cs_main); unsigned int extraNonce = 0; - IncrementExtraNonce(config, &block, chainActive.Tip(), extraNonce); + IncrementExtraNonce(&block, chainActive.Tip(), config.GetMaxBlockSize(), + extraNonce); } const Consensus::Params ¶ms = config.GetChainParams().GetConsensus(); diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -291,14 +291,17 @@ class BlockValidationOptions { private: + uint64_t excessiveBlockSize; bool checkPoW : 1; bool checkMerkleRoot : 1; - uint64_t excessiveBlockSize; - public: // Do full validation by default BlockValidationOptions(const Config &config); + BlockValidationOptions(uint64_t _excessiveBlockSize, bool _checkPow = true, + bool _checkMerkleRoot = true) + : excessiveBlockSize(_excessiveBlockSize), checkPoW(_checkPow), + checkMerkleRoot(_checkMerkleRoot) {} BlockValidationOptions withCheckPoW(bool _checkPoW = true) const { BlockValidationOptions ret = *this; diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -297,8 +297,8 @@ } // namespace BlockValidationOptions::BlockValidationOptions(const Config &config) - : checkPoW(true), checkMerkleRoot(true), - excessiveBlockSize(config.GetMaxBlockSize()) {} + : excessiveBlockSize(config.GetMaxBlockSize()), checkPoW(true), + checkMerkleRoot(true) {} CBlockIndex *FindForkInGlobalIndex(const CChain &chain, const CBlockLocator &locator) {