@@ -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 ) ;
@@ -3091,6 +3091,21 @@ impl<Signer: Sign> Channel<Signer> {
3091
3091
return None ;
3092
3092
}
3093
3093
3094
+ // If the new outbound feerate is inferior to the dust buffer feerate, pending HTLCs
3095
+ // have been already evaluated with the dust buffer feerate and as such the proposed
3096
+ // feerate is not affecting our dust exposure.
3097
+ if feerate_per_kw > self . get_dust_buffer_feerate ( None ) {
3098
+ // Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
3099
+ let holder_tx_dust_exposure = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
3100
+ let counterparty_tx_dust_exposure = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
3101
+ if holder_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
3102
+ return None ;
3103
+ }
3104
+ if counterparty_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
3105
+ return None ;
3106
+ }
3107
+ }
3108
+
3094
3109
if ( self . channel_state & ( ChannelState :: AwaitingRemoteRevoke as u32 | ChannelState :: MonitorUpdateFailed as u32 ) ) != 0 {
3095
3110
self . holding_cell_update_fee = Some ( feerate_per_kw) ;
3096
3111
return None ;
@@ -3270,16 +3285,16 @@ impl<Signer: Sign> Channel<Signer> {
3270
3285
return Err ( ChannelError :: Close ( "Peer sent update_fee when we needed a channel_reestablish" . to_owned ( ) ) ) ;
3271
3286
}
3272
3287
Channel :: < Signer > :: check_remote_fee ( fee_estimator, msg. feerate_per_kw ) ?;
3273
- let feerate_over_dust_buffer = msg. feerate_per_kw > self . get_dust_buffer_feerate ( ) ;
3288
+ let feerate_over_dust_buffer = msg. feerate_per_kw > self . get_dust_buffer_feerate ( None ) ;
3274
3289
3275
3290
self . pending_update_fee = Some ( ( msg. feerate_per_kw , FeeUpdateState :: RemoteAnnounced ) ) ;
3276
3291
self . update_time_counter += 1 ;
3277
3292
// If the feerate has increased over the previous dust buffer (note that
3278
3293
// `get_dust_buffer_feerate` considers the `pending_update_fee` status), check that we
3279
3294
// won't be pushed over our dust exposure limit by the feerate increase.
3280
3295
if feerate_over_dust_buffer {
3281
- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
3282
- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
3296
+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
3297
+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
3283
3298
let holder_tx_dust_exposure = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
3284
3299
let counterparty_tx_dust_exposure = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
3285
3300
if holder_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -3980,7 +3995,7 @@ impl<Signer: Sign> Channel<Signer> {
3980
3995
self . feerate_per_kw
3981
3996
}
3982
3997
3983
- pub fn get_dust_buffer_feerate ( & self ) -> u32 {
3998
+ pub fn get_dust_buffer_feerate ( & self , outbound_feerate_update : Option < u32 > ) -> u32 {
3984
3999
// When calculating our exposure to dust HTLCs, we assume that the channel feerate
3985
4000
// may, at any point, increase by at least 10 sat/vB (i.e 2530 sat/kWU) or 25%,
3986
4001
// whichever is higher. This ensures that we aren't suddenly exposed to significantly
@@ -3992,6 +4007,9 @@ impl<Signer: Sign> Channel<Signer> {
3992
4007
if let Some ( ( feerate, _) ) = self . pending_update_fee {
3993
4008
feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
3994
4009
}
4010
+ if let Some ( feerate) = outbound_feerate_update {
4011
+ feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
4012
+ }
3995
4013
cmp:: max ( 2530 , feerate_per_kw * 1250 / 1000 )
3996
4014
}
3997
4015
@@ -4654,8 +4672,8 @@ impl<Signer: Sign> Channel<Signer> {
4654
4672
return Err ( ChannelError :: Ignore ( "Cannot send an HTLC while disconnected from channel counterparty" . to_owned ( ) ) ) ;
4655
4673
}
4656
4674
4657
- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
4658
- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
4675
+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
4676
+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
4659
4677
if outbound_stats. pending_htlcs + 1 > self . counterparty_max_accepted_htlcs as u32 {
4660
4678
return Err ( ChannelError :: Ignore ( format ! ( "Cannot push more than their max accepted HTLCs ({})" , self . counterparty_max_accepted_htlcs) ) ) ;
4661
4679
}
@@ -4676,7 +4694,7 @@ impl<Signer: Sign> Channel<Signer> {
4676
4694
}
4677
4695
}
4678
4696
4679
- let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
4697
+ let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
4680
4698
if amount_msat / 1000 < exposure_dust_limit_success_sats {
4681
4699
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;
4682
4700
if on_counterparty_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -4685,7 +4703,7 @@ impl<Signer: Sign> Channel<Signer> {
4685
4703
}
4686
4704
}
4687
4705
4688
- let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
4706
+ let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
4689
4707
if amount_msat / 1000 < exposure_dust_limit_timeout_sats {
4690
4708
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;
4691
4709
if on_holder_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
0 commit comments