From 2278f017afad4d2c570527b15df776ee64fc1ee2 Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Mon, 9 Feb 2026 15:44:27 -0500 Subject: [PATCH] ipc mining: remove deprecated methods (incompatible schema change) This change removes deprecated methods from the ipc mining interface. Warning: This is an intermediate, review-only commit. Binaries built from it should not be distributed or used to connect to other clients or servers. It makes incompatible changes to the `mining.capnp` schema without updating the `Init.makeMining` version, causing binaries to advertise support for a schema they do not actually implement. Mixed versions may therefore exchange garbage requests/responses instead of producing clear errors. The final commit in this series bumps the mining interface number to ensure mismatches are detected. git-bisect-skip: yes --- src/interfaces/mining.h | 22 ---------------------- src/ipc/capnp/mining.capnp | 13 +++++-------- src/node/interfaces.cpp | 15 --------------- src/node/miner.cpp | 2 +- src/node/miner.h | 1 - src/validation.cpp | 5 +---- src/validation.h | 2 +- test/functional/interface_ipc_mining.py | 18 +----------------- test/functional/test_framework/ipc_util.py | 10 +--------- 9 files changed, 10 insertions(+), 78 deletions(-) diff --git a/src/interfaces/mining.h b/src/interfaces/mining.h index 993f70bd7aa..42002284d11 100644 --- a/src/interfaces/mining.h +++ b/src/interfaces/mining.h @@ -42,31 +42,9 @@ public: // Sigop cost per transaction, not including coinbase transaction. virtual std::vector getTxSigops() = 0; - /** - * Return serialized dummy coinbase transaction. - * - * @note deprecated: use getCoinbaseTx() - */ - virtual CTransactionRef getCoinbaseRawTx() = 0; - /** Return fields needed to construct a coinbase transaction */ virtual node::CoinbaseTx getCoinbaseTx() = 0; - /** - * Return scriptPubKey with SegWit OP_RETURN. - * - * @note deprecated: use getCoinbaseTx() - */ - virtual std::vector getCoinbaseCommitment() = 0; - - /** - * Return which output in the dummy coinbase contains the SegWit OP_RETURN. - * - * @note deprecated. Scan outputs from getCoinbaseTx() outputs field for the - * SegWit marker. - */ - virtual int getWitnessCommitmentIndex() = 0; - /** * Compute merkle path to the coinbase transaction * diff --git a/src/ipc/capnp/mining.capnp b/src/ipc/capnp/mining.capnp index 1811716ff54..0727fcc0a50 100644 --- a/src/ipc/capnp/mining.capnp +++ b/src/ipc/capnp/mining.capnp @@ -32,14 +32,11 @@ interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") { getBlock @2 (context: Proxy.Context) -> (result: Data); getTxFees @3 (context: Proxy.Context) -> (result: List(Int64)); getTxSigops @4 (context: Proxy.Context) -> (result: List(Int64)); - getCoinbaseRawTx @5 (context: Proxy.Context) -> (result: Data); - getCoinbaseTx @12 (context: Proxy.Context) -> (result: CoinbaseTx); - getCoinbaseCommitment @6 (context: Proxy.Context) -> (result: Data); - getWitnessCommitmentIndex @7 (context: Proxy.Context) -> (result: Int32); - getCoinbaseMerklePath @8 (context: Proxy.Context) -> (result: List(Data)); - submitSolution @9 (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool); - waitNext @10 (context: Proxy.Context, options: BlockWaitOptions) -> (result: BlockTemplate); - interruptWait @11() -> (); + getCoinbaseTx @5 (context: Proxy.Context) -> (result: CoinbaseTx); + getCoinbaseMerklePath @6 (context: Proxy.Context) -> (result: List(Data)); + submitSolution @7 (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool); + waitNext @8 (context: Proxy.Context, options: BlockWaitOptions) -> (result: BlockTemplate); + interruptWait @9() -> (); } struct BlockCreateOptions $Proxy.wrap("node::BlockCreateOptions") { diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index af9388d4b9f..8f5406ab3c0 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -890,26 +890,11 @@ public: return m_block_template->vTxSigOpsCost; } - CTransactionRef getCoinbaseRawTx() override - { - return m_block_template->block.vtx[0]; - } - CoinbaseTx getCoinbaseTx() override { return m_block_template->m_coinbase_tx; } - std::vector getCoinbaseCommitment() override - { - return m_block_template->vchCoinbaseCommitment; - } - - int getWitnessCommitmentIndex() override - { - return GetWitnessCommitmentIndex(m_block_template->block); - } - std::vector getCoinbaseMerklePath() override { return TransactionMerklePath(m_block_template->block, 0); diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 7bdd8b690d7..fe26794528b 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -197,7 +197,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock() coinbase_tx.lock_time = coinbaseTx.nLockTime; pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx)); - pblocktemplate->vchCoinbaseCommitment = m_chainstate.m_chainman.GenerateCoinbaseCommitment(*pblock, pindexPrev); + m_chainstate.m_chainman.GenerateCoinbaseCommitment(*pblock, pindexPrev); const CTransactionRef& final_coinbase{pblock->vtx[0]}; if (final_coinbase->HasWitness()) { diff --git a/src/node/miner.h b/src/node/miner.h index 0c268f1826d..5a338dfb917 100644 --- a/src/node/miner.h +++ b/src/node/miner.h @@ -46,7 +46,6 @@ struct CBlockTemplate std::vector vTxFees; // Sigops per transaction, not including coinbase transaction (unlike CBlock::vtx). std::vector vTxSigOpsCost; - std::vector vchCoinbaseCommitment; /* A vector of package fee rates, ordered by the sequence in which * packages are selected for inclusion in the block template.*/ std::vector m_package_feerates; diff --git a/src/validation.cpp b/src/validation.cpp index c200c3d6cd8..b7a113ea4b9 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4040,9 +4040,8 @@ void ChainstateManager::UpdateUncommittedBlockStructures(CBlock& block, const CB } } -std::vector ChainstateManager::GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const +void ChainstateManager::GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const { - std::vector commitment; int commitpos = GetWitnessCommitmentIndex(block); std::vector ret(32, 0x00); if (commitpos == NO_WITNESS_COMMITMENT) { @@ -4058,13 +4057,11 @@ std::vector ChainstateManager::GenerateCoinbaseCommitment(CBlock& out.scriptPubKey[4] = 0xa9; out.scriptPubKey[5] = 0xed; memcpy(&out.scriptPubKey[6], witnessroot.begin(), 32); - commitment = std::vector(out.scriptPubKey.begin(), out.scriptPubKey.end()); CMutableTransaction tx(*block.vtx[0]); tx.vout.push_back(out); block.vtx[0] = MakeTransactionRef(std::move(tx)); } UpdateUncommittedBlockStructures(block, pindexPrev); - return commitment; } bool HasValidProofOfWork(std::span headers, const Consensus::Params& consensusParams) diff --git a/src/validation.h b/src/validation.h index 675d7061ab1..c1468836925 100644 --- a/src/validation.h +++ b/src/validation.h @@ -1310,7 +1310,7 @@ public: void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev) const; /** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */ - std::vector GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const; + void GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const; /** This is used by net_processing to report pre-synchronization progress of headers, as * headers are not yet fed to validation during that time, but validation is (for now) diff --git a/test/functional/interface_ipc_mining.py b/test/functional/interface_ipc_mining.py index a02727bb4c9..0a530827cd1 100755 --- a/test/functional/interface_ipc_mining.py +++ b/test/functional/interface_ipc_mining.py @@ -34,7 +34,6 @@ from test_framework.ipc_util import ( make_capnp_init_ctx, mining_get_block, mining_get_coinbase_tx, - mining_get_coinbase_raw_tx, mining_wait_next_template, wait_and_do, ) @@ -93,27 +92,12 @@ class IPCMiningTest(BitcoinTestFramework): coinbase_tx.vout[0].nValue = coinbase_res.blockRewardRemaining # Add SegWit OP_RETURN. This is currently always present even for # empty blocks, but this may change. - found_witness_op_return = False - # Compare SegWit OP_RETURN to getCoinbaseCommitment() - coinbase_commitment = (await template.getCoinbaseCommitment(ctx)).result for output_data in coinbase_res.requiredOutputs: output = CTxOut() output.deserialize(BytesIO(output_data)) coinbase_tx.vout.append(output) - if output.scriptPubKey == coinbase_commitment: - found_witness_op_return = True - - assert_equal(has_witness, found_witness_op_return) coinbase_tx.nLockTime = coinbase_res.lockTime - # Compare to dummy coinbase transaction provided by the deprecated - # getCoinbaseRawTx() - coinbase_legacy = await mining_get_coinbase_raw_tx(template, ctx) - assert_equal(coinbase_legacy.vout[0].nValue, coinbase_res.blockRewardRemaining) - # Swap dummy output for our own - coinbase_legacy.vout[0].scriptPubKey = coinbase_tx.vout[0].scriptPubKey - assert_equal(coinbase_tx.serialize().hex(), coinbase_legacy.serialize().hex()) - return coinbase_tx async def make_mining_ctx(self): @@ -276,7 +260,7 @@ class IPCMiningTest(BitcoinTestFramework): asyncio.run(capnp.run(async_routine())) def run_coinbase_and_submission_test(self): - """Test coinbase construction (getCoinbaseTx, getCoinbaseCommitment) and block submission (submitSolution).""" + """Test coinbase construction (getCoinbaseTx) and block submission (submitSolution).""" self.log.info("Running coinbase construction and submission test") async def async_routine(): diff --git a/test/functional/test_framework/ipc_util.py b/test/functional/test_framework/ipc_util.py index 1b1ad7a55aa..2ab74abad96 100644 --- a/test/functional/test_framework/ipc_util.py +++ b/test/functional/test_framework/ipc_util.py @@ -12,7 +12,7 @@ from pathlib import Path import shutil from typing import Optional -from test_framework.messages import CBlock, CTransaction +from test_framework.messages import CBlock # Test may be skipped and not have capnp installed try: @@ -129,14 +129,6 @@ async def mining_get_block(block_template, ctx): return block -async def mining_get_coinbase_raw_tx(block_template, ctx): - assert block_template is not None - coinbase_data = BytesIO((await block_template.getCoinbaseRawTx(ctx)).result) - tx = CTransaction() - tx.deserialize(coinbase_data) - return tx - - async def mining_get_coinbase_tx(block_template, ctx) -> CoinbaseTxData: assert block_template is not None # Note: the template_capnp struct will be garbage-collected when this