mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Merge #17921: test: test OP_CSV empty stack fail in feature_csv_activation.py
5ffaf883b93fb8d3d841c36e808b90d61d39d492 test: eliminiated magic numbers in feature_csv_activation.py (Sebastian Falbesoner) 09f706ab8e47ddfdfa41418f2e7cb6d87661147a test: check for OP_CSV empty stack fail reject reason in feature_csv_activation.py (Sebastian Falbesoner) cbd345a75c2be26e17fce4c65c0c1ca19a3eb9e0 test: test OP_CSV empty stack fail in feature_csv_activation.py (Sebastian Falbesoner) Pull request description: Adds an empty stack failure check for OP_CSV (BIP112) to the functional test `feature_csv_activation.py` by prepending a valid scriptSig with `OP_CHECKSEQUENCEVERIFY`. If BIP112 is inactive, the operator just behaves as a NOP (for both tx versions 1 and 2) and the transaction remains valid -- if it is active, the tx is invalid due to an empty stack (for both tx versions 1 and 2, as well). Top commit has no ACKs. Tree-SHA512: 81102aaead5be11e02b894867fa9a9cc17358ec0eb2f21ce2d3db845b87691d305e6ed7c525f9c7e5bcb3c5c609eb28deca0fbaa3d5e9ff928cecd3b91ff129a
This commit is contained in:
parent
eb8d399985
commit
79bd96b744
@ -41,6 +41,7 @@ bip112txs_vary_nSequence_9 - 16 txs with nSequence relative_locktimes of 9 evalu
|
|||||||
bip112txs_vary_OP_CSV - 16 txs with nSequence = 10 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
|
bip112txs_vary_OP_CSV - 16 txs with nSequence = 10 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
|
||||||
bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
|
bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
|
||||||
bip112tx_special - test negative argument to OP_CSV
|
bip112tx_special - test negative argument to OP_CSV
|
||||||
|
bip112tx_emptystack - test empty stack (= no argument) OP_CSV
|
||||||
"""
|
"""
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from itertools import product
|
from itertools import product
|
||||||
@ -61,6 +62,8 @@ from test_framework.util import (
|
|||||||
hex_str_to_bytes,
|
hex_str_to_bytes,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
TESTING_TX_COUNT = 83 # Number of testing transactions: 1 BIP113 tx, 16 BIP68 txs, 66 BIP112 txs (see comments above)
|
||||||
|
COINBASE_BLOCK_COUNT = TESTING_TX_COUNT # Number of coinbase blocks we need to generate as inputs for our txs
|
||||||
BASE_RELATIVE_LOCKTIME = 10
|
BASE_RELATIVE_LOCKTIME = 10
|
||||||
SEQ_DISABLE_FLAG = 1 << 31
|
SEQ_DISABLE_FLAG = 1 << 31
|
||||||
SEQ_RANDOM_HIGH_BIT = 1 << 25
|
SEQ_RANDOM_HIGH_BIT = 1 << 25
|
||||||
@ -99,6 +102,13 @@ def create_bip112special(node, input, txversion, address):
|
|||||||
signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
|
signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
|
||||||
return signtx
|
return signtx
|
||||||
|
|
||||||
|
def create_bip112emptystack(node, input, txversion, address):
|
||||||
|
tx = create_transaction(node, input, address, amount=Decimal("499.98"))
|
||||||
|
tx.nVersion = txversion
|
||||||
|
signtx = sign_transaction(node, tx)
|
||||||
|
signtx.vin[0].scriptSig = CScript([OP_CHECKSEQUENCEVERIFY] + list(CScript(signtx.vin[0].scriptSig)))
|
||||||
|
return signtx
|
||||||
|
|
||||||
def send_generic_input_tx(node, coinbases, address):
|
def send_generic_input_tx(node, coinbases, address):
|
||||||
return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("499.99")))))
|
return node.sendrawtransaction(ToHex(sign_transaction(node, create_transaction(node, node.getblock(coinbases.pop())['tx'][0], address, amount=Decimal("499.99")))))
|
||||||
|
|
||||||
@ -148,6 +158,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
'-whitelist=noban@127.0.0.1',
|
'-whitelist=noban@127.0.0.1',
|
||||||
'-blockversion=4',
|
'-blockversion=4',
|
||||||
'-maxtipage=600100', '-dip3params=2000:2000',
|
'-maxtipage=600100', '-dip3params=2000:2000',
|
||||||
|
'-par=1', # Use only one script thread to get the exact reject reason for testing
|
||||||
]]
|
]]
|
||||||
self.supports_cli = False
|
self.supports_cli = False
|
||||||
|
|
||||||
@ -177,28 +188,33 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
block.solve()
|
block.solve()
|
||||||
return block
|
return block
|
||||||
|
|
||||||
def send_blocks(self, blocks, success=True):
|
def send_blocks(self, blocks, success=True, reject_reason=None):
|
||||||
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
|
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
|
||||||
|
|
||||||
Call with success = False if the tip shouldn't advance to the most recent block."""
|
Call with success = False if the tip shouldn't advance to the most recent block."""
|
||||||
self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success)
|
self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason)
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
self.nodes[0].add_p2p_connection(P2PDataStore())
|
self.nodes[0].add_p2p_connection(P2PDataStore())
|
||||||
|
|
||||||
self.log.info("Generate blocks in the past for coinbase outputs.")
|
self.log.info("Generate blocks in the past for coinbase outputs.")
|
||||||
self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2 * 32 + 1) # 82 blocks generated for inputs
|
self.coinbase_blocks = self.nodes[0].generate(COINBASE_BLOCK_COUNT) # blocks generated for inputs
|
||||||
# set time so that there was enough time to build up to 1000 blocks 10 minutes apart on top of the last one
|
# set time so that there was enough time to build up to 1000 blocks 10 minutes apart on top of the last one
|
||||||
# without worrying about getting into the future
|
# without worrying about getting into the future
|
||||||
self.nodes[0].setmocktime(TIME_GENESIS_BLOCK + 600 * 1000 + 100)
|
self.nodes[0].setmocktime(TIME_GENESIS_BLOCK + 600 * 1000 + 100)
|
||||||
self.tipheight = 82 # height of the next block to build
|
self.tipheight = COINBASE_BLOCK_COUNT # height of the next block to build
|
||||||
self.last_block_time = TIME_GENESIS_BLOCK
|
self.last_block_time = TIME_GENESIS_BLOCK
|
||||||
self.tip = int(self.nodes[0].getbestblockhash(), 16)
|
self.tip = int(self.nodes[0].getbestblockhash(), 16)
|
||||||
self.nodeaddress = self.nodes[0].getnewaddress()
|
self.nodeaddress = self.nodes[0].getnewaddress()
|
||||||
|
|
||||||
|
# TODO: uncomment the code below when bitcoin#16060 is backported,
|
||||||
|
# should go right below `# Activation height is hardcoded` line
|
||||||
|
# # We advance to block height five below BIP112 activation for the following tests
|
||||||
|
# test_blocks = self.generate_blocks(CSV_ACTIVATION_HEIGHT-5 - COINBASE_BLOCK_COUNT)
|
||||||
|
|
||||||
self.log.info("Test that the csv softfork is DEFINED")
|
self.log.info("Test that the csv softfork is DEFINED")
|
||||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
|
||||||
test_blocks = self.generate_blocks(61, 4)
|
test_blocks = self.generate_blocks(60, 4)
|
||||||
self.send_blocks(test_blocks)
|
self.send_blocks(test_blocks)
|
||||||
|
|
||||||
self.log.info("Advance from DEFINED to STARTED, height = 143")
|
self.log.info("Advance from DEFINED to STARTED, height = 143")
|
||||||
@ -259,6 +275,8 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
|
|
||||||
# 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
|
# 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
|
||||||
bip112specialinput = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
|
bip112specialinput = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
|
||||||
|
# 1 special input with (empty stack) OP_CSV (actually will be prepended to spending scriptSig)
|
||||||
|
bip112emptystackinput = send_generic_input_tx(self.nodes[0],self.coinbase_blocks, self.nodeaddress)
|
||||||
|
|
||||||
# 1 normal input
|
# 1 normal input
|
||||||
bip113input = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
|
bip113input = send_generic_input_tx(self.nodes[0], self.coinbase_blocks, self.nodeaddress)
|
||||||
@ -269,7 +287,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
self.tip = int(inputblockhash, 16)
|
self.tip = int(inputblockhash, 16)
|
||||||
self.tipheight += 1
|
self.tipheight += 1
|
||||||
self.last_block_time += 600
|
self.last_block_time += 600
|
||||||
assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), 82 + 1)
|
assert_equal(len(self.nodes[0].getblock(inputblockhash, True)["tx"]), TESTING_TX_COUNT + 1)
|
||||||
|
|
||||||
# 2 more version 4 blocks
|
# 2 more version 4 blocks
|
||||||
test_blocks = self.generate_blocks(2, 4)
|
test_blocks = self.generate_blocks(2, 4)
|
||||||
@ -307,6 +325,9 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
# -1 OP_CSV OP_DROP input
|
# -1 OP_CSV OP_DROP input
|
||||||
bip112tx_special_v1 = create_bip112special(self.nodes[0], bip112specialinput, 1, self.nodeaddress)
|
bip112tx_special_v1 = create_bip112special(self.nodes[0], bip112specialinput, 1, self.nodeaddress)
|
||||||
bip112tx_special_v2 = create_bip112special(self.nodes[0], bip112specialinput, 2, self.nodeaddress)
|
bip112tx_special_v2 = create_bip112special(self.nodes[0], bip112specialinput, 2, self.nodeaddress)
|
||||||
|
# (empty stack) OP_CSV input
|
||||||
|
bip112tx_emptystack_v1 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 1, self.nodeaddress)
|
||||||
|
bip112tx_emptystack_v2 = create_bip112emptystack(self.nodes[0], bip112emptystackinput, 2, self.nodeaddress)
|
||||||
|
|
||||||
self.log.info("TESTING")
|
self.log.info("TESTING")
|
||||||
|
|
||||||
@ -314,11 +335,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
self.log.info("Test version 1 txs")
|
self.log.info("Test version 1 txs")
|
||||||
|
|
||||||
success_txs = []
|
success_txs = []
|
||||||
# add BIP113 tx and -1 CSV tx
|
# BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
|
||||||
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
||||||
bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
|
bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
|
||||||
success_txs.append(bip113signed1)
|
success_txs.append(bip113signed1)
|
||||||
success_txs.append(bip112tx_special_v1)
|
success_txs.append(bip112tx_special_v1)
|
||||||
|
success_txs.append(bip112tx_emptystack_v1)
|
||||||
# add BIP 68 txs
|
# add BIP 68 txs
|
||||||
success_txs.extend(all_rlt_txs(bip68txs_v1))
|
success_txs.extend(all_rlt_txs(bip68txs_v1))
|
||||||
# add BIP 112 with seq=10 txs
|
# add BIP 112 with seq=10 txs
|
||||||
@ -333,11 +355,12 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
self.log.info("Test version 2 txs")
|
self.log.info("Test version 2 txs")
|
||||||
|
|
||||||
success_txs = []
|
success_txs = []
|
||||||
# add BIP113 tx and -1 CSV tx
|
# BIP113 tx, -1 CSV tx and empty stack CSV tx should succeed
|
||||||
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
||||||
bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
|
bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
|
||||||
success_txs.append(bip113signed2)
|
success_txs.append(bip113signed2)
|
||||||
success_txs.append(bip112tx_special_v2)
|
success_txs.append(bip112tx_special_v2)
|
||||||
|
success_txs.append(bip112tx_emptystack_v2)
|
||||||
# add BIP 68 txs
|
# add BIP 68 txs
|
||||||
success_txs.extend(all_rlt_txs(bip68txs_v2))
|
success_txs.extend(all_rlt_txs(bip68txs_v2))
|
||||||
# add BIP 112 with seq=10 txs
|
# add BIP 112 with seq=10 txs
|
||||||
@ -424,8 +447,10 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
self.log.info("BIP 112 tests")
|
self.log.info("BIP 112 tests")
|
||||||
self.log.info("Test version 1 txs")
|
self.log.info("Test version 1 txs")
|
||||||
|
|
||||||
# -1 OP_CSV tx should fail
|
# -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
|
||||||
self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False)
|
self.send_blocks([self.create_test_block([bip112tx_special_v1])], success=False)
|
||||||
|
self.send_blocks([self.create_test_block([bip112tx_emptystack_v1])], success=False,
|
||||||
|
reject_reason='non-mandatory-script-verify-flag (Operation not valid with the current stack size)')
|
||||||
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
|
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
|
||||||
|
|
||||||
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if tx['sdf']]
|
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v1 if tx['sdf']]
|
||||||
@ -443,8 +468,10 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
|
|
||||||
self.log.info("Test version 2 txs")
|
self.log.info("Test version 2 txs")
|
||||||
|
|
||||||
# -1 OP_CSV tx should fail
|
# -1 OP_CSV tx and (empty stack) OP_CSV tx should fail
|
||||||
self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False)
|
self.send_blocks([self.create_test_block([bip112tx_special_v2])], success=False)
|
||||||
|
self.send_blocks([self.create_test_block([bip112tx_emptystack_v2])], success=False,
|
||||||
|
reject_reason='non-mandatory-script-verify-flag (Operation not valid with the current stack size)')
|
||||||
|
|
||||||
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
|
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
|
||||||
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if tx['sdf']]
|
success_txs = [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if tx['sdf']]
|
||||||
@ -488,7 +515,5 @@ class BIP68_112_113Test(BitcoinTestFramework):
|
|||||||
self.send_blocks([self.create_test_block(time_txs)])
|
self.send_blocks([self.create_test_block(time_txs)])
|
||||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||||
|
|
||||||
# TODO: Test empty stack fails
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
BIP68_112_113Test().main()
|
BIP68_112_113Test().main()
|
||||||
|
Loading…
Reference in New Issue
Block a user