@@ -21,10 +21,11 @@ use common::{
2121 expect_channel_pending_event, expect_channel_ready_event, expect_channel_ready_events,
2222 expect_event, expect_payment_claimable_event, expect_payment_received_event,
2323 expect_payment_successful_event, expect_splice_pending_event, generate_blocks_and_wait,
24- open_channel, open_channel_push_amt, open_channel_with_all, premine_and_distribute_funds,
25- premine_blocks, prepare_rbf, random_chain_source, random_config, random_listening_addresses,
26- setup_bitcoind_and_electrsd, setup_builder, setup_node, setup_two_nodes, splice_in_with_all,
27- wait_for_cbf_sync, wait_for_tx, TestChainSource , TestStoreType , TestSyncStore ,
24+ invalidate_blocks, open_channel, open_channel_push_amt, open_channel_with_all,
25+ premine_and_distribute_funds, premine_blocks, prepare_rbf, random_chain_source, random_config,
26+ random_listening_addresses, setup_bitcoind_and_electrsd, setup_builder, setup_node,
27+ setup_two_nodes, splice_in_with_all, wait_for_block, wait_for_cbf_sync, wait_for_tx,
28+ TestChainSource , TestStoreType , TestSyncStore ,
2829} ;
2930use ldk_node:: config:: { AsyncPaymentsRole , EsploraSyncConfig } ;
3031use ldk_node:: entropy:: NodeEntropy ;
@@ -2877,3 +2878,101 @@ async fn repeated_manual_sync_cbf() {
28772878
28782879 node. stop ( ) . unwrap ( ) ;
28792880}
2881+
2882+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
2883+ async fn onchain_wallet_sync_cbf_after_reorg ( ) {
2884+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
2885+ let chain_source = TestChainSource :: Cbf ( & bitcoind) ;
2886+ let node = setup_node ( & chain_source, random_config ( true ) ) ;
2887+
2888+ let first_addr = node. onchain_payment ( ) . new_address ( ) . unwrap ( ) ;
2889+ let first_amount_sat = 100_000 ;
2890+ premine_and_distribute_funds (
2891+ & bitcoind. client ,
2892+ & electrsd. client ,
2893+ vec ! [ first_addr] ,
2894+ Amount :: from_sat ( first_amount_sat) ,
2895+ )
2896+ . await ;
2897+
2898+ wait_for_cbf_sync ( & node) . await ;
2899+ assert_eq ! ( node. list_balances( ) . spendable_onchain_balance_sats, first_amount_sat) ;
2900+
2901+ // Advance the tip so the reorg happens below our synced checkpoint.
2902+ generate_blocks_and_wait ( & bitcoind. client , & electrsd. client , 2 ) . await ;
2903+ wait_for_cbf_sync ( & node) . await ;
2904+
2905+ // Replace the last two blocks with a different branch that has no wallet activity.
2906+ invalidate_blocks ( & bitcoind. client , 2 ) ;
2907+ generate_blocks_and_wait ( & bitcoind. client , & electrsd. client , 2 ) . await ;
2908+ wait_for_cbf_sync ( & node) . await ;
2909+
2910+ let second_addr = node. onchain_payment ( ) . new_address ( ) . unwrap ( ) ;
2911+ let second_amount_sat = 50_000 ;
2912+ distribute_funds_unconfirmed (
2913+ & bitcoind. client ,
2914+ & electrsd. client ,
2915+ vec ! [ second_addr] ,
2916+ Amount :: from_sat ( second_amount_sat) ,
2917+ )
2918+ . await ;
2919+ generate_blocks_and_wait ( & bitcoind. client , & electrsd. client , 1 ) . await ;
2920+ wait_for_cbf_sync ( & node) . await ;
2921+
2922+ assert_eq ! (
2923+ node. list_balances( ) . spendable_onchain_balance_sats,
2924+ first_amount_sat + second_amount_sat
2925+ ) ;
2926+ assert_eq ! (
2927+ node. list_payments_with_filter( |p| {
2928+ p. direction == PaymentDirection :: Inbound
2929+ && matches!( p. kind, PaymentKind :: Onchain { .. } )
2930+ } )
2931+ . len( ) ,
2932+ 2
2933+ ) ;
2934+
2935+ node. stop ( ) . unwrap ( ) ;
2936+ }
2937+
2938+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
2939+ async fn onchain_wallet_sync_cbf_reorgs_out_confirmed_receive ( ) {
2940+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
2941+ let chain_source = TestChainSource :: Cbf ( & bitcoind) ;
2942+ let node = setup_node ( & chain_source, random_config ( true ) ) ;
2943+
2944+ let addr = node. onchain_payment ( ) . new_address ( ) . unwrap ( ) ;
2945+ premine_blocks ( & bitcoind. client , & electrsd. client ) . await ;
2946+ let cur_height = bitcoind. client . get_blockchain_info ( ) . unwrap ( ) . blocks as usize ;
2947+ let reward_block_hash =
2948+ bitcoind. client . generate_to_address ( 1 , & addr) . unwrap ( ) . 0 . pop ( ) . unwrap ( ) . parse ( ) . unwrap ( ) ;
2949+ wait_for_block ( & electrsd. client , cur_height + 1 ) . await ;
2950+ let reward_block = bitcoind. client . get_block ( reward_block_hash) . unwrap ( ) ;
2951+ let txid = reward_block. txdata [ 0 ] . compute_txid ( ) ;
2952+ wait_for_cbf_sync ( & node) . await ;
2953+ assert_eq ! ( node. list_balances( ) . total_onchain_balance_sats, 5_000_000_000 ) ;
2954+ assert_eq ! ( node. list_balances( ) . spendable_onchain_balance_sats, 0 ) ;
2955+
2956+ let payment_id = PaymentId ( txid. to_byte_array ( ) ) ;
2957+ let payment = node. payment ( & payment_id) . unwrap ( ) ;
2958+ assert_eq ! ( payment. status, PaymentStatus :: Pending ) ;
2959+ match payment. kind {
2960+ PaymentKind :: Onchain { status : ConfirmationStatus :: Confirmed { .. } , .. } => { } ,
2961+ other => panic ! ( "Unexpected payment state before reorg: {:?}" , other) ,
2962+ }
2963+
2964+ invalidate_blocks ( & bitcoind. client , 1 ) ;
2965+ generate_blocks_and_wait ( & bitcoind. client , & electrsd. client , 2 ) . await ;
2966+ wait_for_cbf_sync ( & node) . await ;
2967+
2968+ assert_eq ! ( node. list_balances( ) . total_onchain_balance_sats, 0 ) ;
2969+ assert_eq ! ( node. list_balances( ) . spendable_onchain_balance_sats, 0 ) ;
2970+ let payment = node. payment ( & payment_id) . unwrap ( ) ;
2971+ assert_eq ! ( payment. status, PaymentStatus :: Pending ) ;
2972+ match payment. kind {
2973+ PaymentKind :: Onchain { status : ConfirmationStatus :: Unconfirmed , .. } => { } ,
2974+ other => panic ! ( "Unexpected payment state after reorg: {:?}" , other) ,
2975+ }
2976+
2977+ node. stop ( ) . unwrap ( ) ;
2978+ }
0 commit comments