test: drop scriptPubKeyIn arg from CreateNewBlock

This removes the temporary overload added in the previous commit.

Also drop unneeded custom coinbase output scripts.
This commit is contained in:
Sjors Provoost 2024-11-21 15:28:34 +01:00
parent ff41b9e296
commit 52fd1511a7
No known key found for this signature in database
GPG Key ID: 57FF9BDBCC301009
15 changed files with 85 additions and 62 deletions

View File

@ -20,19 +20,23 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
using node::BlockAssembler;
static void AssembleBlock(benchmark::Bench& bench) static void AssembleBlock(benchmark::Bench& bench)
{ {
const auto test_setup = MakeNoLogFileContext<const TestingSetup>(); const auto test_setup = MakeNoLogFileContext<const TestingSetup>();
CScriptWitness witness; CScriptWitness witness;
witness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE); witness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE);
BlockAssembler::Options options;
options.coinbase_output_script = P2WSH_OP_TRUE;
// Collect some loose transactions that spend the coinbases of our mined blocks // Collect some loose transactions that spend the coinbases of our mined blocks
constexpr size_t NUM_BLOCKS{200}; constexpr size_t NUM_BLOCKS{200};
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs; std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
for (size_t b{0}; b < NUM_BLOCKS; ++b) { for (size_t b{0}; b < NUM_BLOCKS; ++b) {
CMutableTransaction tx; CMutableTransaction tx;
tx.vin.emplace_back(MineBlock(test_setup->m_node, P2WSH_OP_TRUE)); tx.vin.emplace_back(MineBlock(test_setup->m_node, options));
tx.vin.back().scriptWitness = witness; tx.vin.back().scriptWitness = witness;
tx.vout.emplace_back(1337, P2WSH_OP_TRUE); tx.vout.emplace_back(1337, P2WSH_OP_TRUE);
if (NUM_BLOCKS - b >= COINBASE_MATURITY) if (NUM_BLOCKS - b >= COINBASE_MATURITY)
@ -48,7 +52,7 @@ static void AssembleBlock(benchmark::Bench& bench)
} }
bench.run([&] { bench.run([&] {
PrepareBlock(test_setup->m_node, P2WSH_OP_TRUE); PrepareBlock(test_setup->m_node, options);
}); });
} }
static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench) static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench)
@ -56,11 +60,12 @@ static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench)
FastRandomContext det_rand{true}; FastRandomContext det_rand{true};
auto testing_setup{MakeNoLogFileContext<TestChain100Setup>()}; auto testing_setup{MakeNoLogFileContext<TestChain100Setup>()};
testing_setup->PopulateMempool(det_rand, /*num_transactions=*/1000, /*submit=*/true); testing_setup->PopulateMempool(det_rand, /*num_transactions=*/1000, /*submit=*/true);
node::BlockAssembler::Options assembler_options; BlockAssembler::Options assembler_options;
assembler_options.test_block_validity = false; assembler_options.test_block_validity = false;
assembler_options.coinbase_output_script = P2WSH_OP_TRUE;
bench.run([&] { bench.run([&] {
PrepareBlock(testing_setup->m_node, P2WSH_OP_TRUE, assembler_options); PrepareBlock(testing_setup->m_node, assembler_options);
}); });
} }

View File

@ -172,19 +172,11 @@ public:
/** Construct a new block template */ /** Construct a new block template */
std::unique_ptr<CBlockTemplate> CreateNewBlock(); std::unique_ptr<CBlockTemplate> CreateNewBlock();
/** Temporary overload for tests */
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn)
{
m_options.coinbase_output_script = scriptPubKeyIn;
return CreateNewBlock();
};
inline static std::optional<int64_t> m_last_block_num_txs{}; inline static std::optional<int64_t> m_last_block_num_txs{};
inline static std::optional<int64_t> m_last_block_weight{}; inline static std::optional<int64_t> m_last_block_weight{};
private: private:
// TODO: make const again const Options m_options;
Options m_options;
// utility functions // utility functions
/** Clear the block's state and prepare for assembling a new block */ /** Clear the block's state and prepare for assembling a new block */

View File

