Skip to content

Commit cd3d9fa

Browse files
committed
Merge bitcoin/bitcoin#31318: Drop script_pub_key arg from createNewBlock
52fd151 test: drop scriptPubKeyIn arg from CreateNewBlock (Sjors Provoost) ff41b9e Drop script_pub_key arg from createNewBlock (Sjors Provoost) 7ab733e rpc: rename coinbase_script to coinbase_output_script (Sjors Provoost) Pull request description: Providing a script for the coinbase transaction is only done in test code and for (unoptimized) CPU solo mining. Production miners use the `getblocktemplate` RPC which omits the coinbase transaction entirely from its block template, leaving it to external (pool) software to construct it. This commit removes the `script_pub_key argument` from `createNewBlock()` in the Mining interface. A coinbase script can still be passed via `BlockCreateOptions` instead. Tests are modified to do so. ACKs for top commit: ryanofsky: Code review ACK 52fd151. No change since last review other than rebase TheCharlatan: Re-ACK 52fd151 vasild: ACK 52fd151 Tree-SHA512: c4b3a53774d9a5dc90950e77f47a64dbb68f971baffbb9a0d8f59332ef8e52d0c039130c925bde73135b3d0e79e65d91d1df30dc4cff13f32d8a72e5c56669d8
2 parents 785486a + 52fd151 commit cd3d9fa

21 files changed

+123
-77
lines changed

src/bench/block_assemble.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@
2020
#include <memory>
2121
#include <vector>
2222

23+
using node::BlockAssembler;
24+
2325
static void AssembleBlock(benchmark::Bench& bench)
2426
{
2527
const auto test_setup = MakeNoLogFileContext<const TestingSetup>();
2628

2729
CScriptWitness witness;
2830
witness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE);
31+
BlockAssembler::Options options;
32+
options.coinbase_output_script = P2WSH_OP_TRUE;
2933

3034
// Collect some loose transactions that spend the coinbases of our mined blocks
3135
constexpr size_t NUM_BLOCKS{200};
3236
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
3337
for (size_t b{0}; b < NUM_BLOCKS; ++b) {
3438
CMutableTransaction tx;
35-
tx.vin.emplace_back(MineBlock(test_setup->m_node, P2WSH_OP_TRUE));
39+
tx.vin.emplace_back(MineBlock(test_setup->m_node, options));
3640
tx.vin.back().scriptWitness = witness;
3741
tx.vout.emplace_back(1337, P2WSH_OP_TRUE);
3842
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
@@ -48,19 +52,20 @@ static void AssembleBlock(benchmark::Bench& bench)
4852
}
4953

5054
bench.run([&] {
51-
PrepareBlock(test_setup->m_node, P2WSH_OP_TRUE);
55+
PrepareBlock(test_setup->m_node, options);
5256
});
5357
}
5458
static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench)
5559
{
5660
FastRandomContext det_rand{true};
5761
auto testing_setup{MakeNoLogFileContext<TestChain100Setup>()};
5862
testing_setup->PopulateMempool(det_rand, /*num_transactions=*/1000, /*submit=*/true);
59-
node::BlockAssembler::Options assembler_options;
63+
BlockAssembler::Options assembler_options;
6064
assembler_options.test_block_validity = false;
65+
assembler_options.coinbase_output_script = P2WSH_OP_TRUE;
6166

6267
bench.run([&] {
63-
PrepareBlock(testing_setup->m_node, P2WSH_OP_TRUE, assembler_options);
68+
PrepareBlock(testing_setup->m_node, assembler_options);
6469
});
6570
}
6671

src/interfaces/mining.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,10 @@ class Mining
8888
/**
8989
* Construct a new block template
9090
*
91-
* @param[in] script_pub_key the coinbase output
9291
* @param[in] options options for creating the block
9392
* @returns a block template
9493
*/
95-
virtual std::unique_ptr<BlockTemplate> createNewBlock(const CScript& script_pub_key, const node::BlockCreateOptions& options = {}) = 0;
94+
virtual std::unique_ptr<BlockTemplate> createNewBlock(const node::BlockCreateOptions& options = {}) = 0;
9695

9796
/**
9897
* Processes new block. A valid new block is automatically relayed to peers.

src/ipc/capnp/mining.capnp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface Mining $Proxy.wrap("interfaces::Mining") {
1717
isInitialBlockDownload @1 (context :Proxy.Context) -> (result: Bool);
1818
getTip @2 (context :Proxy.Context) -> (result: Common.BlockRef, hasResult: Bool);
1919
waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64) -> (result: Common.BlockRef);
20-
createNewBlock @4 (scriptPubKey: Data, options: BlockCreateOptions) -> (result: BlockTemplate);
20+
createNewBlock @4 (options: BlockCreateOptions) -> (result: BlockTemplate);
2121
processNewBlock @5 (context :Proxy.Context, block: Data) -> (newBlock: Bool, result: Bool);
2222
getTransactionsUpdated @6 (context :Proxy.Context) -> (result: UInt32);
2323
testBlockValidity @7 (context :Proxy.Context, block: Data, checkMerkleRoot: Bool) -> (state: BlockValidationState, result: Bool);

src/node/interfaces.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,11 +1004,11 @@ class MinerImpl : public Mining
10041004
return TestBlockValidity(state, chainman().GetParams(), chainman().ActiveChainstate(), block, tip, /*fCheckPOW=*/false, check_merkle_root);
10051005
}
10061006

