30
30
from test_framework .script import (
31
31
CScript ,
32
32
MAX_SCRIPT_ELEMENT_SIZE ,
33
+ MAX_SCRIPT_SIZE ,
33
34
OP_2DUP ,
34
35
OP_CHECKMULTISIG ,
35
36
OP_CHECKMULTISIGVERIFY ,
52
53
from test_framework .util import (
53
54
assert_equal ,
54
55
assert_greater_than ,
56
+ assert_raises_rpc_error ,
55
57
)
56
58
from test_framework .wallet_util import generate_keypair
57
59
from data import invalid_txs
@@ -112,10 +114,20 @@ def run_test(self):
112
114
b_dup_cb = self .update_block ('dup_cb' , [])
113
115
self .send_blocks ([b_dup_cb ])
114
116
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 ])
116
124
self .save_spendable_output ()
117
125
self .send_blocks ([b0 ])
118
126
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
+
119
131
# These constants chosen specifically to trigger an immature coinbase spend
120
132
# at a certain time below.
121
133
NUM_BUFFER_BLOCKS_TO_GENERATE = 99
@@ -128,6 +140,19 @@ def run_test(self):
128
140
self .save_spendable_output ()
129
141
self .send_blocks (blocks )
130
142
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
+
131
156
# collect spendable outputs now to avoid cluttering the code later on
132
157
out = []
133
158
for _ in range (NUM_OUTPUTS_TO_COLLECT ):
@@ -1358,9 +1383,11 @@ def create_and_sign_transaction(self, spend_tx, value, output_script=None):
1358
1383
tx .rehash ()
1359
1384
return tx
1360
1385
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 ):
1362
1387
if script is None :
1363
1388
script = CScript ([OP_TRUE ])
1389
+ if additional_output_scripts is None :
1390
+ additional_output_scripts = []
1364
1391
if self .tip is None :
1365
1392
base_block_hash = self .genesis_hash
1366
1393
block_time = int (time .time ()) + 1
@@ -1371,6 +1398,8 @@ def next_block(self, number, spend=None, additional_coinbase_value=0, *, script=
1371
1398
height = self .block_heights [base_block_hash ] + 1
1372
1399
coinbase = create_coinbase (height , self .coinbase_pubkey )
1373
1400
coinbase .vout [0 ].nValue += additional_coinbase_value
1401
+ for additional_script in additional_output_scripts :
1402
+ coinbase .vout .append (CTxOut (0 , additional_script ))
1374
1403
coinbase .rehash ()
1375
1404
if spend is None :
1376
1405
block = create_block (base_block_hash , coinbase , block_time , version = version )
0 commit comments