6
6
7
7
from decimal import Decimal
8
8
9
+ from test_framework .blocktools import COINBASE_MATURITY
9
10
from test_framework .test_framework import BitcoinTestFramework
10
- from test_framework .util import assert_equal , assert_greater_than , assert_raises_rpc_error , create_confirmed_utxos , create_lots_of_big_transactions , gen_return_txouts
11
+ from test_framework .util import assert_equal , assert_greater_than , assert_raises_rpc_error , gen_return_txouts
12
+ from test_framework .wallet import MiniWallet
13
+
11
14
12
15
class MempoolLimitTest (BitcoinTestFramework ):
13
16
def set_test_params (self ):
@@ -20,55 +23,59 @@ def set_test_params(self):
20
23
]]
21
24
self .supports_cli = False
22
25
23
- def skip_test_if_missing_module (self ):
24
- self .skip_if_no_wallet ()
26
+ def send_large_txs (self , node , miniwallet , txouts , fee_rate , tx_batch_size ):
27
+ for _ in range (tx_batch_size ):
28
+ tx = miniwallet .create_self_transfer (from_node = node , fee_rate = fee_rate )['tx' ]
29
+ for txout in txouts :
30
+ tx .vout .append (txout )
31
+ miniwallet .sendrawtransaction (from_node = node , tx_hex = tx .serialize ().hex ())
25
32
26
33
def run_test (self ):
27
34
txouts = gen_return_txouts ()
28
- relayfee = self .nodes [0 ].getnetworkinfo ()['relayfee' ]
35
+ node = self .nodes [0 ]
36
+ miniwallet = MiniWallet (node )
37
+ relayfee = node .getnetworkinfo ()['relayfee' ]
38
+
39
+ self .log .info ('Check that mempoolminfee is minrelaytxfee' )
40
+ assert_equal (node .getmempoolinfo ()['minrelaytxfee' ], Decimal ('0.00001000' ))
41
+ assert_equal (node .getmempoolinfo ()['mempoolminfee' ], Decimal ('0.00001000' ))
29
42
30
- self .log .info ('Check that mempoolminfee is minrelytxfee' )
31
- assert_equal (self .nodes [0 ].getmempoolinfo ()['minrelaytxfee' ], Decimal ('0.00001000' ))
32
- assert_equal (self .nodes [0 ].getmempoolinfo ()['mempoolminfee' ], Decimal ('0.00001000' ))
43
+ tx_batch_size = 25
44
+ num_of_batches = 3
45
+ # Generate UTXOs to flood the mempool
46
+ # 1 to create a tx initially that will be evicted from the mempool later
47
+ # 3 batches of multiple transactions with a fee rate much higher than the previous UTXO
48
+ # And 1 more to verify that this tx does not get added to the mempool with a fee rate less than the mempoolminfee
49
+ self .generate (miniwallet , 1 + (num_of_batches * tx_batch_size ) + 1 )
33
50
34
- txids = []
35
- utxos = create_confirmed_utxos ( self , relayfee , self . nodes [ 0 ], 91 )
51
+ # Mine 99 blocks so that the UTXOs are allowed to be spent
52
+ self . generate ( node , COINBASE_MATURITY - 1 )
36
53
37
54
self .log .info ('Create a mempool tx that will be evicted' )
38
- us0 = utxos .pop ()
39
- inputs = [{ "txid" : us0 ["txid" ], "vout" : us0 ["vout" ]}]
40
- outputs = {self .nodes [0 ].getnewaddress () : 0.0001 }
41
- tx = self .nodes [0 ].createrawtransaction (inputs , outputs )
42
- self .nodes [0 ].settxfee (relayfee ) # specifically fund this tx with low fee
43
- txF = self .nodes [0 ].fundrawtransaction (tx )
44
- self .nodes [0 ].settxfee (0 ) # return to automatic fee selection
45
- txFS = self .nodes [0 ].signrawtransactionwithwallet (txF ['hex' ])
46
- txid = self .nodes [0 ].sendrawtransaction (txFS ['hex' ])
47
-
48
- relayfee = self .nodes [0 ].getnetworkinfo ()['relayfee' ]
49
- base_fee = relayfee * 100
50
- for i in range (3 ):
51
- txids .append ([])
52
- txids [i ] = create_lots_of_big_transactions (self .nodes [0 ], txouts , utxos [30 * i :30 * i + 30 ], 30 , (i + 1 )* base_fee )
55
+ tx_to_be_evicted_id = miniwallet .send_self_transfer (from_node = node , fee_rate = relayfee )["txid" ]
56
+
57
+ # Increase the tx fee rate massively to give the subsequent transactions a higher priority in the mempool
58
+ base_fee = relayfee * 1000
59
+
60
+ self .log .info ("Fill up the mempool with txs with higher fee rate" )
61
+ for batch_of_txid in range (num_of_batches ):
62
+ fee_rate = (batch_of_txid + 1 ) * base_fee
63
+ self .send_large_txs (node , miniwallet , txouts , fee_rate , tx_batch_size )
53
64
54
65
self .log .info ('The tx should be evicted by now' )
55
- assert txid not in self .nodes [0 ].getrawmempool ()
56
- txdata = self .nodes [0 ].gettransaction (txid )
57
- assert txdata ['confirmations' ] == 0 #confirmation should still be 0
66
+ # The number of transactions created should be greater than the ones present in the mempool
67
+ assert_greater_than (tx_batch_size * num_of_batches , len (node .getrawmempool ()))
68
+ # Initial tx created should not be present in the mempool anymore as it had a lower fee rate
69
+ assert tx_to_be_evicted_id not in node .getrawmempool ()
58
70
59
- self .log .info ('Check that mempoolminfee is larger than minrelytxfee ' )
60
- assert_equal (self . nodes [ 0 ] .getmempoolinfo ()['minrelaytxfee' ], Decimal ('0.00001000' ))
61
- assert_greater_than (self . nodes [ 0 ] .getmempoolinfo ()['mempoolminfee' ], Decimal ('0.00001000' ))
71
+ self .log .info ('Check that mempoolminfee is larger than minrelaytxfee ' )
72
+ assert_equal (node .getmempoolinfo ()['minrelaytxfee' ], Decimal ('0.00001000' ))
73
+ assert_greater_than (node .getmempoolinfo ()['mempoolminfee' ], Decimal ('0.00001000' ))
62
74
75
+ # Deliberately try to create a tx with a fee less than the minimum mempool fee to assert that it does not get added to the mempool
63
76
self .log .info ('Create a mempool tx that will not pass mempoolminfee' )
64
- us0 = utxos .pop ()
65
- inputs = [{ "txid" : us0 ["txid" ], "vout" : us0 ["vout" ]}]
66
- outputs = {self .nodes [0 ].getnewaddress () : 0.0001 }
67
- tx = self .nodes [0 ].createrawtransaction (inputs , outputs )
68
- # specifically fund this tx with a fee < mempoolminfee, >= than minrelaytxfee
69
- txF = self .nodes [0 ].fundrawtransaction (tx , {'feeRate' : relayfee })
70
- txFS = self .nodes [0 ].signrawtransactionwithwallet (txF ['hex' ])
71
- assert_raises_rpc_error (- 26 , "mempool min fee not met" , self .nodes [0 ].sendrawtransaction , txFS ['hex' ])
77
+ assert_raises_rpc_error (- 26 , "mempool min fee not met" , miniwallet .send_self_transfer , from_node = node , fee_rate = relayfee , mempool_valid = False )
78
+
72
79
73
80
if __name__ == '__main__' :
74
81
MempoolLimitTest ().main ()
0 commit comments