tests: Add witness commitment if we have a witness transaction in FullBlockTest.update_block()
What changed, and why it matters
This commit only changes Bitcoin Core's own test code. It makes the test framework correctly add a witness commitment to test blocks when they contain a segwit transaction, and adds a new test case for transactions that have unnecessary witness data. There is no change to the actual Bitcoin network code that users run, so this does not create a security vulnerability in Bitcoin Core itself.
No action required; this is a test-only improvement. Reviewers may verify that the new ExtraWitness test case aligns with current consensus rules for witness handling.
Security signals we found
Adds a test for witness-provided-for-non-witness-script rejection
Fixes test helper to include mandatory witness commitment when building witness blocks
Evidence from the diff
The patch modifies functional test helpers: (1) invalid_txs.py gains a new ExtraWitness BadTxTemplate that builds a transaction carrying witness data without spending a segwit output, expecting rejection with ‘tx-size-small’ in mempool and ‘block-script-verify-flag-failed (Witness provided for non-witness script)’ in block validation. (2) feature_block.py’s FullBlockTest.update_block() now detects whether any transaction in the constructed block has non-null witness data and, if so, calls add_witness_commitment(block) before solving. This fixes test-block construction so that witness-containing blocks include the required commitment, preventing unrelated test failures. No consensus, networking, or wallet code is touched.
Changed components
test/functional/data/invalid_txs.pytest/functional/feature_block.pyInspect captured patch +20 / −0
diff --git a/test/functional/data/invalid_txs.py b/test/functional/data/invalid_txs.py
index a7cdcb05..4853f8cc 100644
--- a/test/functional/data/invalid_txs.py
+++ b/test/functional/data/invalid_txs.py
@@ -26,6 +26,7 @@ from test_framework.messages import (
COutPoint,
CTransaction,
CTxIn,
+ CTxInWitness,
CTxOut,
MAX_MONEY,
SEQUENCE_FINAL,
@@ -36,6 +37,7 @@ from test_framework.blocktools import (
MAX_STANDARD_TX_SIGOPS,
)
from test_framework.script import (
+ OP_TRUE,
CScript,
OP_0,
OP_2DIV,
@@ -124,6 +126,20 @@ class SizeTooSmall(BadTxTemplate):
assert MIN_STANDARD_TX_NONWITNESS_SIZE - 1 == 64
return tx
+# reject a transaction that contains a witness
+# but doesn't spend a segwit output
+class ExtraWitness(BadTxTemplate):
+ reject_reason = "tx-size-small"
+ block_reject_reason = "block-script-verify-flag-failed (Witness provided for non-witness script)"
+
+ def get_tx(self):
+ tx = CTransaction()
+ tx.vin.append(self.valid_txin)
+ tx.vout.append(CTxOut(0, CScript()))
+ tx.wit.vtxinwit = [CTxInWitness()]
+ tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
+ return tx
+
class BadInputOutpointIndex(BadTxTemplate):
# Won't be rejected - nonexistent outpoint index is treated as an orphan since the coins
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index aa60788f..60e6117c 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -7,6 +7,7 @@ import copy
import time
from test_framework.blocktools import (
+ add_witness_commitment,
create_block,
create_coinbase,
create_tx_with_script,
@@ -1416,6 +1417,9 @@ class FullBlockTest(BitcoinTestFramework):
if nTime is not None:
block.nTime = nTime
block.hashMerkleRoot = block.calc_merkle_root()
+ has_witness_tx = any(not tx.wit.is_null() for tx in block.vtx)
+ if has_witness_tx:
+ add_witness_commitment(block)
block.solve()
# Update the internal state just like in next_block
self.tip = block
Why this scored 16/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.