@@ -20,10 +20,11 @@ use common::{
20
20
bump_fee_and_broadcast, distribute_funds_unconfirmed, do_channel_full_cycle,
21
21
expect_channel_pending_event, expect_channel_ready_event, expect_event,
22
22
expect_payment_claimable_event, expect_payment_received_event, expect_payment_successful_event,
23
- generate_blocks_and_wait, new_node, open_channel, open_channel_push_amt,
24
- premine_and_distribute_funds, premine_blocks, prepare_rbf, random_config,
25
- random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node,
26
- setup_node_for_async_payments, setup_two_nodes, wait_for_tx, TestChainSource , TestSyncStore ,
23
+ generate_block_and_insert_transactions, generate_blocks_and_wait, new_node, open_channel,
24
+ open_channel_push_amt, premine_and_distribute_funds, premine_blocks, prepare_rbf,
25
+ random_config, random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder,
26
+ setup_node, setup_node_for_async_payments, setup_two_nodes, wait_for_tx, TestChainSource ,
27
+ TestSyncStore ,
27
28
} ;
28
29
use ldk_node:: config:: { AsyncPaymentsRole , EsploraSyncConfig } ;
29
30
use ldk_node:: liquidity:: LSPS2ServiceConfig ;
@@ -669,19 +670,24 @@ fn onchain_wallet_recovery() {
669
670
}
670
671
671
672
#[ test]
672
- fn test_rbf_via_mempool ( ) {
673
- run_rbf_test ( false ) ;
673
+ fn test_rbf_only_in_mempool ( ) {
674
+ run_rbf_test ( false , false ) ;
674
675
}
675
676
676
677
#[ test]
677
- fn test_rbf_via_direct_block_insertion ( ) {
678
- run_rbf_test ( true ) ;
678
+ fn test_rbf_direct_block_insertion_rbf_tx ( ) {
679
+ run_rbf_test ( true , false ) ;
680
+ }
681
+
682
+ #[ test]
683
+ fn test_rbf_direct_block_insertion_original_tx ( ) {
684
+ run_rbf_test ( false , true ) ;
679
685
}
680
686
681
687
// `is_insert_block`:
682
688
// - `true`: transaction is mined immediately (no mempool), testing confirmed-Tx handling.
683
689
// - `false`: transaction stays in mempool until confirmation, testing unconfirmed-Tx handling.
684
- fn run_rbf_test ( is_insert_block : bool ) {
690
+ fn run_rbf_test ( is_insert_block : bool , is_insertion_original_tx : bool ) {
685
691
let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
686
692
let chain_source_bitcoind = TestChainSource :: BitcoindRpcSync ( & bitcoind) ;
687
693
let chain_source_electrsd = TestChainSource :: Electrum ( & electrsd) ;
@@ -724,58 +730,98 @@ fn run_rbf_test(is_insert_block: bool) {
724
730
} ;
725
731
}
726
732
733
+ macro_rules! validate_total_onchain_balance {
734
+ ( $expected_balance_sat: expr) => {
735
+ for node in & nodes {
736
+ node. sync_wallets( ) . unwrap( ) ;
737
+ let balances = node. list_balances( ) ;
738
+ assert_eq!( balances. total_onchain_balance_sats, $expected_balance_sat) ;
739
+ }
740
+ } ;
741
+ }
742
+
727
743
let scripts_buf: HashSet < ScriptBuf > =
728
744
all_addrs. iter ( ) . map ( |addr| addr. script_pubkey ( ) ) . collect ( ) ;
729
745
let mut tx;
730
746
let mut fee_output_index;
731
747
732
- // Modify the output to the nodes
748
+ let mut final_amount_sat = 0 ;
749
+ let mut original_tx;
750
+
751
+ // Step 1: Bump fee and change output address
733
752
distribute_funds_all_nodes ! ( ) ;
734
753
validate_balances ! ( amount_sat, false ) ;
735
754
( tx, fee_output_index) = prepare_rbf ( electrs, txid, & scripts_buf) ;
755
+ original_tx = tx. clone ( ) ;
736
756
tx. output . iter_mut ( ) . for_each ( |output| {
737
757
if scripts_buf. contains ( & output. script_pubkey ) {
738
758
let new_addr = bitcoind. new_address ( ) . unwrap ( ) ;
739
759
output. script_pubkey = new_addr. script_pubkey ( ) ;
740
760
}
741
761
} ) ;
742
762
bump_fee_and_broadcast ( bitcoind, electrs, tx, fee_output_index, is_insert_block) ;
743
- validate_balances ! ( 0 , is_insert_block) ;
763
+ if is_insertion_original_tx {
764
+ generate_block_and_insert_transactions ( bitcoind, electrs, & [ original_tx. clone ( ) ] ) ;
765
+ }
766
+ if is_insertion_original_tx {
767
+ final_amount_sat += amount_sat;
768
+ }
769
+ validate_balances ! ( final_amount_sat, is_insert_block || is_insertion_original_tx) ;
744
770
745
- // Not modifying the output scripts, but still bumping the fee.
771
+ // Step 2: Bump fee only
746
772
distribute_funds_all_nodes ! ( ) ;
747
- validate_balances ! ( amount_sat, false ) ;
773
+ validate_total_onchain_balance ! ( amount_sat + final_amount_sat ) ;
748
774
( tx, fee_output_index) = prepare_rbf ( electrs, txid, & scripts_buf) ;
775
+ original_tx = tx. clone ( ) ;
749
776
bump_fee_and_broadcast ( bitcoind, electrs, tx, fee_output_index, is_insert_block) ;
750
- validate_balances ! ( amount_sat, is_insert_block) ;
777
+ if is_insertion_original_tx {
778
+ generate_block_and_insert_transactions ( bitcoind, electrs, & [ original_tx. clone ( ) ] ) ;
779
+ }
780
+ final_amount_sat += amount_sat;
781
+ validate_balances ! ( final_amount_sat, is_insert_block || is_insertion_original_tx) ;
751
782
752
- let mut final_amount_sat = amount_sat * 2 ;
783
+ // Step 3: Increase output value
753
784
let value_sat = 21_000 ;
754
-
755
- // Increase the value of the nodes' outputs
756
785
distribute_funds_all_nodes ! ( ) ;
786
+ validate_total_onchain_balance ! ( amount_sat + final_amount_sat) ;
757
787
( tx, fee_output_index) = prepare_rbf ( electrs, txid, & scripts_buf) ;
788
+ original_tx = tx. clone ( ) ;
758
789
tx. output . iter_mut ( ) . for_each ( |output| {
759
790
if scripts_buf. contains ( & output. script_pubkey ) {
760
791
output. value = Amount :: from_sat ( output. value . to_sat ( ) + value_sat) ;
761
792
}
762
793
} ) ;
794
+ tx. output [ fee_output_index] . value -= Amount :: from_sat ( scripts_buf. len ( ) as u64 * value_sat) ;
763
795
bump_fee_and_broadcast ( bitcoind, electrs, tx, fee_output_index, is_insert_block) ;
764
- final_amount_sat += value_sat;
765
- validate_balances ! ( final_amount_sat, is_insert_block) ;
796
+ if is_insertion_original_tx {
797
+ generate_block_and_insert_transactions ( bitcoind, electrs, & [ original_tx. clone ( ) ] ) ;
798
+ }
799
+ final_amount_sat += amount_sat;
800
+ if !is_insertion_original_tx {
801
+ final_amount_sat += value_sat;
802
+ }
803
+ validate_balances ! ( final_amount_sat, is_insert_block || is_insertion_original_tx) ;
766
804
767
- // Decreases the value of the nodes' outputs
805
+ // Step 4: Decrease output value
768
806
distribute_funds_all_nodes ! ( ) ;
769
- final_amount_sat += amount_sat ;
807
+ validate_total_onchain_balance ! ( amount_sat + final_amount_sat ) ;
770
808
( tx, fee_output_index) = prepare_rbf ( electrs, txid, & scripts_buf) ;
809
+ original_tx = tx. clone ( ) ;
771
810
tx. output . iter_mut ( ) . for_each ( |output| {
772
811
if scripts_buf. contains ( & output. script_pubkey ) {
773
812
output. value = Amount :: from_sat ( output. value . to_sat ( ) - value_sat) ;
774
813
}
775
814
} ) ;
815
+ tx. output [ fee_output_index] . value += Amount :: from_sat ( scripts_buf. len ( ) as u64 * value_sat) ;
776
816
bump_fee_and_broadcast ( bitcoind, electrs, tx, fee_output_index, is_insert_block) ;
777
- final_amount_sat -= value_sat;
778
- validate_balances ! ( final_amount_sat, is_insert_block) ;
817
+ if is_insertion_original_tx {
818
+ generate_block_and_insert_transactions ( bitcoind, electrs, & [ original_tx. clone ( ) ] ) ;
819
+ }
820
+ final_amount_sat += amount_sat;
821
+ if !is_insertion_original_tx {
822
+ final_amount_sat -= value_sat;
823
+ }
824
+ validate_balances ! ( final_amount_sat, is_insert_block || is_insertion_original_tx) ;
779
825
780
826
if !is_insert_block {
781
827
generate_blocks_and_wait ( bitcoind, electrs, 1 ) ;
0 commit comments