7979 add_witness_commitment ,
8080)
8181from test_framework .script_util import (
82+ PAY_TO_ANCHOR ,
8283 script_to_p2wsh_script ,
8384 script_to_p2sh_script ,
8485)
@@ -856,6 +857,65 @@ def create_block_with_generation_output(script_pubkey):
856857 assert_equal (result , 'bad-txns-vout-script-toolarge' )
857858 self .log .info (" ✓ Generation tx with 84-byte OP_RETURN output rejected" )
858859
860+ def test_p2a_witness_rejected (self ):
861+ """Test that P2A (PayToAnchor) spends with non-empty witness are rejected."""
862+ self .log .info ("Testing P2A non-empty witness rejection..." )
863+ node = self .nodes [0 ]
864+
865+ # Create a P2A output (4 bytes, within the 34-byte limit)
866+ p2a_funding = self .create_test_transaction (PAY_TO_ANCHOR )
867+ p2a_funding .rehash ()
868+ p2a_value = p2a_funding .vout [0 ].nValue
869+
870+ block_height = node .getblockcount () + 1
871+ block = create_block (int (node .getbestblockhash (), 16 ), create_coinbase (block_height ), int (node .getblockheader (node .getbestblockhash ())['time' ]) + 1 )
872+ block .vtx .append (p2a_funding )
873+ add_witness_commitment (block )
874+ block .solve ()
875+ assert_equal (node .submitblock (block .serialize ().hex ()), None )
876+ self .log .info (" P2A output created" )
877+
878+ # Test 1: Spend with 100 KB of arbitrary witness data (must be rejected)
879+ self .log .info (" Test: P2A spend with large arbitrary witness (should be rejected)" )
880+ arbitrary_data = b'\xab ' * 100_000
881+
882+ p2a_spend = CTransaction ()
883+ p2a_spend .vin = [CTxIn (COutPoint (int (p2a_funding .rehash (), 16 ), 0 ))]
884+ p2a_spend .vout = [CTxOut (p2a_value - 1000 , CScript ([OP_0 , hash160 (b'\x01 ' * 33 )]))]
885+ p2a_spend .wit .vtxinwit = [CTxInWitness ()]
886+ p2a_spend .wit .vtxinwit [0 ].scriptWitness .stack = [arbitrary_data ]
887+ p2a_spend .rehash ()
888+
889+ block_height = node .getblockcount () + 1
890+ block_bad = create_block (int (node .getbestblockhash (), 16 ), create_coinbase (block_height ), int (node .getblockheader (node .getbestblockhash ())['time' ]) + 1 )
891+ block_bad .vtx .append (p2a_spend )
892+ add_witness_commitment (block_bad )
893+ block_bad .solve ()
894+
895+ result = node .submitblock (block_bad .serialize ().hex ())
896+ assert result is not None
897+ assert_equal (node .getblockcount (), block_height - 1 )
898+ self .log .info (f" ✓ P2A spend with 100 KB witness rejected ({ result } )" )
899+
900+ # Test 2: Spend with empty witness (must still be accepted)
901+ self .log .info (" Test: P2A spend with empty witness (should be accepted)" )
902+ p2a_spend_empty = CTransaction ()
903+ p2a_spend_empty .vin = [CTxIn (COutPoint (int (p2a_funding .rehash (), 16 ), 0 ))]
904+ p2a_spend_empty .vout = [CTxOut (p2a_value - 1000 , CScript ([OP_0 , hash160 (b'\x01 ' * 33 )]))]
905+ p2a_spend_empty .wit .vtxinwit = [CTxInWitness ()]
906+ p2a_spend_empty .wit .vtxinwit [0 ].scriptWitness .stack = []
907+ p2a_spend_empty .rehash ()
908+
909+ block_height = node .getblockcount () + 1
910+ block_good = create_block (int (node .getbestblockhash (), 16 ), create_coinbase (block_height ), int (node .getblockheader (node .getbestblockhash ())['time' ]) + 1 )
911+ block_good .vtx .append (p2a_spend_empty )
912+ add_witness_commitment (block_good )
913+ block_good .solve ()
914+
915+ assert_equal (node .submitblock (block_good .serialize ().hex ()), None )
916+ assert_equal (node .getblockcount (), block_height )
917+ self .log .info (" ✓ P2A spend with empty witness accepted" )
918+
859919 def run_test (self ):
860920 self .init_test ()
861921
@@ -869,6 +929,7 @@ def run_test(self):
869929 self .test_op_success_rejection ()
870930 self .test_op_if_notif_rejection ()
871931 self .test_mandatory_flags_cannot_be_bypassed ()
932+ self .test_p2a_witness_rejected ()
872933
873934 self .log .info ("All UASF-ReducedData tests completed" )
874935
0 commit comments