|
|
|
@ -48,14 +48,14 @@ from io import BytesIO
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
from test_framework.blocktools import create_coinbase, create_block
|
|
|
|
|
from test_framework.comptool import TestInstance, TestManager
|
|
|
|
|
from test_framework.mininode import ToHex, CTransaction, network_thread_start
|
|
|
|
|
from test_framework.messages import ToHex, CTransaction
|
|
|
|
|
from test_framework.mininode import network_thread_start, P2PDataStore
|
|
|
|
|
from test_framework.script import (
|
|
|
|
|
CScript,
|
|
|
|
|
OP_CHECKSEQUENCEVERIFY,
|
|
|
|
|
OP_DROP,
|
|
|
|
|
)
|
|
|
|
|
from test_framework.test_framework import ComparisonTestFramework
|
|
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
|
|
|
|
from test_framework.util import (
|
|
|
|
|
assert_equal,
|
|
|
|
|
get_bip9_status,
|
|
|
|
@ -149,22 +149,18 @@ def create_bip112txs(node, bip112inputs, varyOP_CSV, txversion, address, locktim
|
|
|
|
|
txs.append({'tx': signtx, 'sdf': sdf, 'stf': stf})
|
|
|
|
|
return txs
|
|
|
|
|
|
|
|
|
|
class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
class BIP68_112_113Test(BitcoinTestFramework):
|
|
|
|
|
def set_test_params(self):
|
|
|
|
|
self.num_nodes = 1
|
|
|
|
|
self.setup_clean_chain = True
|
|
|
|
|
self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']]
|
|
|
|
|
|
|
|
|
|
def run_test(self):
|
|
|
|
|
test = TestManager(self, self.options.tmpdir)
|
|
|
|
|
test.add_all_connections(self.nodes)
|
|
|
|
|
network_thread_start()
|
|
|
|
|
test.run()
|
|
|
|
|
|
|
|
|
|
def generate_blocks(self, number, version, test_blocks=[]):
|
|
|
|
|
def generate_blocks(self, number, version, test_blocks=None):
|
|
|
|
|
if test_blocks is None:
|
|
|
|
|
test_blocks = []
|
|
|
|
|
for i in range(number):
|
|
|
|
|
block = self.create_test_block([], version)
|
|
|
|
|
test_blocks.append([block, True])
|
|
|
|
|
test_blocks.append(block)
|
|
|
|
|
self.last_block_time += 600
|
|
|
|
|
self.tip = block.sha256
|
|
|
|
|
self.tipheight += 1
|
|
|
|
@ -179,7 +175,17 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
block.solve()
|
|
|
|
|
return block
|
|
|
|
|
|
|
|
|
|
def get_tests(self):
|
|
|
|
|
def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True):
|
|
|
|
|
"""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."""
|
|
|
|
|
self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_code=reject_code, reject_reason=reject_reason, request_block=request_block)
|
|
|
|
|
|
|
|
|
|
def run_test(self):
|
|
|
|
|
self.nodes[0].add_p2p_connection(P2PDataStore())
|
|
|
|
|
network_thread_start()
|
|
|
|
|
self.nodes[0].p2p.wait_for_verack()
|
|
|
|
|
|
|
|
|
|
self.log.info("Generate blocks in the past for coinbase outputs.")
|
|
|
|
|
long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future
|
|
|
|
|
self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time
|
|
|
|
@ -193,7 +199,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
self.log.info("Test that the csv softfork is DEFINED")
|
|
|
|
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
|
|
|
|
|
test_blocks = self.generate_blocks(61, 4)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
self.log.info("Advance from DEFINED to STARTED, height = 143")
|
|
|
|
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
|
|
|
@ -205,7 +211,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not)
|
|
|
|
|
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
|
|
|
|
|
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
self.log.info("Failed to advance past STARTED, height = 287")
|
|
|
|
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
|
|
|
@ -217,14 +223,14 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not)
|
|
|
|
|
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
|
|
|
|
|
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
self.log.info("Advanced from STARTED to LOCKED_IN, height = 431")
|
|
|
|
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
|
|
|
|
|
|
|
|
|
# Generate 140 more version 4 blocks
|
|
|
|
|
test_blocks = self.generate_blocks(140, 4)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
# Inputs at height = 572
|
|
|
|
|
#
|
|
|
|
@ -267,7 +273,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
|
|
|
|
|
# 2 more version 4 blocks
|
|
|
|
|
test_blocks = self.generate_blocks(2, 4)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
self.log.info("Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)")
|
|
|
|
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
|
|
|
@ -321,7 +327,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
# try BIP 112 with seq=9 txs
|
|
|
|
|
success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1))
|
|
|
|
|
success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v1))
|
|
|
|
|
yield TestInstance([[self.create_test_block(success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
self.log.info("Test version 2 txs")
|
|
|
|
@ -340,12 +346,12 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
# try BIP 112 with seq=9 txs
|
|
|
|
|
success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2))
|
|
|
|
|
success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v2))
|
|
|
|
|
yield TestInstance([[self.create_test_block(success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
|
|
|
|
|
test_blocks = self.generate_blocks(1, 4)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
|
|
|
|
|
|
|
|
|
|
self.log.info("Post-Soft Fork Tests.")
|
|
|
|
@ -357,74 +363,74 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
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)
|
|
|
|
|
for bip113tx in [bip113signed1, bip113signed2]:
|
|
|
|
|
yield TestInstance([[self.create_test_block([bip113tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([bip113tx])], success=False)
|
|
|
|
|
# BIP 113 tests should now pass if the locktime is < MTP
|
|
|
|
|
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
|
|
|
|
|
bip113signed1 = sign_transaction(self.nodes[0], bip113tx_v1)
|
|
|
|
|
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
|
|
|
|
|
bip113signed2 = sign_transaction(self.nodes[0], bip113tx_v2)
|
|
|
|
|
for bip113tx in [bip113signed1, bip113signed2]:
|
|
|
|
|
yield TestInstance([[self.create_test_block([bip113tx]), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([bip113tx])])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
# Next block height = 580 after 4 blocks of random version
|
|
|
|
|
test_blocks = self.generate_blocks(4, 1234)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
self.log.info("BIP 68 tests")
|
|
|
|
|
self.log.info("Test version 1 txs - all should still pass")
|
|
|
|
|
|
|
|
|
|
success_txs = []
|
|
|
|
|
success_txs.extend(all_rlt_txs(bip68txs_v1))
|
|
|
|
|
yield TestInstance([[self.create_test_block(success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
self.log.info("Test version 2 txs")
|
|
|
|
|
|
|
|
|
|
# All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass
|
|
|
|
|
bip68success_txs = [tx['tx'] for tx in bip68txs_v2 if tx['sdf']]
|
|
|
|
|
yield TestInstance([[self.create_test_block(bip68success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(bip68success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
# All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
|
|
|
|
|
bip68timetxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and tx['stf']]
|
|
|
|
|
for tx in bip68timetxs:
|
|
|
|
|
yield TestInstance([[self.create_test_block([tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([tx])], success=False)
|
|
|
|
|
|
|
|
|
|
bip68heighttxs = [tx['tx'] for tx in bip68txs_v2 if not tx['sdf'] and not tx['stf']]
|
|
|
|
|
for tx in bip68heighttxs:
|
|
|
|
|
yield TestInstance([[self.create_test_block([tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([tx])], success=False)
|
|
|
|
|
|
|
|
|
|
# Advance one block to 581
|
|
|
|
|
test_blocks = self.generate_blocks(1, 1234)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
# Height txs should fail and time txs should now pass 9 * 600 > 10 * 512
|
|
|
|
|
bip68success_txs.extend(bip68timetxs)
|
|
|
|
|
yield TestInstance([[self.create_test_block(bip68success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(bip68success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
for tx in bip68heighttxs:
|
|
|
|
|
yield TestInstance([[self.create_test_block([tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([tx])], success=False)
|
|
|
|
|
|
|
|
|
|
# Advance one block to 582
|
|
|
|
|
test_blocks = self.generate_blocks(1, 1234)
|
|
|
|
|
yield TestInstance(test_blocks, sync_every_block=False)
|
|
|
|
|
self.sync_blocks(test_blocks)
|
|
|
|
|
|
|
|
|
|
# All BIP 68 txs should pass
|
|
|
|
|
bip68success_txs.extend(bip68heighttxs)
|
|
|
|
|
yield TestInstance([[self.create_test_block(bip68success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(bip68success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
self.log.info("BIP 112 tests")
|
|
|
|
|
self.log.info("Test version 1 txs")
|
|
|
|
|
|
|
|
|
|
# -1 OP_CSV tx should fail
|
|
|
|
|
yield TestInstance([[self.create_test_block([bip112tx_special_v1]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([bip112tx_special_v1])], success=False)
|
|
|
|
|
# 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_9_v1 if tx['sdf']]
|
|
|
|
|
yield TestInstance([[self.create_test_block(success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
|
|
|
|
@ -433,18 +439,18 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
|
|
|
|
|
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v1 if not tx['sdf']]
|
|
|
|
|
for tx in fail_txs:
|
|
|
|
|
yield TestInstance([[self.create_test_block([tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([tx])], success=False)
|
|
|
|
|
|
|
|
|
|
self.log.info("Version 2 txs")
|
|
|
|
|
self.log.info("Test version 2 txs")
|
|
|
|
|
|
|
|
|
|
# -1 OP_CSV tx should fail
|
|
|
|
|
yield TestInstance([[self.create_test_block([bip112tx_special_v2]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([bip112tx_special_v2])], success=False)
|
|
|
|
|
|
|
|
|
|
# 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_9_v2 if tx['sdf']]
|
|
|
|
|
|
|
|
|
|
yield TestInstance([[self.create_test_block(success_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
# SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ##
|
|
|
|
@ -453,23 +459,23 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
fail_txs = all_rlt_txs(bip112txs_vary_nSequence_9_v2)
|
|
|
|
|
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_9_v2 if not tx['sdf']]
|
|
|
|
|
for tx in fail_txs:
|
|
|
|
|
yield TestInstance([[self.create_test_block([tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([tx])], success=False)
|
|
|
|
|
|
|
|
|
|
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
|
|
|
|
|
fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if tx['sdf']]
|
|
|
|
|
for tx in fail_txs:
|
|
|
|
|
yield TestInstance([[self.create_test_block([tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([tx])], success=False)
|
|
|
|
|
|
|
|
|
|
# If sequencelock types mismatch, tx should fail
|
|
|
|
|
fail_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and tx['stf']]
|
|
|
|
|
fail_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and tx['stf']]
|
|
|
|
|
for tx in fail_txs:
|
|
|
|
|
yield TestInstance([[self.create_test_block([tx]), False]])
|
|
|
|
|
self.sync_blocks([self.create_test_block([tx])], success=False)
|
|
|
|
|
|
|
|
|
|
# Remaining txs should pass, just test masking works properly
|
|
|
|
|
success_txs = [tx['tx'] for tx in bip112txs_vary_nSequence_v2 if not tx['sdf'] and not tx['stf']]
|
|
|
|
|
success_txs += [tx['tx'] for tx in bip112txs_vary_OP_CSV_v2 if not tx['sdf'] and not tx['stf']]
|
|
|
|
|
yield TestInstance([[self.create_test_block(success_txs), True]]) # 124
|
|
|
|
|
self.sync_blocks([self.create_test_block(success_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
# Additional test, of checking that comparison of two time types works properly
|
|
|
|
@ -479,7 +485,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
|
|
|
|
|
signtx = sign_transaction(self.nodes[0], tx)
|
|
|
|
|
time_txs.append(signtx)
|
|
|
|
|
|
|
|
|
|
yield TestInstance([[self.create_test_block(time_txs), True]])
|
|
|
|
|
self.sync_blocks([self.create_test_block(time_txs)])
|
|
|
|
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
|
|
|
|
|
|
|
|
|
# TODO: Test empty stack fails
|
|
|
|
|