@ -67,8 +67,9 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev,
const std::vector<CMutableTransaction>& txns, const std::vector<CMutableTransaction>& txns,
const CScript& scriptPubKey) const CScript& scriptPubKey)
{ {
BlockAssembler::Options options; BlockAssembler::Options options;
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock(scriptPubKey); options.coinbase_output_script = scriptPubKey;
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock();
CBlock& block = pblocktemplate->block; CBlock& block = pblocktemplate->block;
block.hashPrevBlock = prev->GetBlockHash(); block.hashPrevBlock = prev->GetBlockHash();
block.nTime = prev->nTime + 1; block.nTime = prev->nTime + 1;

View File

@ -174,15 +174,15 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
miner_options.blockMinFeeRate = target_feerate; miner_options.blockMinFeeRate = target_feerate;
miner_options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; miner_options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
miner_options.test_block_validity = false; miner_options.test_block_validity = false;
miner_options.coinbase_output_script = CScript() << OP_0;
node::BlockAssembler miner{g_setup->m_node.chainman->ActiveChainstate(), &pool, miner_options}; node::BlockAssembler miner{g_setup->m_node.chainman->ActiveChainstate(), &pool, miner_options};
node::MiniMiner mini_miner{pool, outpoints}; node::MiniMiner mini_miner{pool, outpoints};
assert(mini_miner.IsReadyToCalculate()); assert(mini_miner.IsReadyToCalculate());
CScript spk_placeholder = CScript() << OP_0;
// Use BlockAssembler as oracle. BlockAssembler and MiniMiner should select the same // Use BlockAssembler as oracle. BlockAssembler and MiniMiner should select the same
// transactions, stopping once packages do not meet target_feerate. // transactions, stopping once packages do not meet target_feerate.
const auto blocktemplate{miner.CreateNewBlock(spk_placeholder)}; const auto blocktemplate{miner.CreateNewBlock()};
mini_miner.BuildMockTemplate(target_feerate); mini_miner.BuildMockTemplate(target_feerate);
assert(!mini_miner.IsReadyToCalculate()); assert(!mini_miner.IsReadyToCalculate());
auto mock_template_txids = mini_miner.GetMockTemplateTxids(); auto mock_template_txids = mini_miner.GetMockTemplateTxids();

View File

@ -21,6 +21,7 @@
#include <validation.h> #include <validation.h>
#include <validationinterface.h> #include <validationinterface.h>
using node::BlockAssembler;
using node::NodeContext; using node::NodeContext;
namespace { namespace {
@ -42,8 +43,11 @@ void initialize_tx_pool()
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
g_setup = testing_setup.get(); g_setup = testing_setup.get();
BlockAssembler::Options options;
options.coinbase_output_script = P2WSH_EMPTY;
for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) { for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) {
COutPoint prevout{MineBlock(g_setup->m_node, P2WSH_EMPTY)}; COutPoint prevout{MineBlock(g_setup->m_node, options)};
if (i < COINBASE_MATURITY) { if (i < COINBASE_MATURITY) {
// Remember the txids to avoid expensive disk access later on // Remember the txids to avoid expensive disk access later on
g_outpoints_coinbase_init_mature.push_back(prevout); g_outpoints_coinbase_init_mature.push_back(prevout);

View File

@ -45,7 +45,7 @@ void initialize_process_message()
{.extra_args = {"-txreconciliation"}}); {.extra_args = {"-txreconciliation"}});
g_setup = testing_setup.get(); g_setup = testing_setup.get();
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) { for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
MineBlock(g_setup->m_node, CScript() << OP_TRUE); MineBlock(g_setup->m_node, {});
} }
g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }

View File

@ -35,7 +35,7 @@ void initialize_process_messages()
{.extra_args = {"-txreconciliation"}}); {.extra_args = {"-txreconciliation"}});
g_setup = testing_setup.get(); g_setup = testing_setup.get();
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) { for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
MineBlock(g_setup->m_node, CScript() << OP_TRUE); MineBlock(g_setup->m_node, {});
} }
g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue(); g_setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();
} }

View File

