diff --git a/src/miner.h b/src/miner.h --- a/src/miner.h +++ b/src/miner.h @@ -161,17 +161,16 @@ int64_t nLockTimeCutoff; int64_t nMedianTimePast; - const Config *config; const CTxMemPool *mempool; // Variables used for addPriorityTxs int lastFewTxs; public: - BlockAssembler(const Config &_config, const CTxMemPool &mempool); + BlockAssembler(const Config &config, const CTxMemPool &mempool); /** Construct a new block template with coinbase to scriptPubKeyIn */ std::unique_ptr - CreateNewBlock(const CScript &scriptPubKeyIn); + CreateNewBlock(const Config &config, const CScript &scriptPubKeyIn); uint64_t GetMaxGeneratedBlockSize() const { return nMaxGeneratedBlockSize; } @@ -184,13 +183,14 @@ // Methods for how to add transactions to a block. /** Add transactions based on tx "priority" */ - void addPriorityTxs(); + void addPriorityTxs(const Config &config); /** * Add transactions based on feerate including unconfirmed ancestors. * Increments nPackagesSelected / nDescendantsUpdated with corresponding * statistics from the package selection (for logging statistics). */ - void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) + void addPackageTxs(const Config &config, int &nPackagesSelected, + int &nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(mempool->cs); /** Enum for the results from TestForBlock */ @@ -202,7 +202,8 @@ // helper function for addPriorityTxs /** Test if tx will still "fit" in the block */ - TestForBlockResult TestForBlock(CTxMemPool::txiter iter); + TestForBlockResult TestForBlock(const Config &config, + CTxMemPool::txiter iter); /** Test if tx still has unconfirmed parents not yet in block */ bool isStillDependent(CTxMemPool::txiter iter); @@ -217,7 +218,8 @@ * succeed, and they're here only as an extra check in case of suboptimal * node configuration. */ - bool TestPackageTransactions(const CTxMemPool::setEntries &package); + bool TestPackageTransactions(const Config &config, + const CTxMemPool::setEntries &package); /** * Return true if given transaction from mapTx has already been evaluated, * or if the transaction's cached data in mapTx is incorrect. diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -81,8 +81,8 @@ return nMaxGeneratedBlockSize; } -BlockAssembler::BlockAssembler(const Config &_config, const CTxMemPool &mpool) - : config(&_config), mempool(&mpool) { +BlockAssembler::BlockAssembler(const Config &config, const CTxMemPool &mpool) + : mempool(&mpool) { if (gArgs.IsArgSet("-blockmintxfee")) { Amount n = Amount::zero(); @@ -94,7 +94,7 @@ LOCK(cs_main); nMaxGeneratedBlockSize = - ComputeMaxGeneratedBlockSize(*config, chainActive.Tip()); + ComputeMaxGeneratedBlockSize(config, chainActive.Tip()); } void BlockAssembler::resetBlock() { @@ -120,7 +120,8 @@ } std::unique_ptr -BlockAssembler::CreateNewBlock(const CScript &scriptPubKeyIn) { +BlockAssembler::CreateNewBlock(const Config &config, + const CScript &scriptPubKeyIn) { int64_t nTimeStart = GetTimeMicros(); resetBlock(); @@ -141,7 +142,7 @@ assert(pindexPrev != nullptr); nHeight = pindexPrev->nHeight + 1; - const CChainParams &chainparams = config->GetChainParams(); + const CChainParams &chainparams = config.GetChainParams(); pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus()); // -regtest only: allow overriding block.nVersion with @@ -151,7 +152,7 @@ } pblock->nTime = GetAdjustedTime(); - nMaxGeneratedBlockSize = ComputeMaxGeneratedBlockSize(*config, pindexPrev); + nMaxGeneratedBlockSize = ComputeMaxGeneratedBlockSize(config, pindexPrev); nMedianTimePast = pindexPrev->GetMedianTimePast(); nLockTimeCutoff = @@ -159,12 +160,12 @@ ? nMedianTimePast : pblock->GetBlockTime(); - addPriorityTxs(); + addPriorityTxs(config); int nPackagesSelected = 0; int nDescendantsUpdated = 0; - addPackageTxs(nPackagesSelected, nDescendantsUpdated); + addPackageTxs(config, nPackagesSelected, nDescendantsUpdated); - if (IsMagneticAnomalyEnabled(*config, pindexPrev)) { + if (IsMagneticAnomalyEnabled(config, pindexPrev)) { // If magnetic anomaly is enabled, we make sure transaction are // canonically ordered. // FIXME: Use a zipped list. See T479 @@ -212,8 +213,8 @@ // Fill in header. pblock->hashPrevBlock = pindexPrev->GetBlockHash(); - UpdateTime(pblock, *config, pindexPrev); - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, *config); + UpdateTime(pblock, config, pindexPrev); + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, config); pblock->nNonce = 0; pblocktemplate->entries[0].txSigOps = GetSigOpCountWithoutP2SH( *pblocktemplate->entries[0].tx, STANDARD_SCRIPT_VERIFY_FLAGS); @@ -227,7 +228,7 @@ CValidationState state; BlockValidationOptions validationOptions(false, false); - if (!TestBlockValidity(*config, state, *pblock, pindexPrev, + if (!TestBlockValidity(config, state, *pblock, pindexPrev, validationOptions)) { throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, @@ -287,11 +288,11 @@ * - Serialized size (in case -blockmaxsize is in use) */ bool BlockAssembler::TestPackageTransactions( - const CTxMemPool::setEntries &package) { + const Config &config, const CTxMemPool::setEntries &package) { uint64_t nPotentialBlockSize = nBlockSize; for (const CTxMemPool::txiter it : package) { CValidationState state; - if (!ContextualCheckTransaction(*config, it->GetTx(), state, nHeight, + if (!ContextualCheckTransaction(config, it->GetTx(), state, nHeight, nLockTimeCutoff, nMedianTimePast)) { return false; } @@ -309,7 +310,7 @@ } BlockAssembler::TestForBlockResult -BlockAssembler::TestForBlock(CTxMemPool::txiter it) { +BlockAssembler::TestForBlock(const Config &config, CTxMemPool::txiter it) { auto blockSizeWithTx = nBlockSize + ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION); @@ -343,7 +344,7 @@ // 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, it->GetTx(), state, nHeight, + if (!ContextualCheckTransaction(config, it->GetTx(), state, nHeight, nLockTimeCutoff, nMedianTimePast)) { return TestForBlockResult::TXCantFit; } @@ -438,7 +439,7 @@ * @param[out] nPackagesSelected How many packages were selected * @param[out] nDescendantsUpdated Number of descendant transactions updated */ -void BlockAssembler::addPackageTxs(int &nPackagesSelected, +void BlockAssembler::addPackageTxs(const Config &config, int &nPackagesSelected, int &nDescendantsUpdated) { // selection algorithm orders the mempool based on feerate of a @@ -556,7 +557,7 @@ ancestors.insert(iter); // Test if all tx's are Final. - if (!TestPackageTransactions(ancestors)) { + if (!TestPackageTransactions(config, ancestors)) { if (fUsingModified) { mapModifiedTx.get().erase(modit); failedTx.insert(iter); @@ -584,15 +585,15 @@ } } -void BlockAssembler::addPriorityTxs() { +void BlockAssembler::addPriorityTxs(const Config &config) { // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay. - if (config->GetBlockPriorityPercentage() == 0) { + if (config.GetBlockPriorityPercentage() == 0) { return; } uint64_t nBlockPrioritySize = - nMaxGeneratedBlockSize * config->GetBlockPriorityPercentage() / 100; + nMaxGeneratedBlockSize * config.GetBlockPriorityPercentage() / 100; // This vector will be sorted into a priority queue: std::vector vecPriority; @@ -638,7 +639,7 @@ continue; } - TestForBlockResult testResult = TestForBlock(iter); + TestForBlockResult testResult = TestForBlock(config, iter); // Break if the block is completed if (testResult == TestForBlockResult::BlockFinished) { break; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -131,7 +131,7 @@ while (nHeight < nHeightEnd && !ShutdownRequested()) { std::unique_ptr pblocktemplate( BlockAssembler(config, g_mempool) - .CreateNewBlock(coinbaseScript->reserveScript)); + .CreateNewBlock(config, coinbaseScript->reserveScript)); if (!pblocktemplate.get()) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); @@ -591,8 +591,8 @@ // Create new block CScript scriptDummy = CScript() << OP_TRUE; - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptDummy); + pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptDummy); if (!pblocktemplate) { throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); } 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 @@ -126,7 +126,7 @@ .FromTx(tx)); std::unique_ptr pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[1]->GetId() == parentTxId); BOOST_CHECK(pblocktemplate->block.vtx[2]->GetId() == highFeeTxId); BOOST_CHECK(pblocktemplate->block.vtx[3]->GetId() == mediumFeeTxId); @@ -149,7 +149,7 @@ TxId lowFeeTxId = tx.GetId(); g_mempool.addUnchecked(lowFeeTxId, entry.Fee(feeToUse).FromTx(tx)); pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); // Verify that the free tx and the low fee tx didn't get selected. for (const auto &txn : pblocktemplate->block.vtx) { BOOST_CHECK(txn->GetId() != freeTxId); @@ -166,7 +166,7 @@ g_mempool.addUnchecked(lowFeeTxId, entry.Fee(feeToUse + 2 * SATOSHI).FromTx(tx)); pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[4]->GetId() == freeTxId); BOOST_CHECK(pblocktemplate->block.vtx[5]->GetId() == lowFeeTxId); @@ -191,7 +191,7 @@ g_mempool.addUnchecked( lowFeeTxId2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); // Verify that this tx isn't selected. for (const auto &txn : pblocktemplate->block.vtx) { @@ -206,7 +206,7 @@ tx.vout[0].nValue = (100000000 - 10000) * SATOSHI; g_mempool.addUnchecked(tx.GetId(), entry.Fee(10000 * SATOSHI).FromTx(tx)); pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[8]->GetId() == lowFeeTxId2); } @@ -221,7 +221,7 @@ << OP_CHECKSIG; std::unique_ptr pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); CBlock *pblock = &pblocktemplate->block; @@ -265,9 +265,8 @@ GlobalConfig config; // Simple block creation, nothing special yet: - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); // We can't make transactions until we have inputs. Therefore, load 100 // blocks :) @@ -306,9 +305,8 @@ LOCK(cs_main); // Just to make sure we can still make simple blocks. - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); const Amount BLOCKSUBSIDY = 50 * COIN; const Amount LOWFEE = CENT; @@ -337,7 +335,7 @@ tx.vin[0].prevout = COutPoint(txid, 0); } BOOST_CHECK_THROW( - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey), + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey), std::runtime_error); g_mempool.clear(); @@ -357,9 +355,8 @@ .FromTx(tx)); tx.vin[0].prevout = COutPoint(txid, 0); } - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); g_mempool.clear(); // block size > limit @@ -384,16 +381,15 @@ .FromTx(tx)); tx.vin[0].prevout = COutPoint(txid, 0); } - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); g_mempool.clear(); // Orphan in mempool, template creation fails. TxId txid = tx.GetId(); g_mempool.addUnchecked(txid, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); BOOST_CHECK_THROW( - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey), + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey), std::runtime_error); g_mempool.clear(); @@ -415,9 +411,8 @@ g_mempool.addUnchecked( txid, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); g_mempool.clear(); // Coinbase in mempool, template creation fails. @@ -431,7 +426,7 @@ txid, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); BOOST_CHECK_THROW( - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey), + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey), std::runtime_error); g_mempool.clear(); @@ -450,7 +445,7 @@ txid, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK_THROW( - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey), + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey), std::runtime_error); g_mempool.clear(); @@ -467,9 +462,8 @@ next->BuildSkip(); chainActive.SetTip(next); } - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); // Extend to a 210000-long block chain. while (chainActive.Tip()->nHeight < 210000) { CBlockIndex *prev = chainActive.Tip(); @@ -481,9 +475,8 @@ next->BuildSkip(); chainActive.SetTip(next); } - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); // Invalid p2sh txn in mempool, template creation fails tx.vin[0].prevout = COutPoint(txFirst[0]->GetId(), 0); @@ -504,7 +497,7 @@ txid, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); BOOST_CHECK_THROW( - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey), + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey), std::runtime_error); g_mempool.clear(); @@ -675,7 +668,7 @@ BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); BOOST_CHECK(pblocktemplate); // None of the of the absolute height/time locked tx should have made it @@ -693,9 +686,8 @@ chainActive.Tip()->nHeight++; SetMockTime(chainActive.Tip()->GetMedianTimePast() + 1); - BOOST_CHECK( - pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey)); + BOOST_CHECK(pblocktemplate = BlockAssembler(config, g_mempool) + .CreateNewBlock(config, scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5UL); chainActive.Tip()->nHeight--; 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 @@ -169,7 +169,7 @@ const std::vector &txns, const CScript &scriptPubKey) { const Config &config = GetConfig(); std::unique_ptr pblocktemplate = - BlockAssembler(config, g_mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, g_mempool).CreateNewBlock(config, scriptPubKey); CBlock &block = pblocktemplate->block; // Replace mempool-selected txns with just coinbase plus passed-in txns: diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -56,7 +56,8 @@ CScript pubKey; pubKey << i++ << OP_TRUE; - auto ptemplate = BlockAssembler(config, g_mempool).CreateNewBlock(pubKey); + auto ptemplate = + BlockAssembler(config, g_mempool).CreateNewBlock(config, pubKey); auto pblock = std::make_shared(ptemplate->block); pblock->hashPrevBlock = prev_hash; pblock->nTime = ++time;