Changeset View
Changeset View
Standalone View
Standalone View
test/functional/bip68-sequence.py
Show All 20 Lines | |||||
# 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): | ||||
self.num_nodes = 2 | self.num_nodes = 2 | ||||
self.extra_args = [["-blockprioritypercentage=0", "-noparkdeepreorg", "-maxreorgdepth=-1", "-deprecatedrpc=signrawtransaction"], | self.extra_args = [["-blockprioritypercentage=0", "-noparkdeepreorg", "-maxreorgdepth=-1"], | ||||
["-blockprioritypercentage=0", "-acceptnonstdtxn=0", "-maxreorgdepth=-1", "-deprecatedrpc=signrawtransaction"]] | ["-blockprioritypercentage=0", "-acceptnonstdtxn=0", "-maxreorgdepth=-1"]] | ||||
def run_test(self): | def run_test(self): | ||||
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] | self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] | ||||
# Generate some coins | # Generate some coins | ||||
self.nodes[0].generate(110) | self.nodes[0].generate(110) | ||||
self.log.info("Running test disable flag") | self.log.info("Running test disable flag") | ||||
Show All 39 Lines | def test_disable_flag(self): | ||||
# If sequence locks were used, this would require 1 block for the | # If sequence locks were used, this would require 1 block for the | ||||
# input to mature. | # input to mature. | ||||
sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1 | sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1 | ||||
tx1.vin = [ | tx1.vin = [ | ||||
CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)] | CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)] | ||||
tx1.vout = [CTxOut(value, CScript([b'a']))] | tx1.vout = [CTxOut(value, CScript([b'a']))] | ||||
pad_tx(tx1) | pad_tx(tx1) | ||||
tx1_signed = self.nodes[0].signrawtransaction(ToHex(tx1))["hex"] | tx1_signed = self.nodes[0].signrawtransactionwithwallet(ToHex(tx1))[ | ||||
"hex"] | |||||
tx1_id = self.nodes[0].sendrawtransaction(tx1_signed) | tx1_id = self.nodes[0].sendrawtransaction(tx1_signed) | ||||
tx1_id = int(tx1_id, 16) | tx1_id = int(tx1_id, 16) | ||||
# This transaction will enable sequence-locks, so this transaction should | # This transaction will enable sequence-locks, so this transaction should | ||||
# fail | # fail | ||||
tx2 = CTransaction() | tx2 = CTransaction() | ||||
tx2.nVersion = 2 | tx2.nVersion = 2 | ||||
sequence_value = sequence_value & 0x7fffffff | sequence_value = sequence_value & 0x7fffffff | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | def test_sequence_lock_confirmed_inputs(self): | ||||
tx.vin.append( | tx.vin.append( | ||||
CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value)) | CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value)) | ||||
value += utxos[j]["amount"] * COIN | value += utxos[j]["amount"] * COIN | ||||
# Overestimate the size of the tx - signatures should be less than | # Overestimate the size of the tx - signatures should be less than | ||||
# 120 bytes, and leave 50 for the output | # 120 bytes, and leave 50 for the output | ||||
tx_size = len(ToHex(tx)) // 2 + 120 * num_inputs + 50 | tx_size = len(ToHex(tx)) // 2 + 120 * num_inputs + 50 | ||||
tx.vout.append( | tx.vout.append( | ||||
CTxOut(int(value - self.relayfee * tx_size * COIN / 1000), CScript([b'a']))) | CTxOut(int(value - self.relayfee * tx_size * COIN / 1000), CScript([b'a']))) | ||||
rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"] | rawtx = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))[ | ||||
"hex"] | |||||
if (using_sequence_locks and not should_pass): | if (using_sequence_locks and not should_pass): | ||||
# This transaction should be rejected | # This transaction should be rejected | ||||
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, | assert_raises_rpc_error(-26, NOT_FINAL_ERROR, | ||||
self.nodes[0].sendrawtransaction, rawtx) | self.nodes[0].sendrawtransaction, rawtx) | ||||
else: | else: | ||||
# This raw transaction should be accepted | # This raw transaction should be accepted | ||||
self.nodes[0].sendrawtransaction(rawtx) | self.nodes[0].sendrawtransaction(rawtx) | ||||
Show All 23 Lines | def test_sequence_lock_unconfirmed_inputs(self): | ||||
# Sequence lock of 0 should pass. | # Sequence lock of 0 should pass. | ||||
tx2 = CTransaction() | tx2 = CTransaction() | ||||
tx2.nVersion = 2 | tx2.nVersion = 2 | ||||
tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] | tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] | ||||
tx2.vout = [ | tx2.vout = [ | ||||
CTxOut(int(0), CScript([b'a']))] | CTxOut(int(0), CScript([b'a']))] | ||||
tx2.vout[0].nValue = tx1.vout[0].nValue - \ | tx2.vout[0].nValue = tx1.vout[0].nValue - \ | ||||
fee_multiplier * self.nodes[0].calculate_fee(tx2) | fee_multiplier * self.nodes[0].calculate_fee(tx2) | ||||
tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"] | tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"] | ||||
tx2 = FromHex(tx2, tx2_raw) | tx2 = FromHex(tx2, tx2_raw) | ||||
tx2.rehash() | tx2.rehash() | ||||
self.nodes[0].sendrawtransaction(tx2_raw) | self.nodes[0].sendrawtransaction(tx2_raw) | ||||
# Create a spend of the 0th output of orig_tx with a sequence lock | # Create a spend of the 0th output of orig_tx with a sequence lock | ||||
# of 1, and test what happens when submitting. | # of 1, and test what happens when submitting. | ||||
# orig_tx.vout[0] must be an anyone-can-spend output | # orig_tx.vout[0] must be an anyone-can-spend output | ||||
def test_nonzero_locks(orig_tx, node, use_height_lock): | def test_nonzero_locks(orig_tx, node, use_height_lock): | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | def test_sequence_lock_unconfirmed_inputs(self): | ||||
tx5 = test_nonzero_locks( | tx5 = test_nonzero_locks( | ||||
tx4, self.nodes[0], use_height_lock=True) | tx4, self.nodes[0], use_height_lock=True) | ||||
assert(tx5.hash not in self.nodes[0].getrawmempool()) | assert(tx5.hash not in self.nodes[0].getrawmempool()) | ||||
utxos = self.nodes[0].listunspent() | utxos = self.nodes[0].listunspent() | ||||
tx5.vin.append( | tx5.vin.append( | ||||
CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1)) | CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1)) | ||||
tx5.vout[0].nValue += int(utxos[0]["amount"] * COIN) | tx5.vout[0].nValue += int(utxos[0]["amount"] * COIN) | ||||
raw_tx5 = self.nodes[0].signrawtransaction(ToHex(tx5))["hex"] | raw_tx5 = self.nodes[0].signrawtransactionwithwallet(ToHex(tx5))["hex"] | ||||
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, | assert_raises_rpc_error(-26, NOT_FINAL_ERROR, | ||||
self.nodes[0].sendrawtransaction, raw_tx5) | self.nodes[0].sendrawtransaction, raw_tx5) | ||||
# Test mempool-BIP68 consistency after reorg | # Test mempool-BIP68 consistency after reorg | ||||
# | # | ||||
# State of the transactions in the last blocks: | # State of the transactions in the last blocks: | ||||
# ... -> [ tx2 ] -> [ tx3 ] | # ... -> [ tx2 ] -> [ tx3 ] | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | def test_bip68_not_consensus(self): | ||||
# Make an anyone-can-spend transaction | # Make an anyone-can-spend transaction | ||||
tx2 = CTransaction() | tx2 = CTransaction() | ||||
tx2.nVersion = 1 | tx2.nVersion = 1 | ||||
tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] | tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] | ||||
tx2.vout = [ | tx2.vout = [ | ||||
CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))] | CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))] | ||||
# sign tx2 | # sign tx2 | ||||
tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"] | tx2_raw = self.nodes[0].signrawtransactionwithwallet(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 | sequence_value = 100 # 100 block relative locktime | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | class BIP68Test(BitcoinTestFramework): | ||||
# Use self.nodes[1] to test standardness relay policy | # Use self.nodes[1] to test standardness relay policy | ||||
def test_version2_relay(self, before_activation): | def test_version2_relay(self, before_activation): | ||||
inputs = [] | inputs = [] | ||||
outputs = {self.nodes[1].getnewaddress(): 1.0} | outputs = {self.nodes[1].getnewaddress(): 1.0} | ||||
rawtx = self.nodes[1].createrawtransaction(inputs, outputs) | rawtx = self.nodes[1].createrawtransaction(inputs, outputs) | ||||
rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex'] | rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex'] | ||||
tx = FromHex(CTransaction(), rawtxfund) | tx = FromHex(CTransaction(), rawtxfund) | ||||
tx.nVersion = 2 | tx.nVersion = 2 | ||||
tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"] | tx_signed = self.nodes[1].signrawtransactionwithwallet(ToHex(tx))[ | ||||
"hex"] | |||||
try: | try: | ||||
tx_id = self.nodes[1].sendrawtransaction(tx_signed) | tx_id = self.nodes[1].sendrawtransaction(tx_signed) | ||||
assert(before_activation == False) | assert(before_activation == False) | ||||
except: | except: | ||||
assert(before_activation) | assert(before_activation) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
BIP68Test().main() | BIP68Test().main() |