@@ -1684,63 +1684,108 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
16841684 ( COMMITMENT_TX_BASE_WEIGHT + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC ) * self . feerate_per_kw as u64 / 1000 * 1000
16851685 }
16861686
1687- // Get the commitment tx fee for the local (i.e our) next commitment transaction
1688- // based on the number of pending HTLCs that are on track to be in our next
1689- // commitment tx. `addl_htcs` is an optional parameter allowing the caller
1690- // to add a number of additional HTLCs to the calculation. Note that dust
1691- // HTLCs are excluded.
1692- fn next_local_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1687+ // Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
1688+ // number of pending HTLCs that are on track to be in our next commitment tx, plus an additional
1689+ // HTLC if `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs
1690+ // are excluded.
1691+ fn next_local_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , locally_offered : bool , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
16931692 assert ! ( self . is_outbound( ) ) ;
16941693
1695- let mut their_acked_htlcs = self . pending_inbound_htlcs . len ( ) ;
1694+ let real_dust_limit_success_sat = ( self . feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1695+ let real_dust_limit_timeout_sat = ( self . feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1696+
1697+ let mut addl_htlcs = 0 ;
1698+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1699+ if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1700+ addl_htlcs += 1 ;
1701+ } else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1702+ addl_htlcs += 1 ;
1703+ }
1704+
1705+ let mut included_htlcs = 0 ;
1706+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1707+ if htlc. amount_msat / 1000 < real_dust_limit_success_sat {
1708+ continue
1709+ }
1710+ // We include LocalRemoved HTLCs here because we may still need to broadcast a commitment
1711+ // transaction including this HTLC if it times out before they RAA.
1712+ included_htlcs += 1 ;
1713+ }
1714+
16961715 for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1697- if htlc. amount_msat / 1000 <= self . holder_dust_limit_satoshis {
1716+ if htlc. amount_msat / 1000 < real_dust_limit_timeout_sat {
16981717 continue
16991718 }
17001719 match htlc. state {
1701- OutboundHTLCState :: Committed => their_acked_htlcs += 1 ,
1702- OutboundHTLCState :: RemoteRemoved { ..} => their_acked_htlcs += 1 ,
1703- OutboundHTLCState :: LocalAnnounced { ..} => their_acked_htlcs += 1 ,
1720+ OutboundHTLCState :: LocalAnnounced { ..} => included_htlcs += 1 ,
1721+ OutboundHTLCState :: Committed => included_htlcs += 1 ,
1722+ OutboundHTLCState :: RemoteRemoved { ..} => included_htlcs += 1 ,
1723+ // We don't include AwaitingRemoteRevokeToRemove HTLCs because our next commitment
1724+ // transaction won't be generated until they send us their next RAA, which will mean
1725+ // dropping any HTLCs in this state.
17041726 _ => { } ,
17051727 }
17061728 }
17071729
17081730 for htlc in self . holding_cell_htlc_updates . iter ( ) {
17091731 match htlc {
1710- & HTLCUpdateAwaitingACK :: AddHTLC { .. } => their_acked_htlcs += 1 ,
1711- _ => { } ,
1732+ & HTLCUpdateAwaitingACK :: AddHTLC { amount_msat, .. } => {
1733+ if amount_msat / 1000 < real_dust_limit_timeout_sat {
1734+ continue
1735+ }
1736+ included_htlcs += 1
1737+ } ,
1738+ _ => { } , // Don't include claims/fails that are awaiting ack, because once we get the
1739+ // ack we're guaranteed to never include them in commitment txs anymore.
17121740 }
17131741 }
17141742
1715- self . commit_tx_fee_msat ( their_acked_htlcs + addl_htlcs)
1743+ self . commit_tx_fee_msat ( included_htlcs + addl_htlcs)
17161744 }
17171745
1718- // Get the commitment tx fee for the remote's next commitment transaction
1719- // based on the number of pending HTLCs that are on track to be in their
1720- // next commitment tx. `addl_htcs` is an optional parameter allowing the caller
1721- // to add a number of additional HTLCs to the calculation. Note that dust HTLCs
1722- // are excluded.
1723- fn next_remote_commit_tx_fee_msat ( & self , addl_htlcs : usize ) -> u64 {
1746+ // Get the commitment tx fee for the remote's next commitment transaction based on the number of
1747+ // pending HTLCs that are on track to be in their next commitment tx, plus an additional HTLC if
1748+ // `fee_spike_buffer_htlc` is Some, plus a new HTLC given by `new_htlc_amount`. Dust HTLCs are
1749+ // excluded.
1750+ fn next_remote_commit_tx_fee_msat ( & self , new_htlc_amount : u64 , locally_offered : bool , fee_spike_buffer_htlc : Option < ( ) > ) -> u64 {
17241751 assert ! ( !self . is_outbound( ) ) ;
17251752
1726- // When calculating the set of HTLCs which will be included in their next
1727- // commitment_signed, all inbound HTLCs are included (as all states imply it will be
1728- // included) and only committed outbound HTLCs, see below.
1729- let mut their_acked_htlcs = self . pending_inbound_htlcs . len ( ) ;
1753+ let real_dust_limit_success_sat = ( self . feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1754+ let real_dust_limit_timeout_sat = ( self . feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1755+
1756+ let mut addl_htlcs = 0 ;
1757+ if fee_spike_buffer_htlc. is_some ( ) { addl_htlcs += 1 ; }
1758+ if locally_offered && new_htlc_amount / 1000 >= real_dust_limit_success_sat {
1759+ addl_htlcs += 1 ;
1760+ } else if !locally_offered && new_htlc_amount / 1000 >= real_dust_limit_timeout_sat {
1761+ addl_htlcs += 1 ;
1762+ }
1763+
1764+ // When calculating the set of HTLCs which will be included in their next commitment_signed, all
1765+ // non-dust inbound HTLCs are included (as all states imply it will be included) and only
1766+ // committed outbound HTLCs, see below.
1767+ let mut included_htlcs = 0 ;
1768+ for ref htlc in self . pending_inbound_htlcs . iter ( ) {
1769+ if htlc. amount_msat / 1000 <= real_dust_limit_timeout_sat {
1770+ continue
1771+ }
1772+ included_htlcs += 1 ;
1773+ }
1774+
17301775 for ref htlc in self . pending_outbound_htlcs . iter ( ) {
1731- if htlc. amount_msat / 1000 <= self . counterparty_dust_limit_satoshis {
1776+ if htlc. amount_msat / 1000 <= real_dust_limit_success_sat {
17321777 continue
17331778 }
1734- // We only include outbound HTLCs if it will not be included in their next
1735- // commitment_signed, i.e. if they've responded to us with an RAA after announcement.
1779+ // We only include outbound HTLCs if it will not be included in their next commitment_signed,
1780+ // i.e. if they've responded to us with an RAA after announcement.
17361781 match htlc. state {
1737- OutboundHTLCState :: Committed => their_acked_htlcs += 1 ,
1738- OutboundHTLCState :: RemoteRemoved { ..} => their_acked_htlcs += 1 ,
1782+ OutboundHTLCState :: Committed => included_htlcs += 1 ,
1783+ OutboundHTLCState :: RemoteRemoved { ..} => included_htlcs += 1 ,
17391784 _ => { } ,
17401785 }
17411786 }
17421787
1743- self . commit_tx_fee_msat ( their_acked_htlcs + addl_htlcs)
1788+ self . commit_tx_fee_msat ( included_htlcs + addl_htlcs)
17441789 }
17451790
17461791 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 >
@@ -1808,8 +1853,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
18081853 // Check that the remote can afford to pay for this HTLC on-chain at the current
18091854 // feerate_per_kw, while maintaining their channel reserve (as required by the spec).
18101855 let remote_commit_tx_fee_msat = if self . is_outbound ( ) { 0 } else {
1811- // +1 for this HTLC.
1812- self . next_remote_commit_tx_fee_msat ( 1 )
1856+ self . next_remote_commit_tx_fee_msat ( msg. amount_msat , false , None ) // Don't include the extra fee spike buffer HTLC in calculations
18131857 } ;
18141858 if pending_remote_value_msat - msg. amount_msat < remote_commit_tx_fee_msat {
18151859 return Err ( ChannelError :: Close ( "Remote HTLC add would not leave enough to pay for fees" . to_owned ( ) ) ) ;
@@ -1822,14 +1866,15 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
18221866 }
18231867
18241868 if !self . is_outbound ( ) {
1825- // `+1` for this HTLC, `2 *` and `+1` fee spike buffer we keep for the remote. This deviates from the
1826- // spec because in the spec, the fee spike buffer requirement doesn't exist on the receiver's side,
1827- // only on the sender's.
1828- // Note that when we eventually remove support for fee updates and switch to anchor output fees,
1829- // we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep the extra +1
1830- // as we should still be able to afford adding this HTLC plus one more future HTLC, regardless of
1831- // being sensitive to fee spikes.
1832- let remote_fee_cost_incl_stuck_buffer_msat = 2 * self . next_remote_commit_tx_fee_msat ( 1 + 1 ) ;
1869+ // `2 *` and `Some(())` is for the fee spike buffer we keep for the remote. This deviates from
1870+ // the spec because in the spec, the fee spike buffer requirement doesn't exist on the
1871+ // receiver's side, only on the sender's.
1872+ // Note that when we eventually remove support for fee updates and switch to anchor output
1873+ // fees, we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep
1874+ // the extra htlc when calculating the next remote commitment transaction fee as we should
1875+ // still be able to afford adding this HTLC plus one more future HTLC, regardless of being
1876+ // sensitive to fee spikes.
1877+ let remote_fee_cost_incl_stuck_buffer_msat = 2 * self . next_remote_commit_tx_fee_msat ( msg. amount_msat , false , Some ( ( ) ) ) ;
18331878 if pending_remote_value_msat - msg. amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
18341879 // Note that if the pending_forward_status is not updated here, then it's because we're already failing
18351880 // the HTLC, i.e. its status is already set to failing.
@@ -1838,9 +1883,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
18381883 }
18391884 } else {
18401885 // Check that they won't violate our local required channel reserve by adding this HTLC.
1841-
1842- // +1 for this HTLC.
1843- let local_commit_tx_fee_msat = self . next_local_commit_tx_fee_msat ( 1 ) ;
1886+ let local_commit_tx_fee_msat = self . next_local_commit_tx_fee_msat ( msg. amount_msat , false , None ) ;
18441887 if self . value_to_self_msat < self . counterparty_selected_channel_reserve_satoshis * 1000 + local_commit_tx_fee_msat {
18451888 return Err ( ChannelError :: Close ( "Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value" . to_owned ( ) ) ) ;
18461889 }
@@ -3720,11 +3763,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
37203763
37213764 if !self . is_outbound ( ) {
37223765 // Check that we won't violate the remote channel reserve by adding this HTLC.
3723-
37243766 let counterparty_balance_msat = self . channel_value_satoshis * 1000 - self . value_to_self_msat ;
37253767 let holder_selected_chan_reserve_msat = Channel :: < ChanSigner > :: get_holder_selected_channel_reserve_satoshis ( self . channel_value_satoshis ) ;
3726- // 1 additional HTLC corresponding to this HTLC.
3727- 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, true , None ) ;
37283769 if counterparty_balance_msat < holder_selected_chan_reserve_msat + counterparty_commit_tx_fee_msat {
37293770 return Err ( ChannelError :: Ignore ( "Cannot send value that would put counterparty balance under holder-announced channel reserve value" . to_owned ( ) ) ) ;
37303771 }
@@ -3735,10 +3776,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
37353776 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) ) ) ;
37363777 }
37373778
3738- // The `+1` is for the HTLC currently being added to the commitment tx and
3739- // the `2 *` and `+1` are for the fee spike buffer.
3779+ // `2 *` and extra HTLC are for the fee spike buffer.
37403780 let commit_tx_fee_msat = if self . is_outbound ( ) {
3741- 2 * self . next_local_commit_tx_fee_msat ( 1 + 1 )
3781+ 2 * self . next_local_commit_tx_fee_msat ( amount_msat , true , Some ( ( ) ) )
37423782 } else { 0 } ;
37433783 if pending_value_to_self_msat - amount_msat < commit_tx_fee_msat {
37443784 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) ) ) ;
@@ -4575,6 +4615,73 @@ mod tests {
45754615 assert_eq ! ( open_channel_msg. feerate_per_kw, original_fee) ;
45764616 }
45774617
4618+ #[ test]
4619+ fn test_commit_tx_fees_with_dust ( ) {
4620+ // Test that when calculating the local and remote commitment transaction fees, the correct
4621+ // dust limits are used.
4622+ let feeest = TestFeeEstimator { fee_est : 15000 } ;
4623+ let secp_ctx = Secp256k1 :: new ( ) ;
4624+ let seed = [ 42 ; 32 ] ;
4625+ let network = Network :: Testnet ;
4626+ let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
4627+
4628+ // Go through the flow of opening a channel between two nodes, making sure
4629+ // they have different dust limits.
4630+
4631+ // Create Node A's channel pointing to Node B's pubkey
4632+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 42 ; 32 ] ) . unwrap ( ) ) ;
4633+ let config = UserConfig :: default ( ) ;
4634+ let mut node_a_chan = Channel :: < EnforcingChannelKeys > :: new_outbound ( & & feeest, & & keys_provider, node_b_node_id, 10000000 , 100000 , 42 , & config) . unwrap ( ) ;
4635+
4636+ // Create Node B's channel by receiving Node A's open_channel message
4637+ // Make sure A's dust limit is as we expect.
4638+ let open_channel_msg = node_a_chan. get_open_channel ( genesis_block ( network) . header . block_hash ( ) ) ;
4639+ assert_eq ! ( open_channel_msg. dust_limit_satoshis, 1560 ) ;
4640+ let node_b_node_id = PublicKey :: from_secret_key ( & secp_ctx, & SecretKey :: from_slice ( & [ 7 ; 32 ] ) . unwrap ( ) ) ;
4641+ let node_b_chan = Channel :: < EnforcingChannelKeys > :: new_from_req ( & & feeest, & & keys_provider, node_b_node_id, InitFeatures :: known ( ) , & open_channel_msg, 7 , & config) . unwrap ( ) ;
4642+
4643+ // Node B --> Node A: accept channel, explicitly setting B's dust limit.
4644+ let mut accept_channel_msg = node_b_chan. get_accept_channel ( ) ;
4645+ accept_channel_msg. dust_limit_satoshis = 546 ;
4646+ node_a_chan. accept_channel ( & accept_channel_msg, & config, InitFeatures :: known ( ) ) . unwrap ( ) ;
4647+
4648+ // Put some inbound and outbound HTLCs in A's channel.
4649+ let htlc_amount_msat = 11_092_000 ; // put an amount below A's effective dust amount but above B's.
4650+ node_a_chan. pending_inbound_htlcs . push ( InboundHTLCOutput {
4651+ htlc_id : 0 ,
4652+ amount_msat : htlc_amount_msat,
4653+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 42 ; 32 ] ) . into_inner ( ) ) ,
4654+ cltv_expiry : 300000000 ,
4655+ state : InboundHTLCState :: Committed ,
4656+ } ) ;
4657+
4658+ node_a_chan. pending_outbound_htlcs . push ( OutboundHTLCOutput {
4659+ htlc_id : 1 ,
4660+ amount_msat : htlc_amount_msat, // put an amount below A's dust amount but above B's.
4661+ payment_hash : PaymentHash ( Sha256 :: hash ( & [ 43 ; 32 ] ) . into_inner ( ) ) ,
4662+ cltv_expiry : 200000000 ,
4663+ state : OutboundHTLCState :: Committed ,
4664+ source : HTLCSource :: OutboundRoute {
4665+ path : Vec :: new ( ) ,
4666+ session_priv : SecretKey :: from_slice ( & hex:: decode ( "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ) . unwrap ( ) [ ..] ) . unwrap ( ) ,
4667+ first_hop_htlc_msat : 548 ,
4668+ }
4669+ } ) ;
4670+
4671+ // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
4672+ // the dust limit check.
4673+ let local_commit_tx_fee = node_a_chan. next_local_commit_tx_fee_msat ( htlc_amount_msat, true , None ) ;
4674+ let local_commit_fee_0_htlcs = node_a_chan. commit_tx_fee_msat ( 0 ) ;
4675+ assert_eq ! ( local_commit_tx_fee, local_commit_fee_0_htlcs) ;
4676+
4677+ // Finally, make sure that when Node A calculates the remote's commitment transaction fees, all
4678+ // of the HTLCs are seen to be above the dust limit.
4679+ node_a_chan. channel_transaction_parameters . is_outbound_from_holder = false ;
4680+ let remote_commit_fee_3_htlcs = node_a_chan. commit_tx_fee_msat ( 3 ) ;
4681+ let remote_commit_tx_fee = node_a_chan. next_remote_commit_tx_fee_msat ( htlc_amount_msat, true , None ) ;
4682+ assert_eq ! ( remote_commit_tx_fee, remote_commit_fee_3_htlcs) ;
4683+ }
4684+
45784685 #[ test]
45794686 fn channel_reestablish_no_updates ( ) {
45804687 let feeest = TestFeeEstimator { fee_est : 15000 } ;
0 commit comments