16
16
from test_framework .util import (
17
17
assert_equal ,
18
18
assert_raises_rpc_error ,
19
- find_vout_for_address ,
20
19
)
20
+ from test_framework .wallet import MiniWallet
21
21
22
22
DEFAULT_MEMPOOL_EXPIRY = 336 # hours
23
23
CUSTOM_MEMPOOL_EXPIRY = 10 # hours
26
26
class MempoolExpiryTest (BitcoinTestFramework ):
27
27
def set_test_params (self ):
28
28
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
32
30
33
31
def test_transaction_expiry (self , timeout ):
34
32
"""Tests that a transaction expires after the expiry timeout and its
35
33
children are removed as well."""
36
34
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 )
37
40
38
41
# 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 ()
41
50
42
51
# Set the mocktime to the arrival time of the parent transaction.
43
52
entry_time = node .getmempoolentry (parent_txid )['time' ]
44
53
node .setmocktime (entry_time )
45
54
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.
54
56
half_expiry_time = entry_time + int (60 * 60 * timeout / 2 )
55
57
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 ])
57
60
self .log .info ('Broadcast child transaction after {} hours.' .format (
58
61
timedelta (seconds = (half_expiry_time - entry_time ))))
59
62
63
+ # Broadcast another (independent) transaction.
64
+ independent_txid = self .wallet .send_self_transfer (from_node = node , utxo_to_spend = independent_utxo )['txid' ]
65
+
60
66
# Let most of the timeout elapse and check that the parent tx is still
61
67
# in the mempool.
62
68
nearly_expiry_time = entry_time + 60 * 60 * timeout - 5
63
69
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 )
67
73
self .log .info ('Test parent tx not expired after {} hours.' .format (
68
74
timedelta (seconds = (nearly_expiry_time - entry_time ))))
69
75
assert_equal (entry_time , node .getmempoolentry (parent_txid )['time' ])
@@ -72,9 +78,8 @@ def test_transaction_expiry(self, timeout):
72
78
# has passed.
73
79
expiry_time = entry_time + 60 * 60 * timeout + 5
74
80
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 )
78
83
self .log .info ('Test parent tx expiry after {} hours.' .format (
79
84
timedelta (seconds = (expiry_time - entry_time ))))
80
85
assert_raises_rpc_error (- 5 , 'Transaction not in mempool' ,
@@ -85,6 +90,11 @@ def test_transaction_expiry(self, timeout):
85
90
assert_raises_rpc_error (- 5 , 'Transaction not in mempool' ,
86
91
node .getmempoolentry , child_txid )
87
92
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
+
88
98
def run_test (self ):
89
99
self .log .info ('Test default mempool expiry timeout of %d hours.' %
90
100
DEFAULT_MEMPOOL_EXPIRY )
0 commit comments