@ -45,8 +45,11 @@ void initialize_tx_pool()
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
g_setup = testing_setup.get(); g_setup = testing_setup.get();
BlockAssembler::Options options;
options.coinbase_output_script = P2WSH_OP_TRUE;
for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) { for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) {
COutPoint prevout{MineBlock(g_setup->m_node, P2WSH_OP_TRUE)}; COutPoint prevout{MineBlock(g_setup->m_node, options)};
// Remember the txids to avoid expensive disk access later on // Remember the txids to avoid expensive disk access later on
auto& outpoints = i < COINBASE_MATURITY ? auto& outpoints = i < COINBASE_MATURITY ?
g_outpoints_coinbase_init_mature : g_outpoints_coinbase_init_mature :
@ -98,7 +101,7 @@ void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, Cha
options.nBlockMaxWeight = fuzzed_data_provider.ConsumeIntegralInRange(0U, MAX_BLOCK_WEIGHT); options.nBlockMaxWeight = fuzzed_data_provider.ConsumeIntegralInRange(0U, MAX_BLOCK_WEIGHT);
options.blockMinFeeRate = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)}; options.blockMinFeeRate = CFeeRate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
auto assembler = BlockAssembler{chainstate, &tx_pool, options}; auto assembler = BlockAssembler{chainstate, &tx_pool, options};
auto block_template = assembler.CreateNewBlock(CScript{} << OP_TRUE); auto block_template = assembler.CreateNewBlock();
Assert(block_template->block.vtx.size() >= 1); Assert(block_template->block.vtx.size() >= 1);
} }
const auto info_all = tx_pool.infoAll(); const auto info_all = tx_pool.infoAll();

View File

