Skip to content

Commit 5471e29

Browse files
committed
Merge bitcoin#32304: test: test MAX_SCRIPT_SIZE for block validity
b1ea542 test: test MAX_SCRIPT_SIZE for block validity (Greg Sanders) Pull request description: I don't believe there are direct tests for this. ACKs for top commit: achow101: ACK b1ea542 TheCharlatan: ACK b1ea542 theStack: ACK b1ea542 Tree-SHA512: 1d7d3eab9c54977844bf2ca1aa403b070aae0f818db2fb5cae367d1c4d12f1e403b6fdec224af769a2ebb648cbca8bfd0d7df5db2a89fccf256c9c244484eba2
2 parents c540ede + b1ea542 commit 5471e29

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

test/functional/feature_block.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from test_framework.script import (
3131
CScript,
3232
MAX_SCRIPT_ELEMENT_SIZE,
33+
MAX_SCRIPT_SIZE,
3334
OP_2DUP,
3435
OP_CHECKMULTISIG,
3536
OP_CHECKMULTISIGVERIFY,
@@ -52,6 +53,7 @@
5253
from test_framework.util import (
5354
assert_equal,
5455
assert_greater_than,
56+
assert_raises_rpc_error,
5557
)
5658
from test_framework.wallet_util import generate_keypair
5759
from 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)

test/functional/test_framework/script.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from .crypto.ripemd160 import ripemd160
2424

2525
MAX_SCRIPT_ELEMENT_SIZE = 520
26+
MAX_SCRIPT_SIZE = 10000
2627
MAX_PUBKEYS_PER_MULTI_A = 999
2728
LOCKTIME_THRESHOLD = 500000000
2829
ANNEX_TAG = 0x50

0 commit comments

Comments
 (0)