From 1ea456986502f9fe5cdc1aa35359f34b745ee3e4 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 9 May 2024 21:39:01 +0000 Subject: [PATCH 1/9] RPC/Mining: Abstract TemplateToJSON out of getblocktemplate --- src/rpc/mining.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index b1565f5df5..f16a39eae5 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -567,6 +567,8 @@ static std::string gbt_vb_name(const Consensus::DeploymentPos pos) { return s; } +static UniValue TemplateToJSON(const Consensus::Params&, const ChainstateManager&, const CBlockTemplate*, const CBlockIndex*, const std::set& setClientRules, unsigned int nTransactionsUpdatedLast); + static RPCHelpMan getblocktemplate() { return RPCHelpMan{"getblocktemplate", @@ -830,6 +832,14 @@ static RPCHelpMan getblocktemplate() UpdateTime(pblock, consensusParams, pindexPrev); pblock->nNonce = 0; + return TemplateToJSON(consensusParams, chainman, &*pblocktemplate, pindexPrev, setClientRules, nTransactionsUpdatedLast); +}, + }; +} + +static UniValue TemplateToJSON(const Consensus::Params& consensusParams, const ChainstateManager& chainman, const CBlockTemplate* const pblocktemplate, const CBlockIndex* const pindexPrev, const std::set& setClientRules, const unsigned int nTransactionsUpdatedLast) { + const CBlock* const pblock = &pblocktemplate->block; + // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT); @@ -894,6 +904,7 @@ static RPCHelpMan getblocktemplate() aRules.push_back("!signet"); } + auto block_version = pblock->nVersion; UniValue vbavailable(UniValue::VOBJ); for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { Consensus::DeploymentPos pos = Consensus::DeploymentPos(j); @@ -905,7 +916,7 @@ static RPCHelpMan getblocktemplate() break; case ThresholdState::LOCKED_IN: // Ensure bit is set in block version - pblock->nVersion |= chainman.m_versionbitscache.Mask(consensusParams, pos); + block_version |= chainman.m_versionbitscache.Mask(consensusParams, pos); [[fallthrough]]; case ThresholdState::STARTED: { @@ -914,7 +925,7 @@ static RPCHelpMan getblocktemplate() if (setClientRules.find(vbinfo.name) == setClientRules.end()) { if (!vbinfo.gbt_force) { // If the client doesn't support this, don't indicate it in the [default] version - pblock->nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos); + block_version &= ~chainman.m_versionbitscache.Mask(consensusParams, pos); } } break; @@ -934,7 +945,7 @@ static RPCHelpMan getblocktemplate() } } } - result.pushKV("version", pblock->nVersion); + result.pushKV("version", block_version); result.pushKV("rules", std::move(aRules)); result.pushKV("vbavailable", std::move(vbavailable)); result.pushKV("vbrequired", int(0)); @@ -943,7 +954,7 @@ static RPCHelpMan getblocktemplate() result.pushKV("transactions", std::move(transactions)); result.pushKV("coinbaseaux", std::move(aux)); result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue); - result.pushKV("longpollid", tip.GetHex() + ToString(nTransactionsUpdatedLast)); + result.pushKV("longpollid", pindexPrev->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast)); result.pushKV("target", hashTarget.GetHex()); result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1); result.pushKV("mutable", std::move(aMutable)); @@ -974,8 +985,6 @@ static RPCHelpMan getblocktemplate() } return result; -}, - }; } class submitblock_StateCatcher final : public CValidationInterface From a4af3258af988b1f95ce1f84babf346b48941b62 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 22 Feb 2025 20:31:54 +0000 Subject: [PATCH 2/9] Replace node::BlockAssembler::Options with an alias to node::BlockCreateOptions --- src/node/miner.cpp | 2 +- src/node/miner.h | 11 +---------- src/node/types.h | 13 +++++++++++++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 18c2afb9a6..809575a51b 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -65,7 +65,7 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman) block.hashMerkleRoot = BlockMerkleRoot(block); } -static BlockAssembler::Options ClampOptions(BlockAssembler::Options options) +static BlockCreateOptions ClampOptions(BlockCreateOptions options) { Assert(options.coinbase_max_additional_size <= MAX_BLOCK_SERIALIZED_SIZE - 1000); Assert(options.coinbase_max_additional_weight <= DEFAULT_BLOCK_MAX_WEIGHT); diff --git a/src/node/miner.h b/src/node/miner.h index fca84ff742..e376d9b720 100644 --- a/src/node/miner.h +++ b/src/node/miner.h @@ -31,7 +31,6 @@ class ChainstateManager; namespace Consensus { struct Params; }; namespace node { -static const bool DEFAULT_PRINT_MODIFIED_FEE = false; struct CBlockTemplate { @@ -161,15 +160,7 @@ private: Chainstate& m_chainstate; public: - struct Options : BlockCreateOptions { - // Configuration parameters for the block size - size_t nBlockMaxWeight{DEFAULT_BLOCK_MAX_WEIGHT}; - size_t nBlockMaxSize{DEFAULT_BLOCK_MAX_SIZE}; - CFeeRate blockMinFeeRate{DEFAULT_BLOCK_MIN_TX_FEE}; - // Whether to call TestBlockValidity() at the end of CreateNewBlock(). - bool test_block_validity{true}; - bool print_modified_fee{DEFAULT_PRINT_MODIFIED_FEE}; - }; + using Options = BlockCreateOptions; explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options); diff --git a/src/node/types.h b/src/node/types.h index 5230d38388..4fe2400f52 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -13,6 +13,9 @@ #ifndef BITCOIN_NODE_TYPES_H #define BITCOIN_NODE_TYPES_H +#include +#include + #include namespace node { @@ -27,6 +30,8 @@ enum class TransactionError { INVALID_PACKAGE, }; +static const bool DEFAULT_PRINT_MODIFIED_FEE = false; + struct BlockCreateOptions { /** * Set false to omit mempool transactions @@ -49,6 +54,14 @@ struct BlockCreateOptions { * transaction outputs. */ size_t coinbase_output_max_additional_sigops{400}; + + // Configuration parameters for the block size + size_t nBlockMaxWeight{DEFAULT_BLOCK_MAX_WEIGHT}; + size_t nBlockMaxSize{DEFAULT_BLOCK_MAX_SIZE}; + CFeeRate blockMinFeeRate{DEFAULT_BLOCK_MIN_TX_FEE}; + // Whether to call TestBlockValidity() at the end of CreateNewBlock(). + bool test_block_validity{true}; + bool print_modified_fee{DEFAULT_PRINT_MODIFIED_FEE}; }; } // namespace node From 275a540ea8d55cacff9c02d4e12f6d1b23cabef6 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 10 May 2024 14:53:38 +0000 Subject: [PATCH 3/9] node/miner: Export BlockCreateOptions::Clamped --- src/node/miner.cpp | 5 +++-- src/node/types.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 809575a51b..396b083e62 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -65,8 +65,9 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman) block.hashMerkleRoot = BlockMerkleRoot(block); } -static BlockCreateOptions ClampOptions(BlockCreateOptions options) +BlockCreateOptions BlockCreateOptions::Clamped() const { + BlockAssembler::Options options = *this; Assert(options.coinbase_max_additional_size <= MAX_BLOCK_SERIALIZED_SIZE - 1000); Assert(options.coinbase_max_additional_weight <= DEFAULT_BLOCK_MAX_WEIGHT); Assert(options.coinbase_output_max_additional_sigops <= MAX_BLOCK_SIGOPS_COST); @@ -82,7 +83,7 @@ BlockAssembler::BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool : chainparams{chainstate.m_chainman.GetParams()}, m_mempool{options.use_mempool ? mempool : nullptr}, m_chainstate{chainstate}, - m_options{ClampOptions(options)} + m_options{options.Clamped()} { // Whether we need to account for byte usage (in addition to weight usage) fNeedSizeAccounting = (options.nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE - 1000); diff --git a/src/node/types.h b/src/node/types.h index 4fe2400f52..1c4f871e12 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -62,6 +62,8 @@ struct BlockCreateOptions { // Whether to call TestBlockValidity() at the end of CreateNewBlock(). bool test_block_validity{true}; bool print_modified_fee{DEFAULT_PRINT_MODIFIED_FEE}; + + BlockCreateOptions Clamped() const; }; } // namespace node From 23fd2eb9b1f35e19538c94046773fc1c80d0648a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 30 Jan 2025 19:41:05 +0000 Subject: [PATCH 4/9] interfaces/mining: Add createNewBlock2 that does not override or lose options --- src/interfaces/mining.h | 3 ++- src/node/interfaces.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/interfaces/mining.h b/src/interfaces/mining.h index cebe97edb7..9d98a3919e 100644 --- a/src/interfaces/mining.h +++ b/src/interfaces/mining.h @@ -40,13 +40,14 @@ public: virtual std::optional getTipHash() = 0; /** - * Construct a new block template + * Construct a new block template. For the createNewBlock variant, subclass options (if any) are silently lost and overridden by any config args. For createNewBlock2, the options are assumed to be complete. * * @param[in] script_pub_key the coinbase output * @param[in] options options for creating the block * @returns a block template */ virtual std::unique_ptr createNewBlock(const CScript& script_pub_key, const node::BlockCreateOptions& options={}) = 0; + virtual std::unique_ptr createNewBlock2(const CScript& script_pub_key, const node::BlockCreateOptions& assemble_options) = 0; /** * Processes new block. A valid new block is automatically relayed to peers. diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 54b986c926..b5dca8c61e 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -913,6 +913,11 @@ public: { BlockAssembler::Options assemble_options{options}; ApplyArgsManOptions(*Assert(m_node.args), assemble_options); + return createNewBlock2(script_pub_key, assemble_options); + } + + std::unique_ptr createNewBlock2(const CScript& script_pub_key, const BlockCreateOptions& assemble_options) override + { return BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(script_pub_key); } From a6ed9b19e88bd38376b9e089c9c03a01f9340727 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 10 May 2024 15:50:02 +0000 Subject: [PATCH 5/9] RPC/Mining: Support overriding BlockAssembler options in RPC params --- src/node/types.h | 2 ++ src/rpc/mining.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/node/types.h b/src/node/types.h index 1c4f871e12..059aa045bf 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -64,6 +64,8 @@ struct BlockCreateOptions { bool print_modified_fee{DEFAULT_PRINT_MODIFIED_FEE}; BlockCreateOptions Clamped() const; + + friend bool operator==(const BlockCreateOptions& a, const BlockCreateOptions& b) noexcept = default; }; } // namespace node diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index f16a39eae5..3da5dba3bc 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -34,6 +34,7 @@ #include