@ -17,6 +17,8 @@
#include <util/chaintype.h> #include <util/chaintype.h>
#include <validation.h> #include <validation.h>
using node::BlockAssembler;
FUZZ_TARGET(utxo_total_supply) FUZZ_TARGET(utxo_total_supply)
{ {
/** The testing setup that creates a chainman only (no chainstate) */ /** The testing setup that creates a chainman only (no chainstate) */
@ -36,9 +38,11 @@ FUZZ_TARGET(utxo_total_supply)
LOCK(chainman.GetMutex()); LOCK(chainman.GetMutex());
return chainman.ActiveHeight(); return chainman.ActiveHeight();
}; };
BlockAssembler::Options options;
options.coinbase_output_script = CScript() << OP_FALSE;
const auto PrepareNextBlock = [&]() { const auto PrepareNextBlock = [&]() {
// Use OP_FALSE to avoid BIP30 check from hitting early // Use OP_FALSE to avoid BIP30 check from hitting early
auto block = PrepareBlock(node, CScript{} << OP_FALSE); auto block = PrepareBlock(node, options);
// Replace OP_FALSE with OP_TRUE // Replace OP_FALSE with OP_TRUE
{ {
CMutableTransaction tx{*block->vtx.back()}; CMutableTransaction tx{*block->vtx.back()};

View File

@ -54,7 +54,7 @@ struct MinerTestingSetup : public TestingSetup {
Assert(error.empty()); Assert(error.empty());
return *m_node.mempool; return *m_node.mempool;
} }
BlockAssembler AssemblerForTest(CTxMemPool& tx_mempool); BlockAssembler AssemblerForTest(CTxMemPool& tx_mempool, BlockAssembler::Options options);
}; };
} // namespace miner_tests } // namespace miner_tests
@ -62,10 +62,8 @@ BOOST_FIXTURE_TEST_SUITE(miner_tests, MinerTestingSetup)
static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
BlockAssembler MinerTestingSetup::AssemblerForTest(CTxMemPool& tx_mempool) BlockAssembler MinerTestingSetup::AssemblerForTest(CTxMemPool& tx_mempool, BlockAssembler::Options options)
{ {
BlockAssembler::Options options;
options.nBlockMaxWeight = MAX_BLOCK_WEIGHT; options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
options.blockMinFeeRate = blockMinFeeRate; options.blockMinFeeRate = blockMinFeeRate;
return BlockAssembler{m_node.chainman->ActiveChainstate(), &tx_mempool, options}; return BlockAssembler{m_node.chainman->ActiveChainstate(), &tx_mempool, options};
@ -137,7 +135,9 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
Txid hashHighFeeTx = tx.GetHash(); Txid hashHighFeeTx = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U); BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 4U);
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx); BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx); BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
@ -158,7 +158,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse; tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
Txid hashLowFeeTx = tx.GetHash(); Txid hashLowFeeTx = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(feeToUse).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(feeToUse).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
// Verify that the free tx and the low fee tx didn't get selected // Verify that the free tx and the low fee tx didn't get selected
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) { for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx); BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
@ -172,7 +172,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
hashLowFeeTx = tx.GetHash(); hashLowFeeTx = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(feeToUse + 2).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(feeToUse + 2).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U); BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx); BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx); BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
@ -194,7 +194,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse; tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
Txid hashLowFeeTx2 = tx.GetHash(); Txid hashLowFeeTx2 = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
// Verify that this tx isn't selected. // Verify that this tx isn't selected.
for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) { for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
@ -207,7 +207,7 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const
tx.vin[0].prevout.n = 1; tx.vin[0].prevout.n = 1;
tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
AddToMempool(tx_mempool, entry.Fee(10000).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(10000).FromTx(tx));
pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9U); BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 9U);
BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2); BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
} }
@ -225,12 +225,15 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
const CAmount HIGHFEE = COIN; const CAmount HIGHFEE = COIN;
const CAmount HIGHERFEE = 4 * COIN; const CAmount HIGHERFEE = 4 * COIN;
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
{ {
CTxMemPool& tx_mempool{MakeMempool()}; CTxMemPool& tx_mempool{MakeMempool()};
LOCK(tx_mempool.cs); LOCK(tx_mempool.cs);
// Just to make sure we can still make simple blocks // Just to make sure we can still make simple blocks
auto pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); auto pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_CHECK(pblocktemplate); BOOST_CHECK(pblocktemplate);
// block sigops > limit: 1000 CHECKMULTISIG + 1 // block sigops > limit: 1000 CHECKMULTISIG + 1
@ -250,7 +253,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vin[0].prevout.hash = hash; tx.vin[0].prevout.hash = hash;
} }
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops")); BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-blk-sigops"));
} }
{ {
@ -267,7 +270,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
tx.vin[0].prevout.hash = hash; tx.vin[0].prevout.hash = hash;
} }
BOOST_CHECK(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey)); BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
} }
{ {
@ -291,7 +294,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
tx.vin[0].prevout.hash = hash; tx.vin[0].prevout.hash = hash;
} }
BOOST_CHECK(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey)); BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
} }
{ {
@ -301,7 +304,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
// orphan in tx_mempool, template creation fails // orphan in tx_mempool, template creation fails
hash = tx.GetHash(); hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
} }
{ {
@ -322,7 +325,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vout[0].nValue = tx.vout[0].nValue + BLOCKSUBSIDY - HIGHERFEE; // First txn output + fresh coinbase - new txn fee tx.vout[0].nValue = tx.vout[0].nValue + BLOCKSUBSIDY - HIGHERFEE; // First txn output + fresh coinbase - new txn fee
hash = tx.GetHash(); hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(HIGHERFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(HIGHERFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey)); BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
} }
{ {
@ -338,7 +341,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
// give it a fee so it'll get mined // give it a fee so it'll get mined
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
// Should throw bad-cb-multiple // Should throw bad-cb-multiple
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple")); BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-cb-multiple"));
} }
{ {
@ -355,7 +358,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vout[0].scriptPubKey = CScript() << OP_2; tx.vout[0].scriptPubKey = CScript() << OP_2;
hash = tx.GetHash(); hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent")); BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
} }
{ {
@ -375,7 +378,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
next->BuildSkip(); next->BuildSkip();
m_node.chainman->ActiveChain().SetTip(*next); m_node.chainman->ActiveChain().SetTip(*next);
} }
BOOST_CHECK(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey)); BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
// Extend to a 210000-long block chain. // Extend to a 210000-long block chain.
while (m_node.chainman->ActiveChain().Tip()->nHeight < 210000) { while (m_node.chainman->ActiveChain().Tip()->nHeight < 210000) {
CBlockIndex* prev = m_node.chainman->ActiveChain().Tip(); CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();
@ -387,7 +390,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
next->BuildSkip(); next->BuildSkip();
m_node.chainman->ActiveChain().SetTip(*next); m_node.chainman->ActiveChain().SetTip(*next);
} }
BOOST_CHECK(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey)); BOOST_CHECK(AssemblerForTest(tx_mempool, options).CreateNewBlock());
// invalid p2sh txn in tx_mempool, template creation fails // invalid p2sh txn in tx_mempool, template creation fails
tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vin[0].prevout.hash = txFirst[0]->GetHash();
@ -403,7 +406,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vout[0].nValue -= LOWFEE; tx.vout[0].nValue -= LOWFEE;
hash = tx.GetHash(); hash = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));
BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("mandatory-script-verify-flag-failed")); BOOST_CHECK_EXCEPTION(AssemblerForTest(tx_mempool, options).CreateNewBlock(), std::runtime_error, HasReason("mandatory-script-verify-flag-failed"));
// Delete the dummy blocks again. // Delete the dummy blocks again.
while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) { while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
@ -505,7 +508,7 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1; tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail
auto pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); auto pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_CHECK(pblocktemplate); BOOST_CHECK(pblocktemplate);
// None of the of the absolute height/time locked tx should have made // None of the of the absolute height/time locked tx should have made
@ -521,12 +524,15 @@ void MinerTestingSetup::TestBasicMining(const CScript& scriptPubKey, const std::
m_node.chainman->ActiveChain().Tip()->nHeight++; m_node.chainman->ActiveChain().Tip()->nHeight++;
SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1); SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
BOOST_CHECK(pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey)); BOOST_CHECK(pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock());
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
} }
void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)
{ {
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
CTxMemPool& tx_mempool{MakeMempool()}; CTxMemPool& tx_mempool{MakeMempool()};
LOCK(tx_mempool.cs); LOCK(tx_mempool.cs);
@ -588,7 +594,7 @@ void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const
Txid hashFreeGrandchild = tx.GetHash(); Txid hashFreeGrandchild = tx.GetHash();
AddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(false).FromTx(tx)); AddToMempool(tx_mempool, entry.Fee(0).SpendsCoinbase(false).FromTx(tx));
auto pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey); auto pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock();
BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U); BOOST_REQUIRE_EQUAL(pblocktemplate->block.vtx.size(), 6U);
BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashFreeParent); BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashFreeParent);
BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashFreePrioritisedTx); BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashFreePrioritisedTx);
@ -610,9 +616,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
CScript scriptPubKey = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex << OP_CHECKSIG; CScript scriptPubKey = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex << OP_CHECKSIG;
std::unique_ptr<CBlockTemplate> pblocktemplate; std::unique_ptr<CBlockTemplate> pblocktemplate;
BlockAssembler::Options options;
options.coinbase_output_script = scriptPubKey;
CTxMemPool& tx_mempool{*m_node.mempool}; CTxMemPool& tx_mempool{*m_node.mempool};
// Simple block creation, nothing special yet: // Simple block creation, nothing special yet:
BOOST_CHECK(pblocktemplate = AssemblerForTest(tx_mempool).CreateNewBlock(scriptPubKey)); BOOST_CHECK(pblocktemplate = AssemblerForTest(tx_mempool, options).CreateNewBlock());
// We can't make transactions until we have inputs // We can't make transactions until we have inputs
// Therefore, load 110 blocks :) // Therefore, load 110 blocks :)

