Skip to content

Commit 3b064fc

Browse files
committed
test: run mempool_expiry.py even with wallet disabled
Test coverage is also extended in this commit to: Ensure that another transaction in the mempool is not evicted when other transactions expire. Note: this other transaction does not have any ancestors in the mempool that expired. Otherwise it would be evicted from the mempool, and we already test this case.
1 parent 854b36c commit 3b064fc

File tree

1 file changed

+31
-21
lines changed

1 file changed

+31
-21
lines changed

test/functional/mempool_expiry.py

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
from test_framework.util import (
1717
assert_equal,
1818
assert_raises_rpc_error,
19-
find_vout_for_address,
2019
)
20+
from test_framework.wallet import MiniWallet
2121

2222
DEFAULT_MEMPOOL_EXPIRY = 336 # hours
2323
CUSTOM_MEMPOOL_EXPIRY = 10 # hours
@@ -26,44 +26,50 @@
2626
class MempoolExpiryTest(BitcoinTestFramework):
2727
def set_test_params(self):
2828
self.num_nodes = 1
29-
30-
def skip_test_if_missing_module(self):
31-
self.skip_if_no_wallet()
29+
self.setup_clean_chain = True
3230

3331
def test_transaction_expiry(self, timeout):
3432
"""Tests that a transaction expires after the expiry timeout and its
3533
children are removed as well."""
3634
node = self.nodes[0]
35+
self.wallet = MiniWallet(node)
36+
37+
# Add enough mature utxos to the wallet so that all txs spend confirmed coins.
38+
self.wallet.generate(4)
39+
node.generate(100)
3740

3841
# Send a parent transaction that will expire.
39-
parent_address = node.getnewaddress()
40-
parent_txid = node.sendtoaddress(parent_address, 1.0)
42+
parent_txid = self.wallet.send_self_transfer(from_node=node)['txid']
43+
parent_utxo = self.wallet.get_utxo(txid=parent_txid)
44+
independent_utxo = self.wallet.get_utxo()
45+
46+
# Ensure the transactions we send to trigger the mempool check spend utxos that are independent of
47+
# the transactions being tested for expiration.
48+
trigger_utxo1 = self.wallet.get_utxo()
49+
trigger_utxo2 = self.wallet.get_utxo()
4150

4251
# Set the mocktime to the arrival time of the parent transaction.
4352
entry_time = node.getmempoolentry(parent_txid)['time']
4453
node.setmocktime(entry_time)
4554

46-
# Create child transaction spending the parent transaction
47-
vout = find_vout_for_address(node, parent_txid, parent_address)
48-
inputs = [{'txid': parent_txid, 'vout': vout}]
49-
outputs = {node.getnewaddress(): 0.99}
50-
child_raw = node.createrawtransaction(inputs, outputs)
51-
child_signed = node.signrawtransactionwithwallet(child_raw)['hex']
52-
53-
# Let half of the timeout elapse and broadcast the child transaction.
55+
# Let half of the timeout elapse and broadcast the child transaction spending the parent transaction.
5456
half_expiry_time = entry_time + int(60 * 60 * timeout/2)
5557
node.setmocktime(half_expiry_time)
56-
child_txid = node.sendrawtransaction(child_signed)
58+
child_txid = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=parent_utxo)['txid']
59+
assert_equal(parent_txid, node.getmempoolentry(child_txid)['depends'][0])
5760
self.log.info('Broadcast child transaction after {} hours.'.format(
5861
timedelta(seconds=(half_expiry_time-entry_time))))
5962

63+
# Broadcast another (independent) transaction.
64+
independent_txid = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=independent_utxo)['txid']
65+
6066
# Let most of the timeout elapse and check that the parent tx is still
6167
# in the mempool.
6268
nearly_expiry_time = entry_time + 60 * 60 * timeout - 5
6369
node.setmocktime(nearly_expiry_time)
64-
# Expiry of mempool transactions is only checked when a new transaction
65-
# is added to the to the mempool.
66-
node.sendtoaddress(node.getnewaddress(), 1.0)
70+
# Broadcast a transaction as the expiry of transactions in the mempool is only checked
71+
# when a new transaction is added to the mempool.
72+
self.wallet.send_self_transfer(from_node=node, utxo_to_spend=trigger_utxo1)
6773
self.log.info('Test parent tx not expired after {} hours.'.format(
6874
timedelta(seconds=(nearly_expiry_time-entry_time))))
6975
assert_equal(entry_time, node.getmempoolentry(parent_txid)['time'])
@@ -72,9 +78,8 @@ def test_transaction_expiry(self, timeout):
7278
# has passed.
7379
expiry_time = entry_time + 60 * 60 * timeout + 5
7480
node.setmocktime(expiry_time)
75-
# Expiry of mempool transactions is only checked when a new transaction
76-
# is added to the to the mempool.
77-
node.sendtoaddress(node.getnewaddress(), 1.0)
81+
# Again, broadcast a transaction so the expiry of transactions in the mempool is checked.
82+
self.wallet.send_self_transfer(from_node=node, utxo_to_spend=trigger_utxo2)
7883
self.log.info('Test parent tx expiry after {} hours.'.format(
7984
timedelta(seconds=(expiry_time-entry_time))))
8085
assert_raises_rpc_error(-5, 'Transaction not in mempool',
@@ -85,6 +90,11 @@ def test_transaction_expiry(self, timeout):
8590
assert_raises_rpc_error(-5, 'Transaction not in mempool',
8691
node.getmempoolentry, child_txid)
8792

93+
# Check that the independent tx is still in the mempool.
94+
self.log.info('Test the independent tx not expired after {} hours.'.format(
95+
timedelta(seconds=(expiry_time-half_expiry_time))))
96+
assert_equal(half_expiry_time, node.getmempoolentry(independent_txid)['time'])
97+
8898
def run_test(self):
8999
self.log.info('Test default mempool expiry timeout of %d hours.' %
90100
DEFAULT_MEMPOOL_EXPIRY)

0 commit comments

Comments
 (0)