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