@@ -1729,10 +1729,23 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1729
1729
// commitment tx. `addl_htcs` is an optional parameter allowing the caller
1730
1730
// to add a number of additional HTLCs to the calculation. Note that dust
1731
1731
// HTLCs are excluded.
1732
- fn next_local_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1732
+ fn next_local_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
1733
1733
assert ! ( self . channel_outbound) ;
1734
1734
1735
- let mut their_acked_htlcs = self . pending_inbound_htlcs . len ( ) ;
1735
+ let mut addl_htlcs = 1 ;
1736
+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1737
+ if new_htlc_amount / 1000 <= self . holder_dust_limit_satoshis {
1738
+ addl_htlcs -= 1 ;
1739
+ }
1740
+
1741
+ let mut their_acked_htlcs = 0 ;
1742
+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1743
+ if htlc. amount_msat / 1000 <= self . holder_dust_limit_satoshis {
1744
+ continue
1745
+ }
1746
+ their_acked_htlcs += 1 ;
1747
+ }
1748
+
1736
1749
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1737
1750
if htlc. amount_msat / 1000 <= self . holder_dust_limit_satoshis {
1738
1751
continue
@@ -1760,13 +1773,27 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1760
1773
// next commitment tx. `addl_htcs` is an optional parameter allowing the caller
1761
1774
// to add a number of additional HTLCs to the calculation. Note that dust HTLCs
1762
1775
// are excluded.
1763
- fn next_remote_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1776
+ fn next_remote_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
1764
1777
assert ! ( !self . channel_outbound) ;
1765
1778
1766
- // When calculating the set of HTLCs which will be included in their next
1767
- // commitment_signed, all inbound HTLCs are included (as all states imply it will be
1768
- // included) and only committed outbound HTLCs, see below.
1769
- let mut their_acked_htlcs = self . pending_inbound_htlcs . len ( ) ;
1779
+ let mut addl_htlcs = 1 ;
1780
+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1781
+ if new_htlc_amount / 1000 <= self . counterparty_dust_limit_satoshis {
1782
+ addl_htlcs -= 1 ;
1783
+ }
1784
+
1785
+ // When calculating the set of HTLCs which will be included in their next commitment_signed, all
1786
+ // non-dust inbound HTLCs are included (as all states imply it will be included) and only
1787
+ // committed outbound HTLCs, see below.
1788
+ // let mut their_acked_htlcs = self.pending_inbound_htlcs.len();
1789
+ let mut their_acked_htlcs = 0 ;
1790
+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1791
+ if htlc. amount_msat / 1000 <= self . counterparty_dust_limit_satoshis {
1792
+ continue
1793
+ }
1794
+ their_acked_htlcs += 1 ;
1795
+ }
1796
+
1770
1797
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1771
1798
if htlc. amount_msat / 1000 <= self . counterparty_dust_limit_satoshis {
1772
1799
continue
@@ -1848,8 +1875,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1848
1875
// Check that the remote can afford to pay for this HTLC on-chain at the current
1849
1876
// feerate_per_kw, while maintaining their channel reserve (as required by the spec).
1850
1877
let remote_commit_tx_fee_msat = if self . channel_outbound { 0 } else {
1851
- // +1 for this HTLC.
1852
- self . next_remote_commit_tx_fee_msat ( 1 )
1878
+ self . next_remote_commit_tx_fee_msat ( msg. amount_msat , None ) // Don't include the extra fee spike buffer HTLC in calculations
1853
1879
} ;
1854
1880
if pending_remote_value_msat - msg. amount_msat < remote_commit_tx_fee_msat {
1855
1881
return Err ( ChannelError :: Close ( "Remote HTLC add would not leave enough to pay for fees" . to_owned ( ) ) ) ;
@@ -1862,14 +1888,15 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1862
1888
}
1863
1889
1864
1890
if !self . channel_outbound {
1865
- // `+1` for this HTLC, `2 *` and `+1` fee spike buffer we keep for the remote. This deviates from the
1866
- // spec because in the spec, the fee spike buffer requirement doesn't exist on the receiver's side,
1867
- // only on the sender's.
1868
- // Note that when we eventually remove support for fee updates and switch to anchor output fees,
1869
- // we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep the extra +1
1870
- // as we should still be able to afford adding this HTLC plus one more future HTLC, regardless of
1871
- // being sensitive to fee spikes.
1872
- let remote_fee_cost_incl_stuck_buffer_msat = 2 * self . next_remote_commit_tx_fee_msat ( 1 + 1 ) ;
1891
+ // `2 *` and `Some(())` is for the fee spike buffer we keep for the remote. This deviates from
1892
+ // the spec because in the spec, the fee spike buffer requirement doesn't exist on the
1893
+ // receiver's side, only on the sender's.
1894
+ // Note that when we eventually remove support for fee updates and switch to anchor output
1895
+ // fees, we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep
1896
+ // the extra htlc when calculating the next remote commitment transaction fee as we should
1897
+ // still be able to afford adding this HTLC plus one more future HTLC, regardless of being
1898
+ // sensitive to fee spikes.
1899
+ let remote_fee_cost_incl_stuck_buffer_msat = 2 * self . next_remote_commit_tx_fee_msat ( msg. amount_msat , Some ( ( ) ) ) ;
1873
1900
if pending_remote_value_msat - msg. amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
1874
1901
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
1875
1902
// the HTLC, i.e. its status is already set to failing.
@@ -1878,9 +1905,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1878
1905
}
1879
1906
} else {
1880
1907
// Check that they won't violate our local required channel reserve by adding this HTLC.
1881
-
1882
- // +1 for this HTLC.
1883
- let local_commit_tx_fee_msat = self . next_local_commit_tx_fee_msat ( 1 ) ;
1908
+ let local_commit_tx_fee_msat = self . next_local_commit_tx_fee_msat ( msg. amount_msat , None ) ;
1884
1909
if self . value_to_self_msat < self . counterparty_selected_channel_reserve_satoshis * 1000 + local_commit_tx_fee_msat {
1885
1910
return Err ( ChannelError :: Close ( "Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value" . to_owned ( ) ) ) ;
1886
1911
}
@@ -3738,11 +3763,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3738
3763
3739
3764
if !self . channel_outbound {
3740
3765
// Check that we won't violate the remote channel reserve by adding this HTLC.
3741
-
3742
3766
let counterparty_balance_msat = self . channel_value_satoshis * 1000 - self . value_to_self_msat ;
3743
3767
let holder_selected_chan_reserve_msat = Channel :: < ChanSigner > :: get_holder_selected_channel_reserve_satoshis ( self . channel_value_satoshis ) ;
3744
- // 1 additional HTLC corresponding to this HTLC.
3745
- let counterparty_commit_tx_fee_msat = self . next_remote_commit_tx_fee_msat ( 1 ) ;
3768
+ let counterparty_commit_tx_fee_msat = self . next_remote_commit_tx_fee_msat ( amount_msat, None ) ;
3746
3769
if counterparty_balance_msat < holder_selected_chan_reserve_msat + counterparty_commit_tx_fee_msat {
3747
3770
return Err ( ChannelError :: Ignore ( "Cannot send value that would put counterparty balance under holder-announced channel reserve value" . to_owned ( ) ) ) ;
3748
3771
}
@@ -3753,10 +3776,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3753
3776
return Err ( ChannelError :: Ignore ( format ! ( "Cannot send value that would overdraw remaining funds. Amount: {}, pending value to self {}" , amount_msat, pending_value_to_self_msat) ) ) ;
3754
3777
}
3755
3778
3756
- // The `+1` is for the HTLC currently being added to the commitment tx and
3757
- // the `2 *` and `+1` are for the fee spike buffer.
3779
+ // `2 *` and extra HTLC are for the fee spike buffer.
3758
3780
let commit_tx_fee_msat = if self . channel_outbound {
3759
- 2 * self . next_local_commit_tx_fee_msat ( 1 + 1 )
3781
+ 2 * self . next_local_commit_tx_fee_msat ( amount_msat , Some ( ( ) ) )
3760
3782
} else { 0 } ;
3761
3783
if pending_value_to_self_msat - amount_msat < commit_tx_fee_msat {
3762
3784
return Err ( ChannelError :: Ignore ( format ! ( "Cannot send value that would not leave enough to pay for fees. Pending value to self: {}. local_commit_tx_fee {}" , pending_value_to_self_msat, commit_tx_fee_msat) ) ) ;
@@ -4587,6 +4609,73 @@ mod tests {
4587
4609
assert_eq ! ( open_channel_msg. feerate_per_kw, original_fee) ;
4588
4610
}
4589
4611
4612
+ #[ test]
4613
+ fn test_commit_tx_fees_with_dust ( ) {
4614
+ // Test that when calculating the local and remote commitment transaction fees, the correct
4615
+ // dust limits are used.
4616
+ let feeest = TestFeeEstimator { fee_est : 15000 } ;
4617
+ let secp_ctx = Secp256k1 :: new ( ) ;
4618
+ let seed = [ 42 ; 32 ] ;
4619
+ let network = Network :: Testnet ;
4620
+ let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
4621
+
4622
+ // Go through the flow of opening a channel between two nodes, making sure
4623
+ // they have different dust limits.
4624
+
4625
+ // Create Node A's channel pointing to Node B's pubkey
4626
+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
4627
+ let config = UserConfig :: default ( ) ;
4628
+ let mut node_a_chan = Channel :: < EnforcingChannelKeys > :: new_outbound ( & & feeest, & & keys_provider, node_b_node_id, 10000000 , 100000 , 42 , & config) . unwrap ( ) ;
4629
+
4630
+ // Create Node B's channel by receiving Node A's open_channel message
4631
+ // Make sure A's dust limit is as we expect.
4632
+ let open_channel_msg = node_a_chan. get_open_channel ( genesis_block ( network) . header . block_hash ( ) ) ;
4633
+ assert_eq ! ( open_channel_msg. dust_limit_satoshis, 1560 ) ;
4634
+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 7 ; 32 ] ) . unwrap ( ) ) ;
4635
+ let node_b_chan = Channel :: < EnforcingChannelKeys > :: new_from_req ( & & feeest, & & keys_provider, node_b_node_id, InitFeatures :: known ( ) , & open_channel_msg, 7 , & config) . unwrap ( ) ;
4636
+
4637
+ // Node B --> Node A: accept channel, explicitly setting B's dust limit.
4638
+ let mut accept_channel_msg = node_b_chan. get_accept_channel ( ) ;
4639
+ accept_channel_msg. dust_limit_satoshis = 546 ;
4640
+ node_a_chan. accept_channel ( & accept_channel_msg, & config, InitFeatures :: known ( ) ) . unwrap ( ) ;
4641
+
4642
+ // Put some inbound and outbound HTLCs in A's channel.
4643
+ node_a_chan. pending_inbound_htlcs . push ( InboundHTLCOutput {
4644
+ htlc_id : 0 ,
4645
+ amount_msat : 547_000 , // put an amount below A's dust amount but above B's.
4646
+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 42 ; 32 ] ) . into_inner ( ) ) ,
4647
+ cltv_expiry : 300000000 ,
4648
+ state : InboundHTLCState :: Committed ,
4649
+ } ) ;
4650
+
4651
+ node_a_chan. pending_outbound_htlcs . push ( OutboundHTLCOutput {
4652
+ htlc_id : 1 ,
4653
+ amount_msat : 548_000 , // put an amount below A's dust amount but above B's.
4654
+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 43 ; 32 ] ) . into_inner ( ) ) ,
4655
+ cltv_expiry : 200000000 ,
4656
+ state : OutboundHTLCState :: Committed ,
4657
+ source : HTLCSource :: OutboundRoute {
4658
+ path : Vec :: new ( ) ,
4659
+ session_priv : SecretKey :: from_slice ( & hex:: decode ( "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ) . unwrap ( ) [ ..] ) . unwrap ( ) ,
4660
+ first_hop_htlc_msat : 548 ,
4661
+ }
4662
+ } ) ;
4663
+
4664
+ // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
4665
+ // the dust limit check.
4666
+ let htlc_amt = 549_000 ;
4667
+ let local_commit_tx_fee = node_a_chan. next_local_commit_tx_fee_msat ( htlc_amt, None ) ;
4668
+ let local_commit_fee_0_htlcs = node_a_chan. commit_tx_fee_msat ( 0 ) ;
4669
+ assert_eq ! ( local_commit_tx_fee, local_commit_fee_0_htlcs) ;
4670
+
4671
+ // Finally, make sure that when Node A calculates the remote's commitment transaction fees, all
4672
+ // of the HTLCs are seen to be above the dust limit.
4673
+ node_a_chan. channel_outbound = false ;
4674
+ let remote_commit_fee_3_htlcs = node_a_chan. commit_tx_fee_msat ( 3 ) ;
4675
+ let remote_commit_tx_fee = node_a_chan. next_remote_commit_tx_fee_msat ( htlc_amt, None ) ;
4676
+ assert_eq ! ( remote_commit_tx_fee, remote_commit_fee_3_htlcs) ;
4677
+ }
4678
+
4590
4679
#[ test]
4591
4680
fn channel_reestablish_no_updates ( ) {
4592
4681
let feeest = TestFeeEstimator { fee_est : 15000 } ;
0 commit comments