@@ -1998,7 +1998,7 @@ impl<Signer: Sign> Channel<Signer> {
19981998 }
19991999
20002000 /// Returns a HTLCStats about inbound pending htlcs
2001- fn get_inbound_pending_htlc_stats ( & self ) -> HTLCStats {
2001+ fn get_inbound_pending_htlc_stats ( & self , outbound_feerate_update : Option < u32 > ) -> HTLCStats {
20022002 let mut stats = HTLCStats {
20032003 pending_htlcs : self . pending_inbound_htlcs . len ( ) as u32 ,
20042004 pending_htlcs_value_msat : 0 ,
@@ -2007,8 +2007,8 @@ impl<Signer: Sign> Channel<Signer> {
20072007 holding_cell_msat : 0 ,
20082008 } ;
20092009
2010- let counterparty_dust_limit_timeout_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
2011- let holder_dust_limit_success_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
2010+ let counterparty_dust_limit_timeout_sat = ( self . get_dust_buffer_feerate ( outbound_feerate_update ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
2011+ let holder_dust_limit_success_sat = ( self . get_dust_buffer_feerate ( outbound_feerate_update ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
20122012 for ref htlc in self . pending_inbound_htlcs . iter ( ) {
20132013 stats. pending_htlcs_value_msat += htlc. amount_msat ;
20142014 if htlc. amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
@@ -2022,7 +2022,7 @@ impl<Signer: Sign> Channel<Signer> {
20222022 }
20232023
20242024 /// Returns a HTLCStats about pending outbound htlcs, *including* pending adds in our holding cell.
2025- fn get_outbound_pending_htlc_stats ( & self ) -> HTLCStats {
2025+ fn get_outbound_pending_htlc_stats ( & self , outbound_feerate_update : Option < u32 > ) -> HTLCStats {
20262026 let mut stats = HTLCStats {
20272027 pending_htlcs : self . pending_outbound_htlcs . len ( ) as u32 ,
20282028 pending_htlcs_value_msat : 0 ,
@@ -2031,8 +2031,8 @@ impl<Signer: Sign> Channel<Signer> {
20312031 holding_cell_msat : 0 ,
20322032 } ;
20332033
2034- let counterparty_dust_limit_success_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
2035- let holder_dust_limit_timeout_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
2034+ let counterparty_dust_limit_success_sat = ( self . get_dust_buffer_feerate ( outbound_feerate_update ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
2035+ let holder_dust_limit_timeout_sat = ( self . get_dust_buffer_feerate ( outbound_feerate_update ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
20362036 for ref htlc in self . pending_outbound_htlcs . iter ( ) {
20372037 stats. pending_htlcs_value_msat += htlc. amount_msat ;
20382038 if htlc. amount_msat / 1000 < counterparty_dust_limit_success_sat {
@@ -2068,11 +2068,11 @@ impl<Signer: Sign> Channel<Signer> {
20682068 (
20692069 cmp:: max ( self . channel_value_satoshis as i64 * 1000
20702070 - self . value_to_self_msat as i64
2071- - self . get_inbound_pending_htlc_stats ( ) . pending_htlcs_value_msat as i64
2071+ - self . get_inbound_pending_htlc_stats ( None ) . pending_htlcs_value_msat as i64
20722072 - Self :: get_holder_selected_channel_reserve_satoshis ( self . channel_value_satoshis ) as i64 * 1000 ,
20732073 0 ) as u64 ,
20742074 cmp:: max ( self . value_to_self_msat as i64
2075- - self . get_outbound_pending_htlc_stats ( ) . pending_htlcs_value_msat as i64
2075+ - self . get_outbound_pending_htlc_stats ( None ) . pending_htlcs_value_msat as i64
20762076 - self . counterparty_selected_channel_reserve_satoshis . unwrap_or ( 0 ) as i64 * 1000 ,
20772077 0 ) as u64
20782078 )
@@ -2291,8 +2291,8 @@ impl<Signer: Sign> Channel<Signer> {
22912291 return Err ( ChannelError :: Close ( format ! ( "Remote side tried to send less than our minimum HTLC value. Lower limit: ({}). Actual: ({})" , self . holder_htlc_minimum_msat, msg. amount_msat) ) ) ;
22922292 }
22932293
2294- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
2295- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
2294+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
2295+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
22962296 if inbound_stats. pending_htlcs + 1 > OUR_MAX_HTLCS as u32 {
22972297 return Err ( ChannelError :: Close ( format ! ( "Remote tried to push more than our max accepted HTLCs ({})" , OUR_MAX_HTLCS ) ) ) ;
22982298 }
@@ -2321,7 +2321,7 @@ impl<Signer: Sign> Channel<Signer> {
23212321 }
23222322 }
23232323
2324- let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
2324+ let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
23252325 if msg. amount_msat / 1000 < exposure_dust_limit_timeout_sats {
23262326 let on_counterparty_tx_dust_htlc_exposure_msat = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat + msg. amount_msat ;
23272327 if on_counterparty_tx_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -2331,7 +2331,7 @@ impl<Signer: Sign> Channel<Signer> {
23312331 }
23322332 }
23332333
2334- let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
2334+ let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
23352335 if msg. amount_msat / 1000 < exposure_dust_limit_success_sats {
23362336 let on_holder_tx_dust_htlc_exposure_msat = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat + msg. amount_msat ;
23372337 if on_holder_tx_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -3080,8 +3080,8 @@ impl<Signer: Sign> Channel<Signer> {
30803080 }
30813081
30823082 // Before proposing a feerate update, check that we can actually afford the new fee.
3083- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
3084- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
3083+ let inbound_stats = self . get_inbound_pending_htlc_stats ( Some ( feerate_per_kw ) ) ;
3084+ let outbound_stats = self . get_outbound_pending_htlc_stats ( Some ( feerate_per_kw ) ) ;
30853085 let keys = if let Ok ( keys) = self . build_holder_transaction_keys ( self . cur_holder_commitment_transaction_number ) { keys } else { return None ; } ;
30863086 let ( _, _, num_htlcs, _, holder_balance_msat, _) = self . build_commitment_transaction ( self . cur_holder_commitment_transaction_number , & keys, true , true , logger) ;
30873087 let total_fee_sat = Channel :: < Signer > :: commit_tx_fee_sat ( feerate_per_kw, num_htlcs + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize ) ;
@@ -3092,6 +3092,18 @@ impl<Signer: Sign> Channel<Signer> {
30923092 return None ;
30933093 }
30943094
3095+ // Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
3096+ let holder_tx_dust_exposure = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
3097+ let counterparty_tx_dust_exposure = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
3098+ if holder_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
3099+ log_debug ! ( logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure" , feerate_per_kw) ;
3100+ return None ;
3101+ }
3102+ if counterparty_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
3103+ log_debug ! ( logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure" , feerate_per_kw) ;
3104+ return None ;
3105+ }
3106+
30953107 if ( self . channel_state & ( ChannelState :: AwaitingRemoteRevoke as u32 | ChannelState :: MonitorUpdateFailed as u32 ) ) != 0 {
30963108 self . holding_cell_update_fee = Some ( feerate_per_kw) ;
30973109 return None ;
@@ -3271,16 +3283,16 @@ impl<Signer: Sign> Channel<Signer> {
32713283 return Err ( ChannelError :: Close ( "Peer sent update_fee when we needed a channel_reestablish" . to_owned ( ) ) ) ;
32723284 }
32733285 Channel :: < Signer > :: check_remote_fee ( fee_estimator, msg. feerate_per_kw ) ?;
3274- let feerate_over_dust_buffer = msg. feerate_per_kw > self . get_dust_buffer_feerate ( ) ;
3286+ let feerate_over_dust_buffer = msg. feerate_per_kw > self . get_dust_buffer_feerate ( None ) ;
32753287
32763288 self . pending_update_fee = Some ( ( msg. feerate_per_kw , FeeUpdateState :: RemoteAnnounced ) ) ;
32773289 self . update_time_counter += 1 ;
32783290 // If the feerate has increased over the previous dust buffer (note that
32793291 // `get_dust_buffer_feerate` considers the `pending_update_fee` status), check that we
32803292 // won't be pushed over our dust exposure limit by the feerate increase.
32813293 if feerate_over_dust_buffer {
3282- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
3283- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
3294+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
3295+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
32843296 let holder_tx_dust_exposure = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
32853297 let counterparty_tx_dust_exposure = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
32863298 if holder_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -3981,7 +3993,7 @@ impl<Signer: Sign> Channel<Signer> {
39813993 self . feerate_per_kw
39823994 }
39833995
3984- pub fn get_dust_buffer_feerate ( & self ) -> u32 {
3996+ pub fn get_dust_buffer_feerate ( & self , outbound_feerate_update : Option < u32 > ) -> u32 {
39853997 // When calculating our exposure to dust HTLCs, we assume that the channel feerate
39863998 // may, at any point, increase by at least 10 sat/vB (i.e 2530 sat/kWU) or 25%,
39873999 // whichever is higher. This ensures that we aren't suddenly exposed to significantly
@@ -3993,6 +4005,9 @@ impl<Signer: Sign> Channel<Signer> {
39934005 if let Some ( ( feerate, _) ) = self . pending_update_fee {
39944006 feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
39954007 }
4008+ if let Some ( feerate) = outbound_feerate_update {
4009+ feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
4010+ }
39964011 cmp:: max ( 2530 , feerate_per_kw * 1250 / 1000 )
39974012 }
39984013
@@ -4655,8 +4670,8 @@ impl<Signer: Sign> Channel<Signer> {
46554670 return Err ( ChannelError :: Ignore ( "Cannot send an HTLC while disconnected from channel counterparty" . to_owned ( ) ) ) ;
46564671 }
46574672
4658- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
4659- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
4673+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
4674+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
46604675 if outbound_stats. pending_htlcs + 1 > self . counterparty_max_accepted_htlcs as u32 {
46614676 return Err ( ChannelError :: Ignore ( format ! ( "Cannot push more than their max accepted HTLCs ({})" , self . counterparty_max_accepted_htlcs) ) ) ;
46624677 }
@@ -4677,7 +4692,7 @@ impl<Signer: Sign> Channel<Signer> {
46774692 }
46784693 }
46794694
4680- let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
4695+ let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
46814696 if amount_msat / 1000 < exposure_dust_limit_success_sats {
46824697 let on_counterparty_dust_htlc_exposure_msat = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat + amount_msat;
46834698 if on_counterparty_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -4686,7 +4701,7 @@ impl<Signer: Sign> Channel<Signer> {
46864701 }
46874702 }
46884703
4689- let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
4704+ let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
46904705 if amount_msat / 1000 < exposure_dust_limit_timeout_sats {
46914706 let on_holder_dust_htlc_exposure_msat = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat + amount_msat;
46924707 if on_holder_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
0 commit comments