Merge bitcoin/bitcoin#31823: tests: Add witness commitment if we have a witness transaction in FullBlockTest.update_block()

a7c96f874d tests: Add witness commitment if we have a witness transaction in FullBlockTest.update_block() (Chris Stewart)

Pull request description:

  This is useful for test cases where we want to test logic invalid blocks that contain witness transactions. If we don't add the witness commitment as per [BIP141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#user-content-Commitment_structure), blocks will be rejected with the error [`Block mutated`](fb0ada982a/src/validation.cpp (L4180)).

  This change was needed in https://github.com/ajtowns/bitcoin/pull/13 which is a soft fork proposal to disallow 64 byte transactions. We want to test that 64 byte transactions serialized without the witness are invalid. If we do not have this change, we cannot directly test the logic that rejects 64 byte transactions.

  I decided to PR this upstream as many soft fork proposals may not see the light of day, but this functionality seems strictly additive to the test framework.

ACKs for top commit:
  theStack:
    ACK a7c96f874d
  sedited:
    ACK a7c96f874d
  glozow:
    ACK a7c96f874d

Tree-SHA512: 7c185838abaf068bc96b425c3c971b73f75dfcb41dacc8b2f2543c7602f23f19d908633278b93738f18049e6bd8c845c152cfb93b289bef501c7e86ed8dae0ab
This commit is contained in:
merge-script
2025-12-09 08:11:13 -08:00
2 changed files with 20 additions and 0 deletions

View File

@@ -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

View File

@@ -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