diff --git a/src/miner.h b/src/miner.h --- a/src/miner.h +++ b/src/miner.h @@ -169,7 +169,7 @@ /** Construct a new block template with coinbase to scriptPubKeyIn */ std::unique_ptr - CreateNewBlock(const CScript &scriptPubKeyIn); + CreateNewBlock(CChainState &chainstate, const CScript &scriptPubKeyIn); uint64_t GetMaxGeneratedBlockSize() const { return nMaxGeneratedBlockSize; } diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -118,7 +118,8 @@ std::optional BlockAssembler::m_last_block_size{std::nullopt}; std::unique_ptr -BlockAssembler::CreateNewBlock(const CScript &scriptPubKeyIn) { +BlockAssembler::CreateNewBlock(CChainState &chainstate, + const CScript &scriptPubKeyIn) { int64_t nTimeStart = GetTimeMicros(); resetBlock(); @@ -135,7 +136,9 @@ pblocktemplate->entries.emplace_back(CTransactionRef(), -SATOSHI, -1); LOCK2(cs_main, m_mempool.cs); - CBlockIndex *pindexPrev = ::ChainActive().Tip(); + assert(std::addressof(*::ChainActive().Tip()) == + std::addressof(*chainstate.m_chain.Tip())); + CBlockIndex *pindexPrev = chainstate.m_chain.Tip(); assert(pindexPrev != nullptr); nHeight = pindexPrev->nHeight + 1; @@ -222,8 +225,8 @@ pblocktemplate->entries[0].sigOpCount = 0; BlockValidationState state; - if (!TestBlockValidity(state, chainParams, ::ChainstateActive(), *pblock, - pindexPrev, + assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate)); + if (!TestBlockValidity(state, chainParams, chainstate, *pblock, pindexPrev, BlockValidationOptions(nMaxGeneratedBlockSize) .withCheckPoW(false) .withCheckMerkleRoot(false))) { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -177,7 +177,8 @@ UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd && !ShutdownRequested()) { std::unique_ptr pblocktemplate( - BlockAssembler(config, mempool).CreateNewBlock(coinbase_script)); + BlockAssembler(config, mempool) + .CreateNewBlock(::ChainstateActive(), coinbase_script)); if (!pblocktemplate.get()) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); @@ -439,7 +440,7 @@ CTxMemPool empty_mempool; std::unique_ptr blocktemplate( BlockAssembler(config, empty_mempool) - .CreateNewBlock(coinbase_script)); + .CreateNewBlock(::ChainstateActive(), coinbase_script)); if (!blocktemplate) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); @@ -924,7 +925,8 @@ // Create new block CScript scriptDummy = CScript() << OP_TRUE; pblocktemplate = - BlockAssembler(config, mempool).CreateNewBlock(scriptDummy); + BlockAssembler(config, mempool) + .CreateNewBlock(::ChainstateActive(), scriptDummy); if (!pblocktemplate) { throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); } diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -69,7 +69,8 @@ const CScript &scriptPubKey) { const Config &config = GetConfig(); std::unique_ptr pblocktemplate = - BlockAssembler(config, *m_node.mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, *m_node.mempool) + .CreateNewBlock(::ChainstateActive(), scriptPubKey); CBlock &block = pblocktemplate->block; block.hashPrevBlock = prev->GetBlockHash(); block.nTime = prev->nTime + 1; 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 @@ -141,7 +141,8 @@ .FromTx(tx)); std::unique_ptr pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), 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); @@ -163,7 +164,8 @@ int64_t(5000000000LL - 1000 - 50000) * SATOSHI - feeToUse; TxId lowFeeTxId = tx.GetId(); m_node.mempool->addUnchecked(entry.Fee(feeToUse).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), 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); @@ -179,7 +181,8 @@ tx.vout[0].nValue -= 2 * SATOSHI; lowFeeTxId = tx.GetId(); m_node.mempool->addUnchecked(entry.Fee(feeToUse + 2 * SATOSHI).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[4]->GetId() == freeTxId); BOOST_CHECK(pblocktemplate->block.vtx[5]->GetId() == lowFeeTxId); @@ -203,7 +206,8 @@ TxId lowFeeTxId2 = tx.GetId(); m_node.mempool->addUnchecked( entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey); // Verify that this tx isn't selected. for (const auto &txn : pblocktemplate->block.vtx) { @@ -217,7 +221,8 @@ // 10k satoshi fee. tx.vout[0].nValue = (100000000 - 10000) * SATOSHI; m_node.mempool->addUnchecked(entry.Fee(10000 * SATOSHI).FromTx(tx)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[8]->GetId() == lowFeeTxId2); } @@ -233,7 +238,8 @@ << OP_CHECKSIG; std::unique_ptr pblocktemplate = - BlockAssembler(config, mempool).CreateNewBlock(scriptPubKey); + BlockAssembler(config, mempool) + .CreateNewBlock(::ChainstateActive(), scriptPubKey); CBlock *pblock = &pblocktemplate->block; @@ -277,7 +283,8 @@ // Simple block creation, nothing special yet: BOOST_CHECK(pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey)); // We can't make transactions until we have inputs. // Therefore, load 110 blocks :) @@ -322,7 +329,8 @@ // Just to make sure we can still make simple blocks. BOOST_CHECK(pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey)); const Amount BLOCKSUBSIDY = 50 * COIN; const Amount LOWFEE = CENT; @@ -355,13 +363,15 @@ } BOOST_CHECK(pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey)); m_node.mempool->clear(); // Orphan in mempool, template creation fails. m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx)); BOOST_CHECK_EXCEPTION( - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); m_node.mempool->clear(); @@ -382,7 +392,8 @@ m_node.mempool->addUnchecked( entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK(pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey)); m_node.mempool->clear(); // Coinbase in mempool, template creation fails. @@ -396,7 +407,8 @@ entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw bad-tx-coinbase BOOST_CHECK_EXCEPTION( - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-tx-coinbase")); m_node.mempool->clear(); @@ -413,7 +425,8 @@ m_node.mempool->addUnchecked( entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); BOOST_CHECK_EXCEPTION( - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); m_node.mempool->clear(); @@ -431,7 +444,8 @@ ::ChainActive().SetTip(next); } BOOST_CHECK(pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey)); // Extend to a 210000-long block chain. while (::ChainActive().Tip()->nHeight < 210000) { CBlockIndex *prev = ::ChainActive().Tip(); @@ -445,7 +459,8 @@ } BOOST_CHECK(pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey)); // Invalid p2sh txn in mempool, template creation fails tx.vin[0].prevout = COutPoint(txFirst[0]->GetId(), 0); @@ -465,7 +480,8 @@ entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); // Should throw blk-bad-inputs BOOST_CHECK_EXCEPTION( - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey), std::runtime_error, HasReason("blk-bad-inputs")); m_node.mempool->clear(); @@ -642,7 +658,8 @@ // Sequence locks fail. BOOST_CHECK(!TestSequenceLocks(CTransaction(tx), flags)); - pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey); BOOST_CHECK(pblocktemplate); // None of the of the absolute height/time locked tx should have made it @@ -663,7 +680,8 @@ SetMockTime(::ChainActive().Tip()->GetMedianTimePast() + 1); BOOST_CHECK(pblocktemplate = - AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey)); + AssemblerForTest(chainparams) + .CreateNewBlock(::ChainstateActive(), scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5UL); ::ChainActive().Tip()->nHeight--; diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp --- a/src/test/util/mining.cpp +++ b/src/test/util/mining.cpp @@ -44,10 +44,10 @@ std::shared_ptr PrepareBlock(const Config &config, const NodeContext &node, const CScript &coinbase_scriptPubKey) { - auto block = - std::make_shared(BlockAssembler{config, *Assert(node.mempool)} - .CreateNewBlock(coinbase_scriptPubKey) - ->block); + auto block = std::make_shared( + BlockAssembler{config, *Assert(node.mempool)} + .CreateNewBlock(::ChainstateActive(), coinbase_scriptPubKey) + ->block); LOCK(cs_main); block->nTime = ::ChainActive().Tip()->GetMedianTimePast() + 1; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -259,8 +259,9 @@ const std::vector &txns, const CScript &scriptPubKey) { const Config &config = GetConfig(); CTxMemPool empty_pool; - CBlock block = - BlockAssembler(config, empty_pool).CreateNewBlock(scriptPubKey)->block; + CBlock block = BlockAssembler(config, empty_pool) + .CreateNewBlock(::ChainstateActive(), scriptPubKey) + ->block; Assert(block.vtx.size() == 1); for (const CMutableTransaction &tx : 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 @@ -75,8 +75,8 @@ CScript pubKey; pubKey << i++ << OP_TRUE; - auto ptemplate = - BlockAssembler(config, *m_node.mempool).CreateNewBlock(pubKey); + auto ptemplate = BlockAssembler(config, *m_node.mempool) + .CreateNewBlock(::ChainstateActive(), pubKey); auto pblock = std::make_shared(ptemplate->block); pblock->hashPrevBlock = prev_hash; pblock->nTime = ++time;