66
77from decimal import Decimal
88
9+ from test_framework .blocktools import COINBASE_MATURITY
910from 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+
1114
1215class MempoolLimitTest (BitcoinTestFramework ):
1316 def set_test_params (self ):
@@ -20,55 +23,59 @@ def set_test_params(self):
2023 ]]
2124 self .supports_cli = False
2225
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 ())
2532
2633 def run_test (self ):
2734 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' ))
2942
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 )
3350
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 )
3653
3754 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 )
5364
5465 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 ()
5870
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' ))
6274
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
6376 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+
7279
7380if __name__ == '__main__' :
7481 MempoolLimitTest ().main ()
0 commit comments