@@ -16,6 +16,117 @@ class RPCMempoolInfoTest(BitcoinTestFramework):
1616 def set_test_params (self ):
1717 self .num_nodes = 1
1818
19+ def test_removetxfrommempool (self ):
20+ """Test for removetxfrommempool RPC functionality"""
21+ self .log .info ("Starting removetxfrommempool tests" )
22+ node = self .nodes [0 ]
23+ initial_mempool_size = len (node .getrawmempool ())
24+
25+ # Basic transaction removal
26+ tx1 = self .wallet .send_self_transfer (from_node = node )
27+ txid1 = tx1 ["txid" ]
28+ assert txid1 in node .getrawmempool ()
29+ assert_equal (len (node .getrawmempool ()), initial_mempool_size + 1 )
30+ result = node .removetxfrommempool (txid1 )
31+ assert_equal (result ["removed" ], True )
32+
33+ # Verify transaction is no longer in mempool
34+ assert txid1 not in node .getrawmempool ()
35+ assert_equal (len (node .getrawmempool ()), initial_mempool_size )
36+
37+ # Removing non-existent transaction
38+ fake_txid = "0" * 64
39+ result = node .removetxfrommempool (fake_txid )
40+ assert_equal (result ["removed" ], False )
41+
42+ # Recursive removal (parent-child transactions)
43+ # Create parent transaction
44+ parent_tx = self .wallet .send_self_transfer (from_node = node )
45+ parent_txid = parent_tx ["txid" ]
46+
47+ # Create child transaction spending from parent
48+ child_tx = self .wallet .send_self_transfer (
49+ from_node = node ,
50+ utxo_to_spend = parent_tx ["new_utxo" ]
51+ )
52+ child_txid = child_tx ["txid" ]
53+ mempool = node .getrawmempool ()
54+ assert parent_txid in mempool
55+ assert child_txid in mempool
56+ assert_equal (len (mempool ), initial_mempool_size + 2 )
57+
58+ # Remove parent transaction
59+ result = node .removetxfrommempool (parent_txid )
60+ assert_equal (result ["removed" ], True )
61+
62+ # Verify both parent and child are removed
63+ mempool = node .getrawmempool ()
64+ assert parent_txid not in mempool
65+ assert child_txid not in mempool
66+ assert_equal (len (mempool ), initial_mempool_size )
67+
68+ # Transaction chain removal
69+ # Create a chain of 3 transactions: tx1 -> tx2 -> tx3
70+ chain_tx1 = self .wallet .send_self_transfer (from_node = node )
71+ chain_tx2 = self .wallet .send_self_transfer (
72+ from_node = node ,
73+ utxo_to_spend = chain_tx1 ["new_utxo" ]
74+ )
75+ chain_tx3 = self .wallet .send_self_transfer (
76+ from_node = node ,
77+ utxo_to_spend = chain_tx2 ["new_utxo" ]
78+ )
79+
80+ # Verify all transactions are in mempool
81+ mempool = node .getrawmempool ()
82+ assert_equal (len (mempool ), initial_mempool_size + 3 )
83+ for tx in [chain_tx1 , chain_tx2 , chain_tx3 ]:
84+ assert tx ["txid" ] in mempool
85+
86+ # Remove the middle transaction (chain_tx2)
87+ result = node .removetxfrommempool (chain_tx2 ["txid" ])
88+ assert_equal (result ["removed" ], True )
89+
90+ # chain_tx2 and chain_tx3 should be removed, chain_tx1 should remain
91+ mempool = node .getrawmempool ()
92+ assert chain_tx1 ["txid" ] in mempool
93+ assert chain_tx2 ["txid" ] not in mempool
94+ assert chain_tx3 ["txid" ] not in mempool
95+ assert_equal (len (mempool ), initial_mempool_size + 1 )
96+
97+ # Test with invalid txid format
98+ assert_raises_rpc_error (- 8 , "txid must be of length 64" , node .removetxfrommempool , "invalid" )
99+
100+ # Test with wrong length hex (too short)
101+ assert_raises_rpc_error (- 8 , "txid must be of length 64" , node .removetxfrommempool , "a" * 63 )
102+
103+ # Test with wrong length hex (too long)
104+ assert_raises_rpc_error (- 8 , "txid must be of length 64" , node .removetxfrommempool , "a" * 65 )
105+
106+ # Test with no parameters
107+ assert_raises_rpc_error (- 1 , "" , node .removetxfrommempool )
108+
109+ # Test with valid hex but non-existent txid
110+ valid_but_fake_txid = "a" * 64
111+ result = node .removetxfrommempool (valid_but_fake_txid )
112+ assert_equal (result ["removed" ], False )
113+
114+ # Test removing the same transaction twice
115+ double_remove_tx = self .wallet .send_self_transfer (from_node = node )
116+ double_remove_txid = double_remove_tx ["txid" ]
117+ result1 = node .removetxfrommempool (double_remove_txid )
118+ assert_equal (result1 ["removed" ], True )
119+ result2 = node .removetxfrommempool (double_remove_txid )
120+ assert_equal (result2 ["removed" ], False )
121+
122+ # Clean up remaining transactions
123+ node .removetxfrommempool (chain_tx1 ["txid" ])
124+
125+ # Verify mempool is clean
126+ assert_equal (len (node .getrawmempool ()), initial_mempool_size )
127+
128+ self .log .info ("All removetxfrommempool tests completed successfully" )
129+
19130 def run_test (self ):
20131 self .wallet = MiniWallet (self .nodes [0 ])
21132 confirmed_utxo = self .wallet .get_utxo ()
@@ -94,6 +205,8 @@ def create_tx(**kwargs):
94205 self .log .info ("Missing txid" )
95206 assert_raises_rpc_error (- 3 , "Missing txid" , self .nodes [0 ].gettxspendingprevout , [{'vout' : 3 }])
96207
208+ self .log .info ("Test removetxfrommempool RPC" )
209+ self .test_removetxfrommempool ()
97210
98211if __name__ == '__main__' :
99212 RPCMempoolInfoTest (__file__ ).main ()
0 commit comments