1007-
std::unique_ptr<BlockTemplate> createNewBlock(const CScript& script_pub_key, const BlockCreateOptions& options) override
1007+
std::unique_ptr<BlockTemplate> createNewBlock(const BlockCreateOptions& options) override
10081008
{
10091009
BlockAssembler::Options assemble_options{options};
10101010
ApplyArgsManOptions(*Assert(m_node.args), assemble_options);
1011-
return std::make_unique<BlockTemplateImpl>(BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(script_pub_key), m_node);
1011+
return std::make_unique<BlockTemplateImpl>(BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(), m_node);
10121012
}
10131013

10141014
NodeContext* context() override { return &m_node; }

src/node/miner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ void BlockAssembler::resetBlock()
106106
nFees = 0;
107107
}
108108

109-
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
109+
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock()
110110
{
111111
const auto time_start{SteadyClock::now()};
112112

@@ -151,7 +151,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
151151
coinbaseTx.vin.resize(1);
152152
coinbaseTx.vin[0].prevout.SetNull();
153153
coinbaseTx.vout.resize(1);
154-
coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn;
154+
coinbaseTx.vout[0].scriptPubKey = m_options.coinbase_output_script;
155155
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
156156
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
157157
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));

src/node/miner.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ class BlockAssembler
169169

170170
explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options);
171171

172-
/** Construct a new block template with coinbase to scriptPubKeyIn */
173-
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
172+
/** Construct a new block template */
173+
std::unique_ptr<CBlockTemplate> CreateNewBlock();
174174

175175
inline static std::optional<int64_t> m_last_block_num_txs{};
176176
inline static std::optional<int64_t> m_last_block_weight{};

src/node/types.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
//! @file node/types.h is a home for public enum and struct type definitions
6-
//! that are used by internally by node code, but also used externally by wallet
7-
//! or GUI code.
6+
//! that are used by internally by node code, but also used externally by wallet,
7+
//! mining or GUI code.
88
//!
99
//! This file is intended to define only simple types that do not have external
1010
//! dependencies. More complicated types should be defined in dedicated header
@@ -14,6 +14,7 @@
1414
#define BITCOIN_NODE_TYPES_H
1515

1616
#include <cstddef>
17+
#include <script/script.h>
1718

1819
namespace node {
1920
enum class TransactionError {
@@ -43,6 +44,22 @@ struct BlockCreateOptions {
4344
* transaction outputs.
4445
*/
4546
size_t coinbase_output_max_additional_sigops{400};
47+
/**
48+
* Script to put in the coinbase transaction. The default is an
49+
* anyone-can-spend dummy.
50+
*
51+
* Should only be used for tests, when the default doesn't suffice.
52+
*
53+
* Note that higher level code like the getblocktemplate RPC may omit the
54+
* coinbase transaction entirely. It's instead constructed by pool software
55+
* using fields like coinbasevalue, coinbaseaux and default_witness_commitment.
56+
* This software typically also controls the payout outputs, even for solo
57+
* mining.
58+
*
59+
* The size and sigops are not checked against
60+
* coinbase_max_additional_weight and coinbase_output_max_additional_sigops.
61+
*/
62+
CScript coinbase_output_script{CScript() << OP_TRUE};
4663
};
4764
} // namespace node
4865

src/rpc/mining.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ static bool GenerateBlock(ChainstateManager& chainman, Mining& miner, CBlock&& b
158158
return true;
159159
}
160160

161-
static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
161+
static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const CScript& coinbase_output_script, int nGenerate, uint64_t nMaxTries)
162162
{
163163
UniValue blockHashes(UniValue::VARR);
164164
while (nGenerate > 0 && !chainman.m_interrupt) {
165-
std::unique_ptr<BlockTemplate> block_template(miner.createNewBlock(coinbase_script));
165+
std::unique_ptr<BlockTemplate> block_template(miner.createNewBlock({ .coinbase_output_script = coinbase_output_script }));
166166
CHECK_NONFATAL(block_template);
167167

168168
std::shared_ptr<const CBlock> block_out;
@@ -236,17 +236,17 @@ static RPCHelpMan generatetodescriptor()
236236
const auto num_blocks{self.Arg<int>("num_blocks")};
237237
const auto max_tries{self.Arg<uint64_t>("maxtries")};
238238

239-
CScript coinbase_script;
239+
CScript coinbase_output_script;
240240
std::string error;
241-
if (!getScriptFromDescriptor(self.Arg<std::string>("descriptor"), coinbase_script, error)) {
241+
if (!getScriptFromDescriptor(self.Arg<std::string>("descriptor"), coinbase_output_script, error)) {
242242
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
243243
}
244244

245245
NodeContext& node = EnsureAnyNodeContext(request.context);
246246
Mining& miner = EnsureMining(node);
247247
ChainstateManager& chainman = EnsureChainman(node);
248248

249-
return generateBlocks(chainman, miner, coinbase_script, num_blocks, max_tries);
249+
return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
250250
},
251251
};
252252
}
@@ -292,9 +292,9 @@ static RPCHelpMan generatetoaddress()
292292
Mining& miner = EnsureMining(node);
293293
ChainstateManager& chainman = EnsureChainman(node);
294294