View File

@ -20,8 +20,7 @@ static void mineBlock(const node::NodeContext& node, std::chrono::seconds block_
{ {
auto curr_time = GetTime<std::chrono::seconds>(); auto curr_time = GetTime<std::chrono::seconds>();
SetMockTime(block_time); // update time so the block is created with it SetMockTime(block_time); // update time so the block is created with it
node::BlockAssembler::Options options; CBlock block = node::BlockAssembler{node.chainman->ActiveChainstate(), nullptr, {}}.CreateNewBlock()->block;
CBlock block = node::BlockAssembler{node.chainman->ActiveChainstate(), nullptr, options}.CreateNewBlock(CScript() << OP_TRUE)->block;
while (!CheckProofOfWork(block.GetHash(), block.nBits, node.chainman->GetConsensus())) ++block.nNonce; while (!CheckProofOfWork(block.GetHash(), block.nBits, node.chainman->GetConsensus())) ++block.nNonce;
block.fChecked = true; // little speedup block.fChecked = true; // little speedup
SetMockTime(curr_time); // process block at current time SetMockTime(curr_time); // process block at current time

View File

@ -24,9 +24,10 @@ COutPoint generatetoaddress(const NodeContext& node, const std::string& address)
{ {
const auto dest = DecodeDestination(address); const auto dest = DecodeDestination(address);
assert(IsValidDestination(dest)); assert(IsValidDestination(dest));
const auto coinbase_script = GetScriptForDestination(dest); BlockAssembler::Options assembler_options;
assembler_options.coinbase_output_script = {GetScriptForDestination(dest)};
return MineBlock(node, coinbase_script); return MineBlock(node, assembler_options);
} }
std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params) std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params)
@ -60,9 +61,9 @@ std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const
return ret; return ret;
} }
COutPoint MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) COutPoint MineBlock(const NodeContext& node, const node::BlockAssembler::Options& assembler_options)
{ {
auto block = PrepareBlock(node, coinbase_scriptPubKey); auto block = PrepareBlock(node, assembler_options);
auto valid = MineBlock(node, block); auto valid = MineBlock(node, block);
assert(!valid.IsNull()); assert(!valid.IsNull());
return valid; return valid;
@ -108,12 +109,12 @@ COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block)
return {}; return {};
} }
std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey, std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node,
const BlockAssembler::Options& assembler_options) const BlockAssembler::Options& assembler_options)
{ {
auto block = std::make_shared<CBlock>( auto block = std::make_shared<CBlock>(
BlockAssembler{Assert(node.chainman)->ActiveChainstate(), Assert(node.mempool.get()), assembler_options} BlockAssembler{Assert(node.chainman)->ActiveChainstate(), Assert(node.mempool.get()), assembler_options}
.CreateNewBlock(coinbase_scriptPubKey) .CreateNewBlock()
->block); ->block);
LOCK(cs_main); LOCK(cs_main);
@ -125,6 +126,7 @@ std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coi
std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
{ {
BlockAssembler::Options assembler_options; BlockAssembler::Options assembler_options;
assembler_options.coinbase_output_script = coinbase_scriptPubKey;
ApplyArgsManOptions(*node.args, assembler_options); ApplyArgsManOptions(*node.args, assembler_options);
return PrepareBlock(node, coinbase_scriptPubKey, assembler_options); return PrepareBlock(node, assembler_options);
} }

View File

@ -23,7 +23,8 @@ struct NodeContext;
std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params); std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params);
/** Returns the generated coin */ /** Returns the generated coin */
COutPoint MineBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey); COutPoint MineBlock(const node::NodeContext&,
const node::BlockAssembler::Options& assembler_options);
/** /**
* Returns the generated coin (or Null if the block was invalid). * Returns the generated coin (or Null if the block was invalid).
@ -32,8 +33,8 @@ COutPoint MineBlock(const node::NodeContext&, const CScript& coinbase_scriptPubK
COutPoint MineBlock(const node::NodeContext&, std::shared_ptr<CBlock>& block); COutPoint MineBlock(const node::NodeContext&, std::shared_ptr<CBlock>& block);
/** Prepare a block to be mined */ /** Prepare a block to be mined */
std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey); std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext&);
std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext& node, const CScript& coinbase_scriptPubKey, std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext& node,
const node::BlockAssembler::Options& assembler_options); const node::BlockAssembler::Options& assembler_options);
/** RPC-like helper function, returns the generated coin */ /** RPC-like helper function, returns the generated coin */

View File

@ -377,7 +377,8 @@ CBlock TestChain100Setup::CreateBlock(
Chainstate& chainstate) Chainstate& chainstate)
{ {
BlockAssembler::Options options; BlockAssembler::Options options;
CBlock block = BlockAssembler{chainstate, nullptr, options}.CreateNewBlock(scriptPubKey)->block; options.coinbase_output_script = scriptPubKey;
CBlock block = BlockAssembler{chainstate, nullptr, options}.CreateNewBlock()->block;
Assert(block.vtx.size() == 1); Assert(block.vtx.size() == 1);
for (const CMutableTransaction& tx : txns) { for (const CMutableTransaction& tx : txns) {

View File

@ -66,7 +66,8 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash)
static uint64_t time = Params().GenesisBlock().nTime; static uint64_t time = Params().GenesisBlock().nTime;
BlockAssembler::Options options; BlockAssembler::Options options;
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock(CScript{} << i++ << OP_TRUE); options.coinbase_output_script = CScript{} << i++ << OP_TRUE;
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock();
auto pblock = std::make_shared<CBlock>(ptemplate->block); auto pblock = std::make_shared<CBlock>(ptemplate->block);
pblock->hashPrevBlock = prev_hash; pblock->hashPrevBlock = prev_hash;
pblock->nTime = ++time; pblock->nTime = ++time;
@ -331,7 +332,8 @@ BOOST_AUTO_TEST_CASE(witness_commitment_index)
CScript pubKey; CScript pubKey;
pubKey << 1 << OP_TRUE; pubKey << 1 << OP_TRUE;
BlockAssembler::Options options; BlockAssembler::Options options;
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock(pubKey); options.coinbase_output_script = pubKey;
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock();
CBlock pblock = ptemplate->block; CBlock pblock = ptemplate->block;
CTxOut witness; CTxOut witness;