22# Copyright (c) 2024 The Bitcoin Core developers
33# Distributed under the MIT software license, see the accompanying
44# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+ from decimal import Decimal
56
67from test_framework .messages import (
78 MAX_BIP125_RBF_SEQUENCE ,
@@ -397,6 +398,37 @@ def test_v3_in_testmempoolaccept(self):
397398 test_accept_2children_with_in_mempool_parent = node .testmempoolaccept ([tx_v3_child_1 ["hex" ], tx_v3_child_2 ["hex" ]])
398399 assert all ([result ["package-error" ] == expected_error_extra for result in test_accept_2children_with_in_mempool_parent ])
399400
401+ @cleanup (extra_args = ["-acceptnonstdtxn=1" ])
402+ def test_reorg_2child_rbf (self ):
403+ node = self .nodes [0 ]
404+ self .log .info ("Test that children of a v3 transaction can be replaced individually, even if there are multiple due to reorg" )
405+
406+ ancestor_tx = self .wallet .send_self_transfer_multi (from_node = node , num_outputs = 2 , version = 3 )
407+ self .check_mempool ([ancestor_tx ["txid" ]])
408+
409+ block = self .generate (node , 1 )[0 ]
410+ self .check_mempool ([])
411+
412+ child_1 = self .wallet .send_self_transfer (from_node = node , version = 3 , utxo_to_spend = ancestor_tx ["new_utxos" ][0 ])
413+ child_2 = self .wallet .send_self_transfer (from_node = node , version = 3 , utxo_to_spend = ancestor_tx ["new_utxos" ][1 ])
414+ self .check_mempool ([child_1 ["txid" ], child_2 ["txid" ]])
415+
416+ self .generate (node , 1 )
417+ self .check_mempool ([])
418+
419+ # Create a reorg, causing ancestor_tx to exceed the 1-child limit
420+ node .invalidateblock (block )
421+ self .check_mempool ([ancestor_tx ["txid" ], child_1 ["txid" ], child_2 ["txid" ]])
422+ assert_equal (node .getmempoolentry (ancestor_tx ["txid" ])["descendantcount" ], 3 )
423+
424+ # Create a replacement of child_1. It does not conflict with child_2.
425+ child_1_conflict = self .wallet .send_self_transfer (from_node = node , version = 3 , utxo_to_spend = ancestor_tx ["new_utxos" ][0 ], fee_rate = Decimal ("0.01" ))
426+
427+ # Ensure child_1 and child_1_conflict are different transactions
428+ assert (child_1_conflict ["txid" ] != child_1 ["txid" ])
429+ self .check_mempool ([ancestor_tx ["txid" ], child_1_conflict ["txid" ], child_2 ["txid" ]])
430+ assert_equal (node .getmempoolentry (ancestor_tx ["txid" ])["descendantcount" ], 3 )
431+
400432 def run_test (self ):
401433 self .log .info ("Generate blocks to create UTXOs" )
402434 node = self .nodes [0 ]
@@ -412,6 +444,7 @@ def run_test(self):
412444 self .test_mempool_sibling ()
413445 self .test_v3_package_inheritance ()
414446 self .test_v3_in_testmempoolaccept ()
447+ self .test_reorg_2child_rbf ()
415448
416449
417450if __name__ == "__main__" :
0 commit comments