@@ -1998,7 +1998,7 @@ impl<Signer: Sign> Channel<Signer> {
1998
1998
}
1999
1999
2000
2000
/// 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 {
2002
2002
let mut stats = HTLCStats {
2003
2003
pending_htlcs : self . pending_inbound_htlcs . len ( ) as u32 ,
2004
2004
pending_htlcs_value_msat : 0 ,
@@ -2007,8 +2007,8 @@ impl<Signer: Sign> Channel<Signer> {
2007
2007
holding_cell_msat : 0 ,
2008
2008
} ;
2009
2009
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 ;
2012
2012
for ref htlc in self . pending_inbound_htlcs . iter ( ) {
2013
2013
stats. pending_htlcs_value_msat += htlc. amount_msat ;
2014
2014
if htlc. amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
@@ -2022,7 +2022,7 @@ impl<Signer: Sign> Channel<Signer> {
2022
2022
}
2023
2023
2024
2024
/// 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 {
2026
2026
let mut stats = HTLCStats {
2027
2027
pending_htlcs : self . pending_outbound_htlcs . len ( ) as u32 ,
2028
2028
pending_htlcs_value_msat : 0 ,
@@ -2031,8 +2031,8 @@ impl<Signer: Sign> Channel<Signer> {
2031
2031
holding_cell_msat : 0 ,
2032
2032
} ;
2033
2033
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 ;
2036
2036
for ref htlc in self . pending_outbound_htlcs . iter ( ) {
2037
2037
stats. pending_htlcs_value_msat += htlc. amount_msat ;
2038
2038
if htlc. amount_msat / 1000 < counterparty_dust_limit_success_sat {
@@ -2068,11 +2068,11 @@ impl<Signer: Sign> Channel<Signer> {
2068
2068
(
2069
2069
cmp:: max ( self . channel_value_satoshis as i64 * 1000
2070
2070
- 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
2072
2072
- Self :: get_holder_selected_channel_reserve_satoshis ( self . channel_value_satoshis ) as i64 * 1000 ,
2073
2073
0 ) as u64 ,
2074
2074
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
2076
2076
- self . counterparty_selected_channel_reserve_satoshis . unwrap_or ( 0 ) as i64 * 1000 ,
2077
2077
0 ) as u64
2078
2078
)
@@ -2291,8 +2291,8 @@ impl<Signer: Sign> Channel<Signer> {
2291
2291
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) ) ) ;
2292
2292
}
2293
2293
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 ) ;
2296
2296
if inbound_stats. pending_htlcs + 1 > OUR_MAX_HTLCS as u32 {
2297
2297
return Err ( ChannelError :: Close ( format ! ( "Remote tried to push more than our max accepted HTLCs ({})" , OUR_MAX_HTLCS ) ) ) ;
2298
2298
}
@@ -2321,7 +2321,7 @@ impl<Signer: Sign> Channel<Signer> {
2321
2321
}
2322
2322
}
2323
2323
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 ;
2325
2325
if msg. amount_msat / 1000 < exposure_dust_limit_timeout_sats {
2326
2326
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 ;
2327
2327
if on_counterparty_tx_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -2331,7 +2331,7 @@ impl<Signer: Sign> Channel<Signer> {
2331
2331
}
2332
2332
}
2333
2333
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 ;
2335
2335
if msg. amount_msat / 1000 < exposure_dust_limit_success_sats {
2336
2336
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 ;
2337
2337
if on_holder_tx_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -3080,8 +3080,8 @@ impl<Signer: Sign> Channel<Signer> {
3080
3080
}
3081
3081
3082
3082
// 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 ) ) ;
3085
3085
let keys = if let Ok ( keys) = self . build_holder_transaction_keys ( self . cur_holder_commitment_transaction_number ) { keys } else { return None ; } ;
3086
3086
let ( _, _, num_htlcs, _, holder_balance_msat, _) = self . build_commitment_transaction ( self . cur_holder_commitment_transaction_number , & keys, true , true , logger) ;
3087
3087
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> {
3092
3092
return None ;
3093
3093
}
3094
3094
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
+
3095
3107
if ( self . channel_state & ( ChannelState :: AwaitingRemoteRevoke as u32 | ChannelState :: MonitorUpdateFailed as u32 ) ) != 0 {
3096
3108
self . holding_cell_update_fee = Some ( feerate_per_kw) ;
3097
3109
return None ;
@@ -3271,16 +3283,16 @@ impl<Signer: Sign> Channel<Signer> {
3271
3283
return Err ( ChannelError :: Close ( "Peer sent update_fee when we needed a channel_reestablish" . to_owned ( ) ) ) ;
3272
3284
}
3273
3285
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 ) ;
3275
3287
3276
3288
self . pending_update_fee = Some ( ( msg. feerate_per_kw , FeeUpdateState :: RemoteAnnounced ) ) ;
3277
3289
self . update_time_counter += 1 ;
3278
3290
// If the feerate has increased over the previous dust buffer (note that
3279
3291
// `get_dust_buffer_feerate` considers the `pending_update_fee` status), check that we
3280
3292
// won't be pushed over our dust exposure limit by the feerate increase.
3281
3293
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 ) ;
3284
3296
let holder_tx_dust_exposure = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
3285
3297
let counterparty_tx_dust_exposure = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
3286
3298
if holder_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -3981,7 +3993,7 @@ impl<Signer: Sign> Channel<Signer> {
3981
3993
self . feerate_per_kw
3982
3994
}
3983
3995
3984
- pub fn get_dust_buffer_feerate ( & self ) -> u32 {
3996
+ pub fn get_dust_buffer_feerate ( & self , outbound_feerate_update : Option < u32 > ) -> u32 {
3985
3997
// When calculating our exposure to dust HTLCs, we assume that the channel feerate
3986
3998
// may, at any point, increase by at least 10 sat/vB (i.e 2530 sat/kWU) or 25%,
3987
3999
// whichever is higher. This ensures that we aren't suddenly exposed to significantly
@@ -3993,6 +4005,9 @@ impl<Signer: Sign> Channel<Signer> {
3993
4005
if let Some ( ( feerate, _) ) = self . pending_update_fee {
3994
4006
feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
3995
4007
}
4008
+ if let Some ( feerate) = outbound_feerate_update {
4009
+ feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
4010
+ }
3996
4011
cmp:: max ( 2530 , feerate_per_kw * 1250 / 1000 )
3997
4012
}
3998
4013
@@ -4655,8 +4670,8 @@ impl<Signer: Sign> Channel<Signer> {
4655
4670
return Err ( ChannelError :: Ignore ( "Cannot send an HTLC while disconnected from channel counterparty" . to_owned ( ) ) ) ;
4656
4671
}
4657
4672
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 ) ;
4660
4675
if outbound_stats. pending_htlcs + 1 > self . counterparty_max_accepted_htlcs as u32 {
4661
4676
return Err ( ChannelError :: Ignore ( format ! ( "Cannot push more than their max accepted HTLCs ({})" , self . counterparty_max_accepted_htlcs) ) ) ;
4662
4677
}
@@ -4677,7 +4692,7 @@ impl<Signer: Sign> Channel<Signer> {
4677
4692
}
4678
4693
}
4679
4694
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 ;
4681
4696
if amount_msat / 1000 < exposure_dust_limit_success_sats {
4682
4697
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;
4683
4698
if on_counterparty_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -4686,7 +4701,7 @@ impl<Signer: Sign> Channel<Signer> {
4686
4701
}
4687
4702
}
4688
4703
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 ;
4690
4705
if amount_msat / 1000 < exposure_dust_limit_timeout_sats {
4691
4706
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;
4692
4707
if on_holder_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
0 commit comments