Changeset View
Changeset View
Standalone View
Standalone View
test/functional/feature_bip68_sequence.py
Show All 30 Lines | from test_framework.util import ( | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
connect_nodes, | connect_nodes, | ||||
disconnect_nodes, | disconnect_nodes, | ||||
satoshi_round, | satoshi_round, | ||||
sync_blocks, | sync_blocks, | ||||
) | ) | ||||
SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31) | SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31) | ||||
SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22) # this means use time (0 means height) | # this means use time (0 means height) | ||||
SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift | SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22) | ||||
# this is a bit-shift | |||||
SEQUENCE_LOCKTIME_GRANULARITY = 9 | |||||
SEQUENCE_LOCKTIME_MASK = 0x0000ffff | SEQUENCE_LOCKTIME_MASK = 0x0000ffff | ||||
# RPC error for non-BIP68 final transactions | # RPC error for non-BIP68 final transactions | ||||
NOT_FINAL_ERROR = "64: non-BIP68-final" | NOT_FINAL_ERROR = "64: non-BIP68-final" | ||||
class BIP68Test(BitcoinTestFramework): | class BIP68Test(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
Show All 31 Lines | def run_test(self): | ||||
self.log.info("Passed") | self.log.info("Passed") | ||||
# Test that BIP68 is not in effect if tx version is 1, or if | # Test that BIP68 is not in effect if tx version is 1, or if | ||||
# the first sequence bit is set. | # the first sequence bit is set. | ||||
def test_disable_flag(self): | def test_disable_flag(self): | ||||
# Create some unconfirmed inputs | # Create some unconfirmed inputs | ||||
new_addr = self.nodes[0].getnewaddress() | new_addr = self.nodes[0].getnewaddress() | ||||
self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC | # send 2 BCH | ||||
self.nodes[0].sendtoaddress(new_addr, 2) | |||||
utxos = self.nodes[0].listunspent(0, 0) | utxos = self.nodes[0].listunspent(0, 0) | ||||
assert(len(utxos) > 0) | assert(len(utxos) > 0) | ||||
utxo = utxos[0] | utxo = utxos[0] | ||||
tx1 = CTransaction() | tx1 = CTransaction() | ||||
value = int(satoshi_round(utxo["amount"] - self.relayfee) * COIN) | value = int(satoshi_round(utxo["amount"] - self.relayfee) * COIN) | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | def test_sequence_lock_confirmed_inputs(self): | ||||
# Track whether this transaction was built with sequence locks | # Track whether this transaction was built with sequence locks | ||||
using_sequence_locks = False | using_sequence_locks = False | ||||
tx = CTransaction() | tx = CTransaction() | ||||
tx.nVersion = 2 | tx.nVersion = 2 | ||||
value = 0 | value = 0 | ||||
for j in range(num_inputs): | for j in range(num_inputs): | ||||
sequence_value = 0xfffffffe # this disables sequence locks | # this disables sequence locks | ||||
sequence_value = 0xfffffffe | |||||
# 50% chance we enable sequence locks | # 50% chance we enable sequence locks | ||||
if random.randint(0, 1): | if random.randint(0, 1): | ||||
using_sequence_locks = True | using_sequence_locks = True | ||||
# 10% of the time, make the input sequence value pass | # 10% of the time, make the input sequence value pass | ||||
input_will_pass = (random.randint(1, 10) == 1) | input_will_pass = (random.randint(1, 10) == 1) | ||||
sequence_value = utxos[j]["confirmations"] | sequence_value = utxos[j]["confirmations"] | ||||
if not input_will_pass: | if not input_will_pass: | ||||
sequence_value += 1 | sequence_value += 1 | ||||
should_pass = False | should_pass = False | ||||
# Figure out what the median-time-past was for the confirmed input | # Figure out what the median-time-past was for the confirmed input | ||||
# Note that if an input has N confirmations, we're going back N blocks | # Note that if an input has N confirmations, we're going back N blocks | ||||
# from the tip so that we're looking up MTP of the block | # from the tip so that we're looking up MTP of the block | ||||
# PRIOR to the one the input appears in, as per the BIP68 | # PRIOR to the one the input appears in, as per the BIP68 | ||||
# spec. | # spec. | ||||
orig_time = self.get_median_time_past( | orig_time = self.get_median_time_past( | ||||
utxos[j]["confirmations"]) | utxos[j]["confirmations"]) | ||||
cur_time = self.get_median_time_past(0) # MTP of the tip | # MTP of the tip | ||||
cur_time = self.get_median_time_past(0) | |||||
# can only timelock this input if it's not too old -- | # can only timelock this input if it's not too old -- | ||||
# otherwise use height | # otherwise use height | ||||
can_time_lock = True | can_time_lock = True | ||||
if ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) >= SEQUENCE_LOCKTIME_MASK: | if ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) >= SEQUENCE_LOCKTIME_MASK: | ||||
can_time_lock = False | can_time_lock = False | ||||
# if time-lockable, then 50% chance we make this a time | # if time-lockable, then 50% chance we make this a time | ||||
▲ Show 20 Lines • Show All 217 Lines • ▼ Show 20 Lines | def test_bip68_not_consensus(self): | ||||
tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"] | tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"] | ||||
tx2 = FromHex(tx2, tx2_raw) | tx2 = FromHex(tx2, tx2_raw) | ||||
pad_tx(tx2) | pad_tx(tx2) | ||||
tx2.rehash() | tx2.rehash() | ||||
self.nodes[0].sendrawtransaction(ToHex(tx2)) | self.nodes[0].sendrawtransaction(ToHex(tx2)) | ||||
# Now make an invalid spend of tx2 according to BIP68 | # Now make an invalid spend of tx2 according to BIP68 | ||||
sequence_value = 100 # 100 block relative locktime | # 100 block relative locktime | ||||
sequence_value = 100 | |||||
tx3 = CTransaction() | tx3 = CTransaction() | ||||
tx3.nVersion = 2 | tx3.nVersion = 2 | ||||
tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)] | tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)] | ||||
tx3.vout = [ | tx3.vout = [ | ||||
CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))] | CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))] | ||||
pad_tx(tx3) | pad_tx(tx3) | ||||
tx3.rehash() | tx3.rehash() | ||||
▲ Show 20 Lines • Show All 52 Lines • Show Last 20 Lines |