@@ -1724,63 +1724,108 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1724
1724
( COMMITMENT_TX_BASE_WEIGHT + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC ) * self . feerate_per_kw as u64 / 1000 * 1000
1725
1725
}
1726
1726
1727
- // Get the commitment tx fee for the local (i.e our) next commitment transaction
1728
- // based on the number of pending HTLCs that are on track to be in our next
1729
- // commitment tx. `addl_htcs` is an optional parameter allowing the caller
1730
- // to add a number of additional HTLCs to the calculation. Note that dust
1731
- // HTLCs are excluded.
1732
- fn next_local_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1727
+ // Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
1728
+ // number of pending HTLCs that are on track to be in our next commitment tx, plus an additional
1729
+ // HTLC if `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs
1730
+ // are excluded.
1731
+ fn next_local_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , locally_offered : bool , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
1733
1732
assert ! ( self . channel_outbound) ;
1734
1733
1735
- let mut their_acked_htlcs = self . pending_inbound_htlcs . len ( ) ;
1734
+ let real_dust_limit_success_sat = ( self . feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1735
+ let real_dust_limit_timeout_sat = ( self . feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1736
+
1737
+ let mut addl_htlcs = 0 ;
1738
+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1739
+ if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1740
+ addl_htlcs += 1 ;
1741
+ } else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1742
+ addl_htlcs += 1 ;
1743
+ }
1744
+
1745
+ let mut included_htlcs = 0 ;
1746
+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1747
+ if htlc. amount_msat / 1000 < real_dust_limit_success_sat {
1748
+ continue
1749
+ }
1750
+ // We include LocalRemoved HTLCs here because we may still need to broadcast a commitment
1751
+ // transaction including this HTLC if it times out before they RAA.
1752
+ included_htlcs += 1 ;
1753
+ }
1754
+
1736
1755
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1737
- if htlc. amount_msat / 1000 <= self . holder_dust_limit_satoshis {
1756
+ if htlc. amount_msat / 1000 < real_dust_limit_timeout_sat {
1738
1757
continue
1739
1758
}
1740
1759
match htlc. state {
1741
- OutboundHTLCState :: Committed => their_acked_htlcs += 1 ,
1742
- OutboundHTLCState :: RemoteRemoved { ..} => their_acked_htlcs += 1 ,
1743
- OutboundHTLCState :: LocalAnnounced { ..} => their_acked_htlcs += 1 ,
1760
+ OutboundHTLCState :: LocalAnnounced { ..} => included_htlcs += 1 ,
1761
+ OutboundHTLCState :: Committed => included_htlcs += 1 ,
1762
+ OutboundHTLCState :: RemoteRemoved { ..} => included_htlcs += 1 ,
1763
+ // We don't include AwaitingRemoteRevokeToRemove HTLCs because our next commitment
1764
+ // transaction won't be generated until they send us their next RAA, which will mean
1765
+ // dropping any HTLCs in this state.
1744
1766
_ => { } ,
1745
1767
}
1746
1768
}
1747
1769
1748
1770
for htlc in self . holding_cell_htlc_updates . iter ( ) {
1749
1771
match htlc {
1750
- & HTLCUpdateAwaitingACK :: AddHTLC { .. } => their_acked_htlcs += 1 ,
1751
- _ => { } ,
1772
+ & HTLCUpdateAwaitingACK :: AddHTLC { amount_msat, .. } => {
1773
+ if amount_msat / 1000 < real_dust_limit_timeout_sat {
1774
+ continue
1775
+ }
1776
+ included_htlcs += 1
1777
+ } ,
1778
+ _ => { } , // Don't include claims/fails that are awaiting ack, because once we get the
1779
+ // ack we're guaranteed to never include them in commitment txs anymore.
1752
1780
}
1753
1781
}
1754
1782
1755
- self . commit_tx_fee_msat ( their_acked_htlcs + addl_htlcs)
1783
+ self . commit_tx_fee_msat ( included_htlcs + addl_htlcs)
1756
1784
}
1757
1785
1758
- // Get the commitment tx fee for the remote's next commitment transaction
1759
- // based on the number of pending HTLCs that are on track to be in their
1760
- // next commitment tx. `addl_htcs` is an optional parameter allowing the caller
1761
- // to add a number of additional HTLCs to the calculation. Note that dust HTLCs
1762
- // are excluded.
1763
- fn next_remote_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1786
+ // Get the commitment tx fee for the remote's next commitment transaction based on the number of
1787
+ // pending HTLCs that are on track to be in their next commitment tx, plus an additional HTLC if
1788
+ // `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs are
1789
+ // excluded.
1790
+ fn next_remote_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , locally_offered : bool , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
1764
1791
assert ! ( !self . channel_outbound) ;
1765
1792
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 ( ) ;
1793
+ let real_dust_limit_success_sat = ( self . feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1794
+ let real_dust_limit_timeout_sat = ( self . feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1795
+
1796
+ let mut addl_htlcs = 0 ;
1797
+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1798
+ if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1799
+ addl_htlcs += 1 ;
1800
+ } else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1801
+ addl_htlcs += 1 ;
1802
+ }
1803
+
1804
+ // When calculating the set of HTLCs which will be included in their next commitment_signed, all
1805
+ // non-dust inbound HTLCs are included (as all states imply it will be included) and only
1806
+ // committed outbound HTLCs, see below.
1807
+ let mut included_htlcs = 0 ;
1808
+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1809
+ if htlc. amount_msat / 1000 <= real_dust_limit_timeout_sat {
1810
+ continue
1811
+ }
1812
+ included_htlcs += 1 ;
1813
+ }
1814
+
1770
1815
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1771
- if htlc. amount_msat / 1000 <= self . counterparty_dust_limit_satoshis {
1816
+ if htlc. amount_msat / 1000 <= real_dust_limit_success_sat {
1772
1817
continue
1773
1818
}
1774
- // We only include outbound HTLCs if it will not be included in their next
1775
- // commitment_signed, i.e. if they've responded to us with an RAA after announcement.
1819
+ // We only include outbound HTLCs if it will not be included in their next commitment_signed,
1820
+ // i.e. if they've responded to us with an RAA after announcement.
1776
1821
match htlc. state {
1777
- OutboundHTLCState :: Committed => their_acked_htlcs += 1 ,
1778
- OutboundHTLCState :: RemoteRemoved { ..} => their_acked_htlcs += 1 ,
1822
+ OutboundHTLCState :: Committed => included_htlcs += 1 ,
1823
+ OutboundHTLCState :: RemoteRemoved { ..} => included_htlcs += 1 ,
1779
1824
_ => { } ,
1780
1825
}
1781
1826
}
1782
1827
1783
- self . commit_tx_fee_msat ( their_acked_htlcs + addl_htlcs)
1828
+ self . commit_tx_fee_msat ( included_htlcs + addl_htlcs)
1784
1829
}
1785
1830
1786
1831
pub fn update_add_htlc < F , L : Deref > ( & mut self , msg : & msgs:: UpdateAddHTLC , mut pending_forward_status : PendingHTLCStatus , create_pending_htlc_status : F , logger : & L ) -> Result < ( ) , ChannelError >
@@ -1848,8 +1893,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1848
1893
// Check that the remote can afford to pay for this HTLC on-chain at the current
1849
1894
// feerate_per_kw, while maintaining their channel reserve (as required by the spec).
1850
1895
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 )
1896
+ self . next_remote_commit_tx_fee_msat ( msg. amount_msat , false , None ) // Don't include the extra fee spike buffer HTLC in calculations
1853
1897
} ;
1854
1898
if pending_remote_value_msat - msg. amount_msat < remote_commit_tx_fee_msat {
1855
1899
return Err ( ChannelError :: Close ( "Remote HTLC add would not leave enough to pay for fees" . to_owned ( ) ) ) ;
@@ -1862,14 +1906,15 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1862
1906
}
1863
1907
1864
1908
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 ) ;
1909
+ // `2 *` and `Some(())` is for the fee spike buffer we keep for the remote. This deviates from
1910
+ // the spec because in the spec, the fee spike buffer requirement doesn't exist on the
1911
+ // receiver's side, only on the sender's.
1912
+ // Note that when we eventually remove support for fee updates and switch to anchor output
1913
+ // fees, we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep
1914
+ // the extra htlc when calculating the next remote commitment transaction fee as we should
1915
+ // still be able to afford adding this HTLC plus one more future HTLC, regardless of being
1916
+ // sensitive to fee spikes.
1917
+ let remote_fee_cost_incl_stuck_buffer_msat = 2 * self . next_remote_commit_tx_fee_msat ( msg. amount_msat , false , Some ( ( ) ) ) ;
1873
1918
if pending_remote_value_msat - msg. amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
1874
1919
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
1875
1920
// the HTLC, i.e. its status is already set to failing.
@@ -1878,9 +1923,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
1878
1923
}
1879
1924
} else {
1880
1925
// 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 ) ;
1926
+ let local_commit_tx_fee_msat = self . next_local_commit_tx_fee_msat ( msg. amount_msat , false , None ) ;
1884
1927
if self . value_to_self_msat < self . counterparty_selected_channel_reserve_satoshis * 1000 + local_commit_tx_fee_msat {
1885
1928
return Err ( ChannelError :: Close ( "Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value" . to_owned ( ) ) ) ;
1886
1929
}
@@ -3738,11 +3781,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3738
3781
3739
3782
if !self . channel_outbound {
3740
3783
// Check that we won't violate the remote channel reserve by adding this HTLC.
3741
-
3742
3784
let counterparty_balance_msat = self . channel_value_satoshis * 1000 - self . value_to_self_msat ;
3743
3785
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 ) ;
3786
+ let counterparty_commit_tx_fee_msat = self . next_remote_commit_tx_fee_msat ( amount_msat, true , None ) ;
3746
3787
if counterparty_balance_msat < holder_selected_chan_reserve_msat + counterparty_commit_tx_fee_msat {
3747
3788
return Err ( ChannelError :: Ignore ( "Cannot send value that would put counterparty balance under holder-announced channel reserve value" . to_owned ( ) ) ) ;
3748
3789
}
@@ -3753,10 +3794,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
3753
3794
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
3795
}
3755
3796
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.
3797
+ // `2 *` and extra HTLC are for the fee spike buffer.
3758
3798
let commit_tx_fee_msat = if self . channel_outbound {
3759
- 2 * self . next_local_commit_tx_fee_msat ( 1 + 1 )
3799
+ 2 * self . next_local_commit_tx_fee_msat ( amount_msat , true , Some ( ( ) ) )
3760
3800
} else { 0 } ;
3761
3801
if pending_value_to_self_msat - amount_msat < commit_tx_fee_msat {
3762
3802
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 +4627,73 @@ mod tests {
4587
4627
assert_eq ! ( open_channel_msg. feerate_per_kw, original_fee) ;
4588
4628
}
4589
4629
4630
+ #[ test]
4631
+ fn test_commit_tx_fees_with_dust ( ) {
4632
+ // Test that when calculating the local and remote commitment transaction fees, the correct
4633
+ // dust limits are used.
4634
+ let feeest = TestFeeEstimator { fee_est : 15000 } ;
4635
+ let secp_ctx = Secp256k1 :: new ( ) ;
4636
+ let seed = [ 42 ; 32 ] ;
4637
+ let network = Network :: Testnet ;
4638
+ let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
4639
+
4640
+ // Go through the flow of opening a channel between two nodes, making sure
4641
+ // they have different dust limits.
4642
+
4643
+ // Create Node A's channel pointing to Node B's pubkey
4644
+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
4645
+ let config = UserConfig :: default ( ) ;
4646
+ let mut node_a_chan = Channel :: < EnforcingChannelKeys > :: new_outbound ( & & feeest, & & keys_provider, node_b_node_id, 10000000 , 100000 , 42 , & config) . unwrap ( ) ;
4647
+
4648
+ // Create Node B's channel by receiving Node A's open_channel message
4649
+ // Make sure A's dust limit is as we expect.
4650
+ let open_channel_msg = node_a_chan. get_open_channel ( genesis_block ( network) . header . block_hash ( ) ) ;
4651
+ assert_eq ! ( open_channel_msg. dust_limit_satoshis, 1560 ) ;
4652
+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 7 ; 32 ] ) . unwrap ( ) ) ;
4653
+ let node_b_chan = Channel :: < EnforcingChannelKeys > :: new_from_req ( & & feeest, & & keys_provider, node_b_node_id, InitFeatures :: known ( ) , & open_channel_msg, 7 , & config) . unwrap ( ) ;
4654
+
4655
+ // Node B --> Node A: accept channel, explicitly setting B's dust limit.
4656
+ let mut accept_channel_msg = node_b_chan. get_accept_channel ( ) ;
4657
+ accept_channel_msg. dust_limit_satoshis = 546 ;
4658
+ node_a_chan. accept_channel ( & accept_channel_msg, & config, InitFeatures :: known ( ) ) . unwrap ( ) ;
4659
+
4660
+ // Put some inbound and outbound HTLCs in A's channel.
4661
+ let htlc_amount_msat = 11_092_000 ; // put an amount below A's effective dust amount but above B's.
4662
+ node_a_chan. pending_inbound_htlcs . push ( InboundHTLCOutput {
4663
+ htlc_id : 0 ,
4664
+ amount_msat : htlc_amount_msat,
4665
+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 42 ; 32 ] ) . into_inner ( ) ) ,
4666
+ cltv_expiry : 300000000 ,
4667
+ state : InboundHTLCState :: Committed ,
4668
+ } ) ;
4669
+
4670
+ node_a_chan. pending_outbound_htlcs . push ( OutboundHTLCOutput {
4671
+ htlc_id : 1 ,
4672
+ amount_msat : htlc_amount_msat, // put an amount below A's dust amount but above B's.
4673
+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 43 ; 32 ] ) . into_inner ( ) ) ,
4674
+ cltv_expiry : 200000000 ,
4675
+ state : OutboundHTLCState :: Committed ,
4676
+ source : HTLCSource :: OutboundRoute {
4677
+ path : Vec :: new ( ) ,
4678
+ session_priv : SecretKey :: from_slice ( & hex:: decode ( "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ) . unwrap ( ) [ ..] ) . unwrap ( ) ,
4679
+ first_hop_htlc_msat : 548 ,
4680
+ }
4681
+ } ) ;
4682
+
4683
+ // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
4684
+ // the dust limit check.
4685
+ let local_commit_tx_fee = node_a_chan. next_local_commit_tx_fee_msat ( htlc_amount_msat, true , None ) ;
4686
+ let local_commit_fee_0_htlcs = node_a_chan. commit_tx_fee_msat ( 0 ) ;
4687
+ assert_eq ! ( local_commit_tx_fee, local_commit_fee_0_htlcs) ;
4688
+
4689
+ // Finally, make sure that when Node A calculates the remote's commitment transaction fees, all
4690
+ // of the HTLCs are seen to be above the dust limit.
4691
+ node_a_chan. channel_outbound = false ;
4692
+ let remote_commit_fee_3_htlcs = node_a_chan. commit_tx_fee_msat ( 3 ) ;
4693
+ let remote_commit_tx_fee = node_a_chan. next_remote_commit_tx_fee_msat ( htlc_amount_msat, true , None ) ;
4694
+ assert_eq ! ( remote_commit_tx_fee, remote_commit_fee_3_htlcs) ;
4695
+ }
4696
+
4590
4697
#[ test]
4591
4698
fn channel_reestablish_no_updates ( ) {
4592
4699
let feeest = TestFeeEstimator { fee_est : 15000 } ;
0 commit comments