@@ -8088,6 +8088,53 @@ fn test_funding_contributed_rbf_adjustment_exceeds_max_feerate() {
80888088 assert_eq ! ( splice_init. funding_feerate_per_kw, FEERATE_FLOOR_SATS_PER_KW ) ;
80898089}
80908090
8091+ #[ test]
8092+ fn test_peer_initiated_stfu_skips_local_rbf_feerate_check ( ) {
8093+ // Test that a local low-fee splice RBF attempt does not prevent us from responding to a
8094+ // counterparty-initiated quiescence attempt.
8095+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
8096+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
8097+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
8098+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
8099+
8100+ let node_id_0 = nodes[ 0 ] . node . get_our_node_id ( ) ;
8101+ let node_id_1 = nodes[ 1 ] . node . get_our_node_id ( ) ;
8102+
8103+ let initial_channel_value_sat = 100_000 ;
8104+ let ( _, _, channel_id, _) =
8105+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , initial_channel_value_sat, 0 ) ;
8106+
8107+ let added_value = Amount :: from_sat ( 50_000 ) ;
8108+ provide_utxo_reserves ( & nodes, 4 , added_value * 2 ) ;
8109+
8110+ let floor_feerate = FeeRate :: from_sat_per_kwu ( FEERATE_FLOOR_SATS_PER_KW as u64 ) ;
8111+ let node_0_template = nodes[ 0 ] . node . splice_channel ( & channel_id, & node_id_1) . unwrap ( ) ;
8112+ let wallet = WalletSync :: new ( Arc :: clone ( & nodes[ 0 ] . wallet_source ) , nodes[ 0 ] . logger ) ;
8113+ let node_0_contribution =
8114+ node_0_template. splice_in_sync ( added_value, floor_feerate, floor_feerate, & wallet) . unwrap ( ) ;
8115+
8116+ // Node 1 creates a pending splice before node 0 submits its contribution. Node 0's
8117+ // contribution cannot be adjusted up to the pending splice's minimum RBF feerate, so it must
8118+ // not send its own stfu yet.
8119+ let node_1_contribution = do_initiate_splice_in ( & nodes[ 1 ] , & nodes[ 0 ] , channel_id, added_value) ;
8120+ let ( _first_splice_tx, _) =
8121+ splice_channel ( & nodes[ 1 ] , & nodes[ 0 ] , channel_id, node_1_contribution) ;
8122+ nodes[ 0 ] . node . funding_contributed ( & channel_id, & node_id_1, node_0_contribution, None ) . unwrap ( ) ;
8123+ assert ! ( nodes[ 0 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
8124+
8125+ // Node 1 can still initiate quiescence for its own RBF attempt. Node 0 should reply as the
8126+ // non-initiator instead of applying its local splice RBF feerate check to the response.
8127+ let min_rbf_feerate = FeeRate :: from_sat_per_kwu ( FEERATE_FLOOR_SATS_PER_KW as u64 + 25 ) ;
8128+ let _node_1_rbf_contribution =
8129+ do_initiate_rbf_splice_in ( & nodes[ 1 ] , & nodes[ 0 ] , channel_id, min_rbf_feerate) ;
8130+ let stfu_init = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendStfu , node_id_0) ;
8131+ assert ! ( stfu_init. initiator) ;
8132+
8133+ nodes[ 0 ] . node . handle_stfu ( node_id_1, & stfu_init) ;
8134+ let stfu_response = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendStfu , node_id_1) ;
8135+ assert ! ( !stfu_response. initiator) ;
8136+ }
8137+
80918138#[ test]
80928139fn test_funding_contributed_rbf_adjustment_insufficient_budget ( ) {
80938140 // Test that when the change output can't absorb the fee increase needed for the minimum RBF feerate
0 commit comments