@@ -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:: * ;
@@ -6819,3 +6820,194 @@ fn test_splice_rbf_rejects_own_low_feerate_after_several_attempts() {
68196820 other => panic ! ( "Expected SpliceFailed, got {:?}" , other) ,
68206821 }
68216822}
6823+
6824+ #[ test]
6825+ fn test_no_disconnect_after_splice_completes ( ) {
6826+ // Test that the disconnect timer is cleared when exiting quiescence after a successful splice
6827+ // negotiation. Previously, `on_tx_signatures_exchange` cleared the quiescent state but not the
6828+ // disconnect timer, causing a spurious disconnect after the splice completed.
6829+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
6830+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
6831+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
6832+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
6833+
6834+ let initial_channel_value_sat = 100_000 ;
6835+ let ( _, _, channel_id, _) =
6836+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , initial_channel_value_sat, 0 ) ;
6837+
6838+ let added_value = Amount :: from_sat ( 50_000 ) ;
6839+ provide_utxo_reserves ( & nodes, 2 , added_value * 2 ) ;
6840+
6841+ let funding_contribution = do_initiate_splice_in ( & nodes[ 0 ] , & nodes[ 1 ] , channel_id, added_value) ;
6842+ let new_funding_script = complete_splice_handshake ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
6843+
6844+ // Fire a tick while quiescent to arm the disconnect timer.
6845+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
6846+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
6847+
6848+ // Complete the splice negotiation, which should clear the timer when exiting quiescence.
6849+ complete_interactive_funding_negotiation (
6850+ & nodes[ 0 ] ,
6851+ & nodes[ 1 ] ,
6852+ channel_id,
6853+ funding_contribution,
6854+ new_funding_script,
6855+ ) ;
6856+ let ( _, splice_locked) = sign_interactive_funding_tx ( & nodes[ 0 ] , & nodes[ 1 ] , false ) ;
6857+ assert ! ( splice_locked. is_none( ) ) ;
6858+
6859+ let node_id_0 = nodes[ 0 ] . node . get_our_node_id ( ) ;
6860+ let node_id_1 = nodes[ 1 ] . node . get_our_node_id ( ) ;
6861+ expect_splice_pending_event ( & nodes[ 0 ] , & node_id_1) ;
6862+ expect_splice_pending_event ( & nodes[ 1 ] , & node_id_0) ;
6863+
6864+ // Fire enough ticks to trigger a disconnect if the timer wasn't properly cleared.
6865+ for _ in 0 ..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
6866+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
6867+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
6868+ }
6869+
6870+ let has_disconnect = |events : & [ MessageSendEvent ] | {
6871+ events. iter ( ) . any ( |event| {
6872+ matches ! (
6873+ event,
6874+ MessageSendEvent :: HandleError {
6875+ action: msgs:: ErrorAction :: DisconnectPeerWithWarning { .. } ,
6876+ ..
6877+ }
6878+ )
6879+ } )
6880+ } ;
6881+ assert ! ( !has_disconnect( & nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
6882+ assert ! ( !has_disconnect( & nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
6883+ }
6884+
6885+ #[ test]
6886+ fn test_no_disconnect_after_splice_aborted ( ) {
6887+ // Test that the disconnect timer is cleared when exiting quiescence after a splice negotiation
6888+ // is aborted via tx_abort. Previously, `reset_pending_splice_state` cleared the quiescent
6889+ // state but not the disconnect timer, causing a spurious disconnect after the abort.
6890+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
6891+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
6892+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
6893+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
6894+
6895+ let node_id_0 = nodes[ 0 ] . node . get_our_node_id ( ) ;
6896+ let node_id_1 = nodes[ 1 ] . node . get_our_node_id ( ) ;
6897+
6898+ let initial_channel_value_sat = 100_000 ;
6899+ let ( _, _, channel_id, _) =
6900+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , initial_channel_value_sat, 0 ) ;
6901+
6902+ let added_value = Amount :: from_sat ( 50_000 ) ;
6903+ provide_utxo_reserves ( & nodes, 2 , added_value * 2 ) ;
6904+
6905+ let funding_contribution = do_initiate_splice_in ( & nodes[ 0 ] , & nodes[ 1 ] , channel_id, added_value) ;
6906+ complete_splice_handshake ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
6907+
6908+ // Fire a tick while quiescent to arm the disconnect timer.
6909+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
6910+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
6911+
6912+ // Abort the splice, which should clear the timer when exiting quiescence.
6913+ nodes[ 0 ] . node . abandon_splice ( & channel_id, & node_id_1) . unwrap ( ) ;
6914+
6915+ expect_splice_failed_events ( & nodes[ 0 ] , & channel_id, funding_contribution) ;
6916+
6917+ let msg_events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
6918+ let tx_abort = msg_events
6919+ . iter ( )
6920+ . find_map ( |event| {
6921+ if let MessageSendEvent :: SendTxAbort { msg, .. } = event {
6922+ Some ( msg. clone ( ) )
6923+ } else {
6924+ None
6925+ }
6926+ } )
6927+ . expect ( "Expected SendTxAbort" ) ;
6928+
6929+ nodes[ 1 ] . node . handle_tx_abort ( node_id_0, & tx_abort) ;
6930+ let tx_abort_echo = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendTxAbort , node_id_0) ;
6931+ nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
6932+
6933+ nodes[ 0 ] . node . handle_tx_abort ( node_id_1, & tx_abort_echo) ;
6934+
6935+ // Fire enough ticks to trigger a disconnect if the timer wasn't properly cleared.
6936+ for _ in 0 ..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
6937+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
6938+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
6939+ }
6940+
6941+ let has_disconnect = |events : & [ MessageSendEvent ] | {
6942+ events. iter ( ) . any ( |event| {
6943+ matches ! (
6944+ event,
6945+ MessageSendEvent :: HandleError {
6946+ action: msgs:: ErrorAction :: DisconnectPeerWithWarning { .. } ,
6947+ ..
6948+ }
6949+ )
6950+ } )
6951+ } ;
6952+ assert ! ( !has_disconnect( & nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
6953+ assert ! ( !has_disconnect( & nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
6954+ }
6955+
6956+ #[ test]
6957+ fn test_no_disconnect_after_quiescence_on_reconnect ( ) {
6958+ // Test that there is no spurious disconnect after reconnecting from a quiescent state. The
6959+ // disconnect timer is cleared by `remove_uncommitted_htlcs_and_mark_paused` during
6960+ // disconnection and by `exit_quiescence` during reconnection.
6961+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
6962+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
6963+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
6964+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
6965+
6966+ let node_id_0 = nodes[ 0 ] . node . get_our_node_id ( ) ;
6967+ let node_id_1 = nodes[ 1 ] . node . get_our_node_id ( ) ;
6968+
6969+ let initial_channel_value_sat = 100_000 ;
6970+ let ( _, _, channel_id, _) =
6971+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , initial_channel_value_sat, 0 ) ;
6972+
6973+ let added_value = Amount :: from_sat ( 50_000 ) ;
6974+ provide_utxo_reserves ( & nodes, 2 , added_value * 2 ) ;
6975+
6976+ let funding_contribution = do_initiate_splice_in ( & nodes[ 0 ] , & nodes[ 1 ] , channel_id, added_value) ;
6977+ complete_splice_handshake ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
6978+
6979+ // Fire a tick while quiescent to arm the disconnect timer.
6980+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
6981+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
6982+
6983+ // Disconnect and reconnect.
6984+ nodes[ 0 ] . node . peer_disconnected ( node_id_1) ;
6985+ nodes[ 1 ] . node . peer_disconnected ( node_id_0) ;
6986+
6987+ expect_splice_failed_events ( & nodes[ 0 ] , & channel_id, funding_contribution) ;
6988+
6989+ let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 0 ] , & nodes[ 1 ] ) ;
6990+ reconnect_args. send_channel_ready = ( true , true ) ;
6991+ reconnect_args. send_announcement_sigs = ( true , true ) ;
6992+ reconnect_nodes ( reconnect_args) ;
6993+
6994+ // Fire enough ticks to trigger a disconnect if the timer wasn't properly cleared.
6995+ for _ in 0 ..DISCONNECT_PEER_AWAITING_RESPONSE_TICKS {
6996+ nodes[ 0 ] . node . timer_tick_occurred ( ) ;
6997+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
6998+ }
6999+
7000+ let has_disconnect = |events : & [ MessageSendEvent ] | {
7001+ events. iter ( ) . any ( |event| {
7002+ matches ! (
7003+ event,
7004+ MessageSendEvent :: HandleError {
7005+ action: msgs:: ErrorAction :: DisconnectPeerWithWarning { .. } ,
7006+ ..
7007+ }
7008+ )
7009+ } )
7010+ } ;
7011+ assert ! ( !has_disconnect( & nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7012+ assert ! ( !has_disconnect( & nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) ) ) ;
7013+ }
0 commit comments