test: test MAX_SCRIPT_SIZE for block validity
This commit is contained in:
1 parent
247e9de622
commit
b1ea542ae6
2 files changed
+32
-2
No files matched your search
@@ -30,6 +30,7 @@ from test_framework.p2p import P2PDataStore
|
|||||||
from test_framework.script import (
|
from test_framework.script import (
|
||||||
CScript,
|
CScript,
|
||||||
MAX_SCRIPT_ELEMENT_SIZE,
|
MAX_SCRIPT_ELEMENT_SIZE,
|
||||||
|
MAX_SCRIPT_SIZE,
|
||||||
OP_2DUP,
|
OP_2DUP,
|
||||||
OP_CHECKMULTISIG,
|
OP_CHECKMULTISIG,
|
||||||
OP_CHECKMULTISIGVERIFY,
|
OP_CHECKMULTISIGVERIFY,
|
||||||
@@ -52,6 +53,7 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
assert_greater_than,
|
assert_greater_than,
|
||||||
|
assert_raises_rpc_error,
|
||||||
)
|
)
|
||||||
from test_framework.wallet_util import generate_keypair
|
from test_framework.wallet_util import generate_keypair
|
||||||
from data import invalid_txs
|
from data import invalid_txs
|
||||||
@@ -112,10 +114,20 @@ class FullBlockTest(BitcoinTestFramework):
|
|||||||
b_dup_cb = self.update_block('dup_cb', [])
|
b_dup_cb = self.update_block('dup_cb', [])
|
||||||
self.send_blocks([b_dup_cb])
|
self.send_blocks([b_dup_cb])
|
||||||
|
|
||||||
b0 = self.next_block(0)
|
# Add gigantic boundary scripts that respect all other limits
|
||||||
|
max_valid_script = CScript([b'\x01' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [b'\x01' * 62])
|
||||||
|
assert_equal(len(max_valid_script), MAX_SCRIPT_SIZE)
|
||||||
|
min_invalid_script = CScript([b'\x01' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [b'\x01' * 63])
|
||||||
|
assert_equal(len(min_invalid_script), MAX_SCRIPT_SIZE + 1)
|
||||||
|
|
||||||
|
b0 = self.next_block(0, additional_output_scripts=[max_valid_script, min_invalid_script])
|
||||||
self.save_spendable_output()
|
self.save_spendable_output()
|
||||||
self.send_blocks([b0])
|
self.send_blocks([b0])
|
||||||
|
|
||||||
|
# Will test spending once possibly-mature
|
||||||
|
max_size_spendable_output = CTxIn(COutPoint(b0.vtx[0].sha256, 1))
|
||||||
|
min_size_unspendable_output = CTxIn(COutPoint(b0.vtx[0].sha256, 2))
|
||||||
|
|
||||||
# These constants chosen specifically to trigger an immature coinbase spend
|
# These constants chosen specifically to trigger an immature coinbase spend
|
||||||
# at a certain time below.
|
# at a certain time below.
|
||||||
NUM_BUFFER_BLOCKS_TO_GENERATE = 99
|
NUM_BUFFER_BLOCKS_TO_GENERATE = 99
|
||||||
@@ -128,6 +140,19 @@ class FullBlockTest(BitcoinTestFramework):
|
|||||||
self.save_spendable_output()
|
self.save_spendable_output()
|
||||||
self.send_blocks(blocks)
|
self.send_blocks(blocks)
|
||||||
|
|
||||||
|
# MAX_SCRIPT_SIZE testing now that coins are mature
|
||||||
|
tx = CTransaction()
|
||||||
|
tx.vin.append(max_size_spendable_output)
|
||||||
|
tx.vout.append(CTxOut(0, CScript([])))
|
||||||
|
block = self.generateblock(self.nodes[0], output="raw(55)", transactions=[tx.serialize().hex()])
|
||||||
|
assert_equal(block["hash"], self.nodes[0].getbestblockhash())
|
||||||
|
self.nodes[0].invalidateblock(block["hash"])
|
||||||
|
assert_equal(self.nodes[0].getrawmempool(), [])
|
||||||
|
|
||||||
|
# MAX_SCRIPT_SIZE + 1 wasn't added to the utxo set
|
||||||
|
tx.vin[0] = min_size_unspendable_output
|
||||||
|
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()])
|
||||||
|
|
||||||
# collect spendable outputs now to avoid cluttering the code later on
|
# collect spendable outputs now to avoid cluttering the code later on
|
||||||
out = []
|
out = []
|
||||||
for _ in range(NUM_OUTPUTS_TO_COLLECT):
|
for _ in range(NUM_OUTPUTS_TO_COLLECT):
|
||||||
@@ -1349,9 +1374,11 @@ class FullBlockTest(BitcoinTestFramework):
|
|||||||
tx.rehash()
|
tx.rehash()
|
||||||
return tx
|
return tx
|
||||||
|
|
||||||
def next_block(self, number, spend=None, additional_coinbase_value=0, *, script=None, version=4):
|
def next_block(self, number, spend=None, additional_coinbase_value=0, *, script=None, version=4, additional_output_scripts=None):
|
||||||
if script is None:
|
if script is None:
|
||||||
script = CScript([OP_TRUE])
|
script = CScript([OP_TRUE])
|
||||||
|
if additional_output_scripts is None:
|
||||||
|
additional_output_scripts = []
|
||||||
if self.tip is None:
|
if self.tip is None:
|
||||||
base_block_hash = self.genesis_hash
|
base_block_hash = self.genesis_hash
|
||||||
block_time = int(time.time()) + 1
|
block_time = int(time.time()) + 1
|
||||||
@@ -1362,6 +1389,8 @@ class FullBlockTest(BitcoinTestFramework):
|
|||||||
height = self.block_heights[base_block_hash] + 1
|
height = self.block_heights[base_block_hash] + 1
|
||||||
coinbase = create_coinbase(height, self.coinbase_pubkey)
|
coinbase = create_coinbase(height, self.coinbase_pubkey)
|
||||||
coinbase.vout[0].nValue += additional_coinbase_value
|
coinbase.vout[0].nValue += additional_coinbase_value
|
||||||
|
for additional_script in additional_output_scripts:
|
||||||
|
coinbase.vout.append(CTxOut(0, additional_script))
|
||||||
coinbase.rehash()
|
coinbase.rehash()
|
||||||
if spend is None:
|
if spend is None:
|
||||||
block = create_block(base_block_hash, coinbase, block_time, version=version)
|
block = create_block(base_block_hash, coinbase, block_time, version=version)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from .messages import (
|
|||||||
from .crypto.ripemd160 import ripemd160
|
from .crypto.ripemd160 import ripemd160
|
||||||
|
|
||||||
MAX_SCRIPT_ELEMENT_SIZE = 520
|
MAX_SCRIPT_ELEMENT_SIZE = 520
|
||||||
|
MAX_SCRIPT_SIZE = 10000
|
||||||
MAX_PUBKEYS_PER_MULTI_A = 999
|
MAX_PUBKEYS_PER_MULTI_A = 999
|
||||||
LOCKTIME_THRESHOLD = 500000000
|
LOCKTIME_THRESHOLD = 500000000
|
||||||
ANNEX_TAG = 0x50
|
ANNEX_TAG = 0x50
|
||||||
|
|||||||
Reference in new issue
Block a user