@@ -16,7 +16,8 @@ use crate::chain::ChannelMonitorUpdateStatus;
1616use crate :: events:: { ClosureReason , Event , FundingInfo , HTLCHandlingFailureType } ;
1717use crate :: ln:: chan_utils;
1818use crate :: ln:: channel:: {
19- CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY , FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE ,
19+ CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY , DISCONNECT_PEER_AWAITING_RESPONSE_TICKS ,
20+ FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE ,
2021} ;
2122use crate :: ln:: channelmanager:: { provided_init_features, PaymentId , BREAKDOWN_TIMEOUT } ;
2223use crate :: ln:: functional_test_utils:: * ;
@@ -7082,3 +7083,194 @@ fn test_splice_rbf_rejects_own_low_feerate_after_several_attempts() {
70827083 other => panic ! ( "Expected SpliceFailed, got {:?}" , other) ,
70837084 }
70847085}
7086+
7087+ #[ test]
7088+ fn test_no_disconnect_after_splice_completes ( ) {
7089+ // Test that the disconnect timer is cleared when exiting quiescence after a successful splice
7090+ // negotiation. Previously, `on_tx_signatures_exchange` cleared the quiescent state but not the
7091+ // disconnect timer, causing a spurious disconnect after the splice completed.
7092+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
7093+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
7094+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
7095+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
7096+
7097+ let initial_channel_value_sat = 100_000 ;
7098+ let ( _, _, channel_id, _) =
7099+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , initial_channel_value_sat, 0 ) ;
7100+
7101+ let added_value = Amount :: from_sat ( 50_000 ) ;
7102+ provide_utxo_reserves ( & nodes, 2 , added_value * 2 ) ;
7103+
7104+ let funding_contribution = do_initiate_splice_in ( & nodes[ 0 ] , & nodes[ 1 ] , channel_id, added_value) ;
7105+ let new_funding_script = complete_splice_handshake ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
7106+
7107+ // Fire a tick while quiescent to arm the disconnect timer.
7108+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
7109+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
7110+
7111+ // Complete the splice negotiation, which should clear the timer when exiting quiescence.
7112+ complete_interactive_funding_negotiation (
7113+ & nodes[ 0 ] ,
7114+ & nodes[ 1 ] ,
7115+ channel_id,
7116+ funding_contribution,
7117+ new_funding_script,
7118+ ) ;
7119+ let ( _, splice_locked) = sign_interactive_funding_tx ( & nodes[ 0 ] , & nodes[ 1 ] , false ) ;
7120+ assert ! ( splice_locked. is_none( ) ) ;
7121+
7122+ let node_id_0 = nodes[ 0 ] . node . get_our_node_id ( ) ;
7123+ let node_id_1 = nodes[ 1 ] . node . get_our_node_id ( ) ;
7124+ expect_splice_pending_event ( & nodes[ 0 ] , & node_id_1) ;
7125+ expect_splice_pending_event ( & nodes[ 1 ] , & node_id_0) ;
7126+
7127+ // Fire enough ticks to trigger a disconnect if the timer wasn't properly cleared.
7128+ for _ in 0 ..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
7129+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
7130+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
7131+ }
7132+
7133+ let has_disconnect = |events : & [ MessageSendEvent ] | {
7134+ events. iter ( ) . any ( |event| {
7135+ matches ! (
7136+ event,
7137+ MessageSendEvent :: HandleError {
7138+ action: msgs:: ErrorAction :: DisconnectPeerWithWarning { .. } ,
7139+ ..
7140+ }
7141+ )
7142+ } )
7143+ } ;
7144+ assert ! ( !has_disconnect( & nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7145+ assert ! ( !has_disconnect( & nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7146+ }
7147+
7148+ #[ test]
7149+ fn test_no_disconnect_after_splice_aborted ( ) {
7150+ // Test that the disconnect timer is cleared when exiting quiescence after a splice negotiation
7151+ // is aborted via tx_abort. Previously, `reset_pending_splice_state` cleared the quiescent
7152+ // state but not the disconnect timer, causing a spurious disconnect after the abort.
7153+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
7154+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
7155+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
7156+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
7157+
7158+ let node_id_0 = nodes[ 0 ] . node . get_our_node_id ( ) ;
7159+ let node_id_1 = nodes[ 1 ] . node . get_our_node_id ( ) ;
7160+
7161+ let initial_channel_value_sat = 100_000 ;
7162+ let ( _, _, channel_id, _) =
7163+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , initial_channel_value_sat, 0 ) ;
7164+
7165+ let added_value = Amount :: from_sat ( 50_000 ) ;
7166+ provide_utxo_reserves ( & nodes, 2 , added_value * 2 ) ;
7167+
7168+ let funding_contribution = do_initiate_splice_in ( & nodes[ 0 ] , & nodes[ 1 ] , channel_id, added_value) ;
7169+ complete_splice_handshake ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
7170+
7171+ // Fire a tick while quiescent to arm the disconnect timer.
7172+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
7173+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
7174+
7175+ // Abort the splice, which should clear the timer when exiting quiescence.
7176+ nodes[ 0 ] . node . abandon_splice ( & channel_id, & node_id_1) . unwrap ( ) ;
7177+
7178+ expect_splice_failed_events ( & nodes[ 0 ] , & channel_id, funding_contribution) ;
7179+
7180+ let msg_events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
7181+ let tx_abort = msg_events
7182+ . iter ( )
7183+ . find_map ( |event| {
7184+ if let MessageSendEvent :: SendTxAbort { msg, .. } = event {
7185+ Some ( msg. clone ( ) )
7186+ } else {
7187+ None
7188+ }
7189+ } )
7190+ . expect ( "Expected SendTxAbort" ) ;
7191+
7192+ nodes[ 1 ] . node . handle_tx_abort ( node_id_0, & tx_abort) ;
7193+ let tx_abort_echo = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendTxAbort , node_id_0) ;
7194+ nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
7195+
7196+ nodes[ 0 ] . node . handle_tx_abort ( node_id_1, & tx_abort_echo) ;
7197+
7198+ // Fire enough ticks to trigger a disconnect if the timer wasn't properly cleared.
7199+ for _ in 0 ..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
7200+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
7201+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
7202+ }
7203+
7204+ let has_disconnect = |events : & [ MessageSendEvent ] | {
7205+ events. iter ( ) . any ( |event| {
7206+ matches ! (
7207+ event,
7208+ MessageSendEvent :: HandleError {
7209+ action: msgs:: ErrorAction :: DisconnectPeerWithWarning { .. } ,
7210+ ..
7211+ }
7212+ )
7213+ } )
7214+ } ;
7215+ assert ! ( !has_disconnect( & nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7216+ assert ! ( !has_disconnect( & nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7217+ }
7218+
7219+ #[ test]
7220+ fn test_no_disconnect_after_quiescence_on_reconnect ( ) {
7221+ // Test that there is no spurious disconnect after reconnecting from a quiescent state. The
7222+ // disconnect timer is cleared by `remove_uncommitted_htlcs_and_mark_paused` during
7223+ // disconnection and by `exit_quiescence` during reconnection.
7224+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
7225+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
7226+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
7227+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
7228+
7229+ let node_id_0 = nodes[ 0 ] . node . get_our_node_id ( ) ;
7230+ let node_id_1 = nodes[ 1 ] . node . get_our_node_id ( ) ;
7231+
7232+ let initial_channel_value_sat = 100_000 ;
7233+ let ( _, _, channel_id, _) =
7234+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , initial_channel_value_sat, 0 ) ;
7235+
7236+ let added_value = Amount :: from_sat ( 50_000 ) ;
7237+ provide_utxo_reserves ( & nodes, 2 , added_value * 2 ) ;
7238+
7239+ let funding_contribution = do_initiate_splice_in ( & nodes[ 0 ] , & nodes[ 1 ] , channel_id, added_value) ;
7240+ complete_splice_handshake ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
7241+
7242+ // Fire a tick while quiescent to arm the disconnect timer.
7243+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
7244+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
7245+
7246+ // Disconnect and reconnect.
7247+ nodes[ 0 ] . node . peer_disconnected ( node_id_1) ;
7248+ nodes[ 1 ] . node . peer_disconnected ( node_id_0) ;
7249+
7250+ expect_splice_failed_events ( & nodes[ 0 ] , & channel_id, funding_contribution) ;
7251+
7252+ let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
7253+ reconnect_args. send_channel_ready = ( true , true ) ;
7254+ reconnect_args. send_announcement_sigs = ( true , true ) ;
7255+ reconnect_nodes ( reconnect_args) ;
7256+
7257+ // Fire enough ticks to trigger a disconnect if the timer wasn't properly cleared.
7258+ for _ in 0 ..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
7259+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
7260+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
7261+ }
7262+
7263+ let has_disconnect = |events : & [ MessageSendEvent ] | {
7264+ events. iter ( ) . any ( |event| {
7265+ matches ! (
7266+ event,
7267+ MessageSendEvent :: HandleError {
7268+ action: msgs:: ErrorAction :: DisconnectPeerWithWarning { .. } ,
7269+ ..
7270+ }
7271+ )
7272+ } )
7273+ } ;
7274+ assert ! ( !has_disconnect( & nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7275+ assert ! ( !has_disconnect( & nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7276+ }
0 commit comments