295-
CScript coinbase_script = GetScriptForDestination(destination);
295+
CScript coinbase_output_script = GetScriptForDestination(destination);
296296

297-
return generateBlocks(chainman, miner, coinbase_script, num_blocks, max_tries);
297+
return generateBlocks(chainman, miner, coinbase_output_script, num_blocks, max_tries);
298298
},
299299
};
300300
}
@@ -328,16 +328,16 @@ static RPCHelpMan generateblock()
328328
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
329329
{
330330
const auto address_or_descriptor = request.params[0].get_str();
331-
CScript coinbase_script;
331+
CScript coinbase_output_script;
332332
std::string error;
333333

334-
if (!getScriptFromDescriptor(address_or_descriptor, coinbase_script, error)) {
334+
if (!getScriptFromDescriptor(address_or_descriptor, coinbase_output_script, error)) {
335335
const auto destination = DecodeDestination(address_or_descriptor);
336336
if (!IsValidDestination(destination)) {
337337
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address or descriptor");
338338
}
339339

340-
coinbase_script = GetScriptForDestination(destination);
340+
coinbase_output_script = GetScriptForDestination(destination);
341341
}
342342

343343
NodeContext& node = EnsureAnyNodeContext(request.context);
@@ -371,7 +371,7 @@ static RPCHelpMan generateblock()
371371

372372
ChainstateManager& chainman = EnsureChainman(node);
373373
{
374-
std::unique_ptr<BlockTemplate> block_template{miner.createNewBlock(coinbase_script, {.use_mempool = false})};
374+
std::unique_ptr<BlockTemplate> block_template{miner.createNewBlock({.use_mempool = false, .coinbase_output_script = coinbase_output_script})};
375375
CHECK_NONFATAL(block_template);
376376

377377
block = block_template->getBlock();
@@ -814,8 +814,7 @@ static RPCHelpMan getblocktemplate()
814814
time_start = GetTime();
815815

816816
// Create new block
817-
CScript scriptDummy = CScript() << OP_TRUE;
818-
block_template = miner.createNewBlock(scriptDummy);
817+
block_template = miner.createNewBlock();
819818
CHECK_NONFATAL(block_template);
820819

821820

src/test/blockfilter_index_tests.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev,
6767
const std::vector<CMutableTransaction>& txns,
6868
const CScript& scriptPubKey)
6969
{
70-
BlockAssembler::Options options;
71-
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock(scriptPubKey);
70+
BlockAssembler::Options options;
71+
options.coinbase_output_script = scriptPubKey;
72+
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock();
7273
CBlock& block = pblocktemplate->block;
7374
block.hashPrevBlock = prev->GetBlockHash();
7475
block.nTime = prev->nTime + 1;

src/test/fuzz/mini_miner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,15 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
174174
miner_options.blockMinFeeRate = target_feerate;
175175
miner_options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
176176
miner_options.test_block_validity = false;
177+
miner_options.coinbase_output_script = CScript() << OP_0;
177178

178179
node::BlockAssembler miner{g_setup->m_node.chainman->ActiveChainstate(), &pool, miner_options};
179180
node::MiniMiner mini_miner{pool, outpoints};
180181
assert(mini_miner.IsReadyToCalculate());
181182

182-
CScript spk_placeholder = CScript() << OP_0;
183183
// Use BlockAssembler as oracle. BlockAssembler and MiniMiner should select the same
184184
// transactions, stopping once packages do not meet target_feerate.
185-
const auto blocktemplate{miner.CreateNewBlock(spk_placeholder)};
185+
const auto blocktemplate{miner.CreateNewBlock()};
186186
mini_miner.BuildMockTemplate(target_feerate);
187187
assert(!mini_miner.IsReadyToCalculate());
188188
auto mock_template_txids = mini_miner.GetMockTemplateTxids();

0 commit comments

Comments
 (0)