@@ -1053,10 +1053,10 @@ pub fn test_chan_reserve_dust_inbound_htlcs_outbound_chan() {
10531053 * 1000 ;
10541054 create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100000 , push_amt) ;
10551055
1056- let ( htlc_success_tx_fee_sat , _ ) =
1056+ let ( _htlc_success_tx_fee_sat , htlc_timeout_tx_fee_sat ) =
10571057 second_stage_tx_fees_sat ( & channel_type_features, feerate_per_kw) ;
10581058 let dust_amt = crate :: ln:: channel:: MIN_CHAN_DUST_LIMIT_SATOSHIS * 1000
1059- + htlc_success_tx_fee_sat * 1000
1059+ + htlc_timeout_tx_fee_sat * 1000
10601060 - 1 ;
10611061 // In the previous code, routing this dust payment would cause nodes[0] to perceive a channel
10621062 // reserve violation even though it's a dust HTLC and therefore shouldn't count towards the
@@ -3528,3 +3528,268 @@ fn test_fail_cannot_afford_dust_htlcs_at_spike_multiple_if_nondust_at_base_feera
35283528 true ,
35293529 ) ;
35303530}
3531+
3532+ #[ xtest( feature = "_externalize_tests" ) ]
3533+ fn test_available_balances_both_commitments_dust_on_funder_commitment ( ) {
3534+ let mut config = test_default_channel_config ( ) ;
3535+
3536+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
3537+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
3538+ config. channel_handshake_config . announced_channel_max_inbound_htlc_value_in_flight_percentage =
3539+ 100 ;
3540+
3541+ let channel_type = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
3542+
3543+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( config. clone ( ) ) , Some ( config) ] ) ;
3544+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
3545+
3546+ const FEERATE : u32 = 253 ;
3547+ const TOTAL_ANCHORS_MSAT : u64 = 2 * 330_000 ;
3548+ const NODE_0_DUST_LIMIT_MSAT : u64 = 10_000 * 1000 ;
3549+ const NODE_1_DUST_LIMIT_MSAT : u64 = 354 * 1000 ;
3550+ const CHANNEL_VALUE_MSAT : u64 = 50_000 * 1000 ;
3551+ const NODE_0_VALUE_TO_SELF_MSAT : u64 = 25_000 * 1000 ;
3552+ const NODE_1_VALUE_TO_SELF_MSAT : u64 = 25_000 * 1000 ;
3553+ const NODE_0_SELECTED_CHANNEL_RESERVE_MSAT : u64 = 1_000 * 1_000 ;
3554+ const NODE_1_SELECTED_CHANNEL_RESERVE_MSAT : u64 = 10_000 * 1_000 ;
3555+
3556+ let channel_id = create_announced_chan_between_nodes_with_value (
3557+ & nodes,
3558+ 0 ,
3559+ 1 ,
3560+ CHANNEL_VALUE_MSAT / 1000 ,
3561+ NODE_1_VALUE_TO_SELF_MSAT ,
3562+ )
3563+ . 2 ;
3564+ assert_eq ! ( nodes[ 0 ] . node. list_channels( ) [ 0 ] . channel_type. as_ref( ) . unwrap( ) , & channel_type) ;
3565+
3566+ {
3567+ let per_peer_state_lock;
3568+ let mut peer_state_lock;
3569+ let chan =
3570+ get_channel_ref ! ( nodes[ 0 ] , nodes[ 1 ] , per_peer_state_lock, peer_state_lock, channel_id) ;
3571+ chan. context_mut ( ) . holder_dust_limit_satoshis = NODE_0_DUST_LIMIT_MSAT / 1000 ;
3572+ chan. funding_mut ( ) . counterparty_selected_channel_reserve_satoshis =
3573+ Some ( NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000 ) ;
3574+ assert_eq ! ( chan. context( ) . counterparty_dust_limit_satoshis, NODE_1_DUST_LIMIT_MSAT / 1000 ) ;
3575+ assert_eq ! (
3576+ chan. funding( ) . holder_selected_channel_reserve_satoshis,
3577+ NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000
3578+ ) ;
3579+ }
3580+
3581+ {
3582+ let per_peer_state_lock;
3583+ let mut peer_state_lock;
3584+ let chan =
3585+ get_channel_ref ! ( nodes[ 1 ] , nodes[ 0 ] , per_peer_state_lock, peer_state_lock, channel_id) ;
3586+ chan. context_mut ( ) . counterparty_dust_limit_satoshis = NODE_0_DUST_LIMIT_MSAT / 1000 ;
3587+ chan. funding_mut ( ) . holder_selected_channel_reserve_satoshis =
3588+ NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000 ;
3589+ assert_eq ! ( chan. context( ) . holder_dust_limit_satoshis, NODE_1_DUST_LIMIT_MSAT / 1000 ) ;
3590+ assert_eq ! (
3591+ chan. funding( ) . counterparty_selected_channel_reserve_satoshis,
3592+ Some ( NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000 )
3593+ ) ;
3594+ }
3595+
3596+ // This HTLC is only present on node 1's commitment
3597+ const SNEAKY_HTLC_MSAT : u64 = 5_000_000 ;
3598+
3599+ route_payment ( & nodes[ 1 ] , & [ & nodes[ 0 ] ] , SNEAKY_HTLC_MSAT ) ;
3600+
3601+ let node_1_details = & nodes[ 1 ] . node . list_channels ( ) [ 0 ] ;
3602+ let expected_outbound_capacity_msat =
3603+ NODE_1_VALUE_TO_SELF_MSAT - SNEAKY_HTLC_MSAT - NODE_0_SELECTED_CHANNEL_RESERVE_MSAT ;
3604+ assert_eq ! ( node_1_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3605+ let expected_available_capacity_msat = expected_outbound_capacity_msat;
3606+ assert_eq ! ( node_1_details. next_outbound_htlc_limit_msat, expected_available_capacity_msat) ;
3607+ let expected_splice_out_max =
3608+ NODE_1_VALUE_TO_SELF_MSAT / 1000 - SNEAKY_HTLC_MSAT / 1000 - NODE_1_DUST_LIMIT_MSAT / 1000 ;
3609+ assert_eq ! ( node_1_details. next_splice_out_maximum_sat, expected_splice_out_max) ;
3610+
3611+ let node_0_details = & nodes[ 0 ] . node . list_channels ( ) [ 0 ] ;
3612+ let expected_outbound_capacity_msat =
3613+ NODE_0_VALUE_TO_SELF_MSAT - NODE_1_SELECTED_CHANNEL_RESERVE_MSAT - TOTAL_ANCHORS_MSAT ;
3614+ assert_eq ! ( node_0_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3615+ let expected_available_capacity_msat =
3616+ expected_outbound_capacity_msat - commit_tx_fee_sat ( FEERATE , 3 , & channel_type) * 1000 ;
3617+ assert_eq ! ( node_0_details. next_outbound_htlc_limit_msat, expected_available_capacity_msat) ;
3618+ let expected_splice_out_max = NODE_0_VALUE_TO_SELF_MSAT / 1000
3619+ - TOTAL_ANCHORS_MSAT / 1000
3620+ - commit_tx_fee_sat ( FEERATE , 2 , & channel_type)
3621+ - NODE_0_DUST_LIMIT_MSAT / 1000 ;
3622+ assert_eq ! ( node_0_details. next_splice_out_maximum_sat, expected_splice_out_max) ;
3623+
3624+ let node_0_payment_msat = expected_available_capacity_msat;
3625+ send_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , node_0_payment_msat) ;
3626+
3627+ route_payment ( & nodes[ 1 ] , & [ & nodes[ 0 ] ] , SNEAKY_HTLC_MSAT ) ;
3628+ route_payment ( & nodes[ 1 ] , & [ & nodes[ 0 ] ] , SNEAKY_HTLC_MSAT ) ;
3629+
3630+ let node_0_details = & nodes[ 0 ] . node . list_channels ( ) [ 0 ] ;
3631+ let expected_outbound_capacity_msat = NODE_0_VALUE_TO_SELF_MSAT
3632+ - node_0_payment_msat
3633+ - NODE_1_SELECTED_CHANNEL_RESERVE_MSAT
3634+ - TOTAL_ANCHORS_MSAT ;
3635+ assert_eq ! ( node_0_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3636+ assert_eq ! (
3637+ node_0_details. outbound_capacity_msat,
3638+ commit_tx_fee_sat( FEERATE , 3 , & channel_type) * 1000
3639+ ) ;
3640+ assert_eq ! ( node_0_details. next_outbound_htlc_limit_msat, 0 ) ;
3641+ assert_eq ! ( node_0_details. next_splice_out_maximum_sat, 0 ) ;
3642+
3643+ let node_1_details = & nodes[ 1 ] . node . list_channels ( ) [ 0 ] ;
3644+ let expected_outbound_capacity_msat = NODE_1_VALUE_TO_SELF_MSAT + node_0_payment_msat
3645+ - 3 * SNEAKY_HTLC_MSAT
3646+ - NODE_0_SELECTED_CHANNEL_RESERVE_MSAT ;
3647+ assert_eq ! ( node_1_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3648+ let ( _htlc_success_tx_fee_sat, htlc_timeout_tx_fee_sat) =
3649+ second_stage_tx_fees_sat ( & channel_type, FEERATE ) ;
3650+ let expected_available_capacity_msat =
3651+ ( NODE_1_DUST_LIMIT_MSAT / 1000 + htlc_timeout_tx_fee_sat) * 1000 - 1 ;
3652+ assert_eq ! ( node_1_details. next_outbound_htlc_limit_msat, expected_available_capacity_msat) ;
3653+ let expected_splice_out_max = NODE_1_VALUE_TO_SELF_MSAT / 1000 + node_0_payment_msat / 1000
3654+ - 3 * SNEAKY_HTLC_MSAT / 1000
3655+ - NODE_1_DUST_LIMIT_MSAT / 1000 ;
3656+ assert_eq ! ( node_1_details. next_splice_out_maximum_sat, expected_splice_out_max) ;
3657+ }
3658+
3659+ #[ xtest( feature = "_externalize_tests" ) ]
3660+ fn test_available_balances_both_commitments_dust_on_fundee_commitment ( ) {
3661+ let mut config = test_default_channel_config ( ) ;
3662+
3663+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
3664+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
3665+ config. channel_handshake_config . announced_channel_max_inbound_htlc_value_in_flight_percentage =
3666+ 100 ;
3667+
3668+ let channel_type = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
3669+
3670+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( config. clone ( ) ) , Some ( config) ] ) ;
3671+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
3672+
3673+ const FEERATE : u32 = 253 ;
3674+ const TOTAL_ANCHORS_MSAT : u64 = 2 * 330_000 ;
3675+ const NODE_0_DUST_LIMIT_MSAT : u64 = 354 * 1000 ;
3676+ const NODE_1_DUST_LIMIT_MSAT : u64 = 10_000 * 1000 ;
3677+ const CHANNEL_VALUE_MSAT : u64 = 50_000 * 1000 ;
3678+ const NODE_0_VALUE_TO_SELF_MSAT : u64 = 25_000 * 1000 ;
3679+ const NODE_1_VALUE_TO_SELF_MSAT : u64 = 25_000 * 1000 ;
3680+ const NODE_0_SELECTED_CHANNEL_RESERVE_MSAT : u64 = 10_000 * 1_000 ;
3681+ const NODE_1_SELECTED_CHANNEL_RESERVE_MSAT : u64 = 1_000 * 1_000 ;
3682+
3683+ let channel_id = create_announced_chan_between_nodes_with_value (
3684+ & nodes,
3685+ 0 ,
3686+ 1 ,
3687+ CHANNEL_VALUE_MSAT / 1000 ,
3688+ NODE_1_VALUE_TO_SELF_MSAT ,
3689+ )
3690+ . 2 ;
3691+ assert_eq ! ( nodes[ 0 ] . node. list_channels( ) [ 0 ] . channel_type. as_ref( ) . unwrap( ) , & channel_type) ;
3692+
3693+ {
3694+ let per_peer_state_lock;
3695+ let mut peer_state_lock;
3696+ let chan =
3697+ get_channel_ref ! ( nodes[ 0 ] , nodes[ 1 ] , per_peer_state_lock, peer_state_lock, channel_id) ;
3698+ chan. context_mut ( ) . counterparty_dust_limit_satoshis = NODE_1_DUST_LIMIT_MSAT / 1000 ;
3699+ chan. funding_mut ( ) . holder_selected_channel_reserve_satoshis =
3700+ NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000 ;
3701+ assert_eq ! ( chan. context( ) . holder_dust_limit_satoshis, NODE_0_DUST_LIMIT_MSAT / 1000 ) ;
3702+ assert_eq ! (
3703+ chan. funding( ) . counterparty_selected_channel_reserve_satoshis,
3704+ Some ( NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000 )
3705+ ) ;
3706+ }
3707+
3708+ {
3709+ let per_peer_state_lock;
3710+ let mut peer_state_lock;
3711+ let chan =
3712+ get_channel_ref ! ( nodes[ 1 ] , nodes[ 0 ] , per_peer_state_lock, peer_state_lock, channel_id) ;
3713+ chan. context_mut ( ) . holder_dust_limit_satoshis = NODE_1_DUST_LIMIT_MSAT / 1000 ;
3714+ chan. funding_mut ( ) . counterparty_selected_channel_reserve_satoshis =
3715+ Some ( NODE_0_SELECTED_CHANNEL_RESERVE_MSAT / 1000 ) ;
3716+ assert_eq ! ( chan. context( ) . counterparty_dust_limit_satoshis, NODE_0_DUST_LIMIT_MSAT / 1000 ) ;
3717+ assert_eq ! (
3718+ chan. funding( ) . holder_selected_channel_reserve_satoshis,
3719+ NODE_1_SELECTED_CHANNEL_RESERVE_MSAT / 1000
3720+ ) ;
3721+ }
3722+
3723+ // This HTLC is only present on node 0's commitment
3724+ const SNEAKY_HTLC_MSAT : u64 = 5_000_000 ;
3725+
3726+ route_payment ( & nodes[ 1 ] , & [ & nodes[ 0 ] ] , SNEAKY_HTLC_MSAT ) ;
3727+
3728+ let node_1_details = & nodes[ 1 ] . node . list_channels ( ) [ 0 ] ;
3729+ let expected_outbound_capacity_msat =
3730+ NODE_1_VALUE_TO_SELF_MSAT - SNEAKY_HTLC_MSAT - NODE_0_SELECTED_CHANNEL_RESERVE_MSAT ;
3731+ assert_eq ! ( node_1_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3732+ let expected_available_capacity_msat = expected_outbound_capacity_msat;
3733+ assert_eq ! ( node_1_details. next_outbound_htlc_limit_msat, expected_available_capacity_msat) ;
3734+ let expected_splice_out_max =
3735+ NODE_1_VALUE_TO_SELF_MSAT / 1000 - SNEAKY_HTLC_MSAT / 1000 - NODE_1_DUST_LIMIT_MSAT / 1000 ;
3736+ assert_eq ! ( node_1_details. next_splice_out_maximum_sat, expected_splice_out_max) ;
3737+
3738+ let node_0_details = & nodes[ 0 ] . node . list_channels ( ) [ 0 ] ;
3739+
3740+ let expected_outbound_capacity_msat =
3741+ NODE_0_VALUE_TO_SELF_MSAT - NODE_1_SELECTED_CHANNEL_RESERVE_MSAT - TOTAL_ANCHORS_MSAT ;
3742+ assert_eq ! ( node_0_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3743+
3744+ let expected_splice_out_max = NODE_0_VALUE_TO_SELF_MSAT / 1000
3745+ - TOTAL_ANCHORS_MSAT / 1000
3746+ - commit_tx_fee_sat ( FEERATE , 2 , & channel_type)
3747+ - NODE_0_DUST_LIMIT_MSAT / 1000 ;
3748+ assert_eq ! ( node_0_details. next_splice_out_maximum_sat, expected_splice_out_max) ;
3749+
3750+ let expected_available_capacity_msat =
3751+ expected_outbound_capacity_msat - commit_tx_fee_sat ( FEERATE , 3 , & channel_type) * 1000 ;
3752+ assert_eq ! ( node_0_details. next_outbound_htlc_limit_msat, expected_available_capacity_msat) ;
3753+
3754+ let node_0_payment_msat = expected_available_capacity_msat;
3755+ send_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , node_0_payment_msat) ;
3756+
3757+ route_payment ( & nodes[ 1 ] , & [ & nodes[ 0 ] ] , SNEAKY_HTLC_MSAT ) ;
3758+ route_payment ( & nodes[ 1 ] , & [ & nodes[ 0 ] ] , SNEAKY_HTLC_MSAT ) ;
3759+
3760+ let node_0_details = & nodes[ 0 ] . node . list_channels ( ) [ 0 ] ;
3761+ let expected_outbound_capacity_msat = NODE_0_VALUE_TO_SELF_MSAT
3762+ - node_0_payment_msat
3763+ - NODE_1_SELECTED_CHANNEL_RESERVE_MSAT
3764+ - TOTAL_ANCHORS_MSAT ;
3765+ assert_eq ! ( node_0_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3766+ assert_eq ! (
3767+ node_0_details. outbound_capacity_msat,
3768+ commit_tx_fee_sat( FEERATE , 3 , & channel_type) * 1000
3769+ ) ;
3770+ assert_eq ! ( node_0_details. next_outbound_htlc_limit_msat, 0 ) ;
3771+
3772+ let local_balance_before_fee_sat =
3773+ NODE_0_VALUE_TO_SELF_MSAT / 1000 - node_0_payment_msat / 1000 - TOTAL_ANCHORS_MSAT / 1000 ;
3774+ let post_splice_delta_above_reserve = commit_tx_fee_sat ( FEERATE , 4 , & channel_type) ;
3775+ let divident_sat = local_balance_before_fee_sat * 100 + 100
3776+ - ( post_splice_delta_above_reserve * 100 )
3777+ - CHANNEL_VALUE_MSAT / 1000 ;
3778+ let expected_splice_out_max = ( divident_sat - 1 ) / 99 ;
3779+ assert_eq ! ( node_0_details. next_splice_out_maximum_sat, expected_splice_out_max) ;
3780+
3781+ let node_1_details = & nodes[ 1 ] . node . list_channels ( ) [ 0 ] ;
3782+ let expected_outbound_capacity_msat = NODE_1_VALUE_TO_SELF_MSAT + node_0_payment_msat
3783+ - 3 * SNEAKY_HTLC_MSAT
3784+ - NODE_0_SELECTED_CHANNEL_RESERVE_MSAT ;
3785+ assert_eq ! ( node_1_details. outbound_capacity_msat, expected_outbound_capacity_msat) ;
3786+ let ( htlc_success_tx_fee_sat, _htlc_timeout_tx_fee_sat) =
3787+ second_stage_tx_fees_sat ( & channel_type, FEERATE ) ;
3788+ let expected_available_capacity_msat =
3789+ ( NODE_0_DUST_LIMIT_MSAT / 1000 + htlc_success_tx_fee_sat) * 1000 - 1 ;
3790+ assert_eq ! ( node_1_details. next_outbound_htlc_limit_msat, expected_available_capacity_msat) ;
3791+ let expected_splice_out_max = NODE_1_VALUE_TO_SELF_MSAT / 1000 + node_0_payment_msat / 1000
3792+ - 3 * SNEAKY_HTLC_MSAT / 1000
3793+ - NODE_1_DUST_LIMIT_MSAT / 1000 ;
3794+ assert_eq ! ( node_1_details. next_splice_out_maximum_sat, expected_splice_out_max) ;
3795+ }
0 commit comments