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,58 @@ 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 , miniwallet , txouts , fee_rate , tx_batch_size ):
27+ for _ in range (tx_batch_size ):
28+ tx = miniwallet .create_self_transfer (from_node = self .nodes [0 ], fee_rate = fee_rate )['tx' ]
29+ for txout in txouts :
30+ tx .vout .append (txout )
31+ miniwallet .sendrawtransaction (from_node = self .nodes [0 ], tx_hex = tx .serialize ().hex ())
2532
2633 def run_test (self ):
2734 txouts = gen_return_txouts ()
35+ miniwallet = MiniWallet (self .nodes [0 ])
2836 relayfee = self .nodes [0 ].getnetworkinfo ()['relayfee' ]
2937
3038 self .log .info ('Check that mempoolminfee is minrelytxfee' )
3139 assert_equal (self .nodes [0 ].getmempoolinfo ()['minrelaytxfee' ], Decimal ('0.00001000' ))
3240 assert_equal (self .nodes [0 ].getmempoolinfo ()['mempoolminfee' ], Decimal ('0.00001000' ))
3341
34- txids = []
35- utxos = create_confirmed_utxos (self , relayfee , self .nodes [0 ], 91 )
42+ tx_batch_size = 25
43+ num_of_batches = 3
44+ # Generate UTXOs to flood the mempool
45+ # 1 to create a tx initially that will be evicted from the mempool later
46+ # 3 batches of multiple transactions with a fee rate much higher than the previous UTXO
47+ # And 1 more to verify that this tx does not get added to the mempool with a fee rate less than the mempoolminfee
48+ self .generate (miniwallet , 1 + (num_of_batches * tx_batch_size ) + 1 )
49+
50+ # Mine 99 blocks so that the UTXOs are allowed to be spent
51+ self .generate (self .nodes [0 ], COINBASE_MATURITY - 1 )
3652
3753 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' ])
54+ tx_to_be_evicted_id = miniwallet .send_self_transfer (from_node = self .nodes [0 ], fee_rate = relayfee )["txid" ]
4755
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 )
56+ # Increase the tx fee rate massively to give the subsequent transactions a higher priority in the mempool
57+ base_fee = relayfee * 1000
58+
59+ self .log .info ("Fill up the mempool with txs with higher fee rate" )
60+ for batch_of_txid in range (num_of_batches ):
61+ fee_rate = (batch_of_txid + 1 ) * base_fee
62+ self .send_large_txs (miniwallet , txouts , fee_rate , tx_batch_size )
5363
5464 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
65+ # The number of transactions created should be greater than the ones present in the mempool
66+ assert_greater_than (tx_batch_size * num_of_batches , len (self .nodes [0 ].getrawmempool ()))
67+ # Initial tx created should not be present in the mempool anymore as it had a lower fee rate
68+ assert tx_to_be_evicted_id not in self .nodes [0 ].getrawmempool ()
5869
5970 self .log .info ('Check that mempoolminfee is larger than minrelytxfee' )
6071 assert_equal (self .nodes [0 ].getmempoolinfo ()['minrelaytxfee' ], Decimal ('0.00001000' ))
6172 assert_greater_than (self .nodes [0 ].getmempoolinfo ()['mempoolminfee' ], Decimal ('0.00001000' ))
6273
74+ # 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
6375 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' ])
76+ assert_raises_rpc_error (- 26 , "mempool min fee not met" , miniwallet .send_self_transfer , from_node = self .nodes [0 ], fee_rate = relayfee , mempool_valid = False )
77+
7278
7379if __name__ == '__main__' :
7480 MempoolLimitTest ().main ()
0 commit comments