3030from test_framework .script import (
3131 CScript ,
3232 MAX_SCRIPT_ELEMENT_SIZE ,
33+ MAX_SCRIPT_SIZE ,
3334 OP_2DUP ,
3435 OP_CHECKMULTISIG ,
3536 OP_CHECKMULTISIGVERIFY ,
5253from test_framework .util import (
5354 assert_equal ,
5455 assert_greater_than ,
56+ assert_raises_rpc_error ,
5557)
5658from test_framework .wallet_util import generate_keypair
5759from data import invalid_txs
@@ -112,10 +114,20 @@ def run_test(self):
112114 b_dup_cb = self .update_block ('dup_cb' , [])
113115 self .send_blocks ([b_dup_cb ])
114116
115- b0 = self .next_block (0 )
117+ # Add gigantic boundary scripts that respect all other limits
118+ max_valid_script = CScript ([b'\x01 ' * MAX_SCRIPT_ELEMENT_SIZE ] * 19 + [b'\x01 ' * 62 ])
119+ assert_equal (len (max_valid_script ), MAX_SCRIPT_SIZE )
120+ min_invalid_script = CScript ([b'\x01 ' * MAX_SCRIPT_ELEMENT_SIZE ] * 19 + [b'\x01 ' * 63 ])
121+ assert_equal (len (min_invalid_script ), MAX_SCRIPT_SIZE + 1 )
122+
123+ b0 = self .next_block (0 , additional_output_scripts = [max_valid_script , min_invalid_script ])
116124 self .save_spendable_output ()
117125 self .send_blocks ([b0 ])
118126
127+ # Will test spending once possibly-mature
128+ max_size_spendable_output = CTxIn (COutPoint (b0 .vtx [0 ].sha256 , 1 ))
129+ min_size_unspendable_output = CTxIn (COutPoint (b0 .vtx [0 ].sha256 , 2 ))
130+
119131 # These constants chosen specifically to trigger an immature coinbase spend
120132 # at a certain time below.
121133 NUM_BUFFER_BLOCKS_TO_GENERATE = 99
@@ -128,6 +140,19 @@ def run_test(self):
128140 self .save_spendable_output ()
129141 self .send_blocks (blocks )
130142
143+ # MAX_SCRIPT_SIZE testing now that coins are mature
144+ tx = CTransaction ()
145+ tx .vin .append (max_size_spendable_output )
146+ tx .vout .append (CTxOut (0 , CScript ([])))
147+ block = self .generateblock (self .nodes [0 ], output = "raw(55)" , transactions = [tx .serialize ().hex ()])
148+ assert_equal (block ["hash" ], self .nodes [0 ].getbestblockhash ())
149+ self .nodes [0 ].invalidateblock (block ["hash" ])
150+ assert_equal (self .nodes [0 ].getrawmempool (), [])
151+
152+ # MAX_SCRIPT_SIZE + 1 wasn't added to the utxo set
153+ tx .vin [0 ] = min_size_unspendable_output
154+ assert_raises_rpc_error (- 25 , f'TestBlockValidity failed: bad-txns-inputs-missingorspent, CheckTxInputs: inputs missing/spent in transaction { tx .rehash ()} ' , self .generateblock , self .nodes [0 ], output = "raw(55)" , transactions = [tx .serialize ().hex ()])
155+
131156 # collect spendable outputs now to avoid cluttering the code later on
132157 out = []
133158 for _ in range (NUM_OUTPUTS_TO_COLLECT ):
@@ -1358,9 +1383,11 @@ def create_and_sign_transaction(self, spend_tx, value, output_script=None):
13581383 tx .rehash ()
13591384 return tx
13601385
1361- def next_block (self , number , spend = None , additional_coinbase_value = 0 , * , script = None , version = 4 ):
1386+ def next_block (self , number , spend = None , additional_coinbase_value = 0 , * , script = None , version = 4 , additional_output_scripts = None ):
13621387 if script is None :
13631388 script = CScript ([OP_TRUE ])
1389+ if additional_output_scripts is None :
1390+ additional_output_scripts = []
13641391 if self .tip is None :
13651392 base_block_hash = self .genesis_hash
13661393 block_time = int (time .time ()) + 1
@@ -1371,6 +1398,8 @@ def next_block(self, number, spend=None, additional_coinbase_value=0, *, script=
13711398 height = self .block_heights [base_block_hash ] + 1
13721399 coinbase = create_coinbase (height , self .coinbase_pubkey )
13731400 coinbase .vout [0 ].nValue += additional_coinbase_value
1401+ for additional_script in additional_output_scripts :
1402+ coinbase .vout .append (CTxOut (0 , additional_script ))
13741403 coinbase .rehash ()
13751404 if spend is None :
13761405 block = create_block (base_block_hash , coinbase , block_time , version = version )
0 commit comments