Changeset View
Changeset View
Standalone View
Standalone View
test/functional/bip68-sequence.py
Show First 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | def test_sequence_lock_unconfirmed_inputs(self): | ||||
# Store height so we can easily reset the chain at the end of the test | # Store height so we can easily reset the chain at the end of the test | ||||
cur_height = self.nodes[0].getblockcount() | cur_height = self.nodes[0].getblockcount() | ||||
# Create a mempool tx. | # Create a mempool tx. | ||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2) | txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2) | ||||
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid)) | tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid)) | ||||
tx1.rehash() | tx1.rehash() | ||||
# As the fees are calculated prior to the transaction being signed, | |||||
# there is some uncertainty that calculate fee provides the correct | |||||
# minimal fee. Since regtest coins are free, let's go ahead and | |||||
# increase the fee by an order of magnitude to ensure this test | |||||
# passes. | |||||
fee_multiplier = 10 | |||||
# Anyone-can-spend mempool tx. | # Anyone-can-spend mempool tx. | ||||
# 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(tx1.vout[0].nValue - self.relayfee * COIN), CScript([b'a']))] | CTxOut(int(0), CScript([b'a']))] | ||||
tx2.vout[0].nValue = tx1.vout[0].nValue - \ | |||||
fee_multiplier * self.nodes[0].calculate_fee(tx2) | |||||
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) | ||||
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, relayfee, use_height_lock): | def test_nonzero_locks(orig_tx, node, use_height_lock): | ||||
sequence_value = 1 | sequence_value = 1 | ||||
if not use_height_lock: | if not use_height_lock: | ||||
sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG | sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG | ||||
tx = CTransaction() | tx = CTransaction() | ||||
tx.nVersion = 2 | tx.nVersion = 2 | ||||
tx.vin = [ | tx.vin = [ | ||||
CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)] | CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)] | ||||
tx.vout = [ | tx.vout = [ | ||||
CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), CScript([b'a']))] | CTxOut(int(orig_tx.vout[0].nValue - fee_multiplier * node.calculate_fee(tx)), CScript([b'a']))] | ||||
tx.rehash() | tx.rehash() | ||||
if (orig_tx.hash in node.getrawmempool()): | if (orig_tx.hash in node.getrawmempool()): | ||||
# sendrawtransaction should fail if the tx is in the mempool | # sendrawtransaction should fail if the tx is in the mempool | ||||
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, | assert_raises_rpc_error(-26, NOT_FINAL_ERROR, | ||||
node.sendrawtransaction, ToHex(tx)) | node.sendrawtransaction, ToHex(tx)) | ||||
else: | else: | ||||
# sendrawtransaction should succeed if the tx is not in the mempool | # sendrawtransaction should succeed if the tx is not in the mempool | ||||
node.sendrawtransaction(ToHex(tx)) | node.sendrawtransaction(ToHex(tx)) | ||||
return tx | return tx | ||||
test_nonzero_locks( | test_nonzero_locks( | ||||
tx2, self.nodes[0], self.relayfee, use_height_lock=True) | tx2, self.nodes[0], use_height_lock=True) | ||||
test_nonzero_locks( | test_nonzero_locks( | ||||
tx2, self.nodes[0], self.relayfee, use_height_lock=False) | tx2, self.nodes[0], use_height_lock=False) | ||||
# Now mine some blocks, but make sure tx2 doesn't get mined. | # Now mine some blocks, but make sure tx2 doesn't get mined. | ||||
# Use prioritisetransaction to lower the effective feerate to 0 | # Use prioritisetransaction to lower the effective feerate to 0 | ||||
self.nodes[0].prioritisetransaction( | self.nodes[0].prioritisetransaction( | ||||
tx2.hash, -1e15, int(-self.relayfee * COIN)) | tx2.hash, -1e15, -fee_multiplier * self.nodes[0].calculate_fee(tx2)) | ||||
cur_time = int(time.time()) | cur_time = int(time.time()) | ||||
for i in range(10): | for i in range(10): | ||||
self.nodes[0].setmocktime(cur_time + 600) | self.nodes[0].setmocktime(cur_time + 600) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
cur_time += 600 | cur_time += 600 | ||||
assert(tx2.hash in self.nodes[0].getrawmempool()) | assert(tx2.hash in self.nodes[0].getrawmempool()) | ||||
test_nonzero_locks( | test_nonzero_locks( | ||||
tx2, self.nodes[0], self.relayfee, use_height_lock=True) | tx2, self.nodes[0], use_height_lock=True) | ||||
test_nonzero_locks( | test_nonzero_locks( | ||||
tx2, self.nodes[0], self.relayfee, use_height_lock=False) | tx2, self.nodes[0], use_height_lock=False) | ||||
# Mine tx2, and then try again | # Mine tx2, and then try again | ||||
self.nodes[0].prioritisetransaction( | self.nodes[0].prioritisetransaction( | ||||
tx2.hash, 1e15, self.nodes[0].calculate_fee(tx2)) | tx2.hash, 1e15, fee_multiplier * self.nodes[0].calculate_fee(tx2)) | ||||
# Advance the time on the node so that we can test timelocks | # Advance the time on the node so that we can test timelocks | ||||
self.nodes[0].setmocktime(cur_time + 600) | self.nodes[0].setmocktime(cur_time + 600) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
assert(tx2.hash not in self.nodes[0].getrawmempool()) | assert(tx2.hash not in self.nodes[0].getrawmempool()) | ||||
# Now that tx2 is not in the mempool, a sequence locked spend should | # Now that tx2 is not in the mempool, a sequence locked spend should | ||||
# succeed | # succeed | ||||
tx3 = test_nonzero_locks( | tx3 = test_nonzero_locks( | ||||
tx2, self.nodes[0], self.relayfee, use_height_lock=False) | tx2, self.nodes[0], use_height_lock=False) | ||||
assert(tx3.hash in self.nodes[0].getrawmempool()) | assert(tx3.hash in self.nodes[0].getrawmempool()) | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
assert(tx3.hash not in self.nodes[0].getrawmempool()) | assert(tx3.hash not in self.nodes[0].getrawmempool()) | ||||
# One more test, this time using height locks | # One more test, this time using height locks | ||||
tx4 = test_nonzero_locks( | tx4 = test_nonzero_locks( | ||||
tx3, self.nodes[0], self.relayfee, use_height_lock=True) | tx3, self.nodes[0], use_height_lock=True) | ||||
assert(tx4.hash in self.nodes[0].getrawmempool()) | assert(tx4.hash in self.nodes[0].getrawmempool()) | ||||
# Now try combining confirmed and unconfirmed inputs | # Now try combining confirmed and unconfirmed inputs | ||||
tx5 = test_nonzero_locks( | tx5 = test_nonzero_locks( | ||||
tx4, self.nodes[0], self.relayfee, 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].signrawtransaction(ToHex(tx5))["hex"] | ||||
▲ Show 20 Lines • Show All 133 Lines • Show Last 20 Lines |