@@ -1913,16 +1913,16 @@ impl<Signer: Sign> Channel<Signer> {
19131913 }
19141914
19151915 /// Returns a HTLCStats about inbound pending htlcs
1916- fn get_inbound_pending_htlc_stats ( & self ) -> HTLCStats {
1916+ fn get_inbound_pending_htlc_stats ( & self , outbound_feerate_update : Option < u32 > ) -> HTLCStats {
19171917 let mut stats = HTLCStats {
19181918 pending_htlcs : self . pending_inbound_htlcs . len ( ) as u32 ,
19191919 pending_htlcs_value_msat : 0 ,
19201920 on_counterparty_tx_dust_exposure_msat : 0 ,
19211921 on_holder_tx_dust_exposure_msat : 0 ,
19221922 } ;
19231923
1924- let counterparty_dust_limit_timeout_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1925- let holder_dust_limit_success_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1924+ 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 ;
1925+ 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 ;
19261926 for ref htlc in self . pending_inbound_htlcs . iter ( ) {
19271927 stats. pending_htlcs_value_msat += htlc. amount_msat ;
19281928 if htlc. amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
@@ -1936,16 +1936,16 @@ impl<Signer: Sign> Channel<Signer> {
19361936 }
19371937
19381938 /// Returns a HTLCStats about pending outbound htlcs, *including* pending adds in our holding cell.
1939- fn get_outbound_pending_htlc_stats ( & self ) -> HTLCStats {
1939+ fn get_outbound_pending_htlc_stats ( & self , outbound_feerate_update : Option < u32 > ) -> HTLCStats {
19401940 let mut stats = HTLCStats {
19411941 pending_htlcs : self . pending_outbound_htlcs . len ( ) as u32 ,
19421942 pending_htlcs_value_msat : 0 ,
19431943 on_counterparty_tx_dust_exposure_msat : 0 ,
19441944 on_holder_tx_dust_exposure_msat : 0 ,
19451945 } ;
19461946
1947- let counterparty_dust_limit_success_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
1948- let holder_dust_limit_timeout_sat = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
1947+ 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 ;
1948+ 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 ;
19491949 for ref htlc in self . pending_outbound_htlcs . iter ( ) {
19501950 stats. pending_htlcs_value_msat += htlc. amount_msat ;
19511951 if htlc. amount_msat / 1000 < counterparty_dust_limit_success_sat {
@@ -1980,11 +1980,11 @@ impl<Signer: Sign> Channel<Signer> {
19801980 (
19811981 cmp:: max ( self . channel_value_satoshis as i64 * 1000
19821982 - self . value_to_self_msat as i64
1983- - self . get_inbound_pending_htlc_stats ( ) . pending_htlcs_value_msat as i64
1983+ - self . get_inbound_pending_htlc_stats ( None ) . pending_htlcs_value_msat as i64
19841984 - Self :: get_holder_selected_channel_reserve_satoshis ( self . channel_value_satoshis ) as i64 * 1000 ,
19851985 0 ) as u64 ,
19861986 cmp:: max ( self . value_to_self_msat as i64
1987- - self . get_outbound_pending_htlc_stats ( ) . pending_htlcs_value_msat as i64
1987+ - self . get_outbound_pending_htlc_stats ( None ) . pending_htlcs_value_msat as i64
19881988 - self . counterparty_selected_channel_reserve_satoshis . unwrap_or ( 0 ) as i64 * 1000 ,
19891989 0 ) as u64
19901990 )
@@ -2203,8 +2203,8 @@ impl<Signer: Sign> Channel<Signer> {
22032203 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) ) ) ;
22042204 }
22052205
2206- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
2207- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
2206+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
2207+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
22082208 if inbound_stats. pending_htlcs + 1 > OUR_MAX_HTLCS as u32 {
22092209 return Err ( ChannelError :: Close ( format ! ( "Remote tried to push more than our max accepted HTLCs ({})" , OUR_MAX_HTLCS ) ) ) ;
22102210 }
@@ -2233,7 +2233,7 @@ impl<Signer: Sign> Channel<Signer> {
22332233 }
22342234 }
22352235
2236- let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
2236+ let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
22372237 if msg. amount_msat / 1000 < exposure_dust_limit_timeout_sats {
22382238 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 ;
22392239 if on_counterparty_tx_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -2243,7 +2243,7 @@ impl<Signer: Sign> Channel<Signer> {
22432243 }
22442244 }
22452245
2246- let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
2246+ let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
22472247 if msg. amount_msat / 1000 < exposure_dust_limit_success_sats {
22482248 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 ;
22492249 if on_holder_tx_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -2977,8 +2977,8 @@ impl<Signer: Sign> Channel<Signer> {
29772977 }
29782978
29792979 // Before proposing a feerate update, check that we can actually afford the new fee.
2980- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
2981- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
2980+ let inbound_stats = self . get_inbound_pending_htlc_stats ( Some ( feerate_per_kw ) ) ;
2981+ let outbound_stats = self . get_outbound_pending_htlc_stats ( Some ( feerate_per_kw ) ) ;
29822982 // In case of a concurrent update_add_htlc proposed by our counterparty, we might
29832983 // not have enough balance value remaining to cover the onchain cost of this new
29842984 // HTLC weight. If this happens, our counterparty fails the reception of our
@@ -2996,6 +2996,18 @@ impl<Signer: Sign> Channel<Signer> {
29962996 return None ;
29972997 }
29982998
2999+ if feerate_per_kw > self . get_dust_buffer_feerate ( None ) {
3000+ // Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
3001+ let holder_tx_dust_exposure = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
3002+ let counterparty_tx_dust_exposure = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
3003+ if holder_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
3004+ return None ;
3005+ }
3006+ if counterparty_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
3007+ return None ;
3008+ }
3009+ }
3010+
29993011 if ( self . channel_state & ( ChannelState :: AwaitingRemoteRevoke as u32 | ChannelState :: MonitorUpdateFailed as u32 ) ) != 0 {
30003012 self . holding_cell_update_fee = Some ( feerate_per_kw) ;
30013013 return None ;
@@ -3163,16 +3175,16 @@ impl<Signer: Sign> Channel<Signer> {
31633175 return Err ( ChannelError :: Close ( "Peer sent update_fee when we needed a channel_reestablish" . to_owned ( ) ) ) ;
31643176 }
31653177 Channel :: < Signer > :: check_remote_fee ( fee_estimator, msg. feerate_per_kw ) ?;
3166- let feerate_over_dust_buffer = msg. feerate_per_kw > self . get_dust_buffer_feerate ( ) ;
3178+ let feerate_over_dust_buffer = msg. feerate_per_kw > self . get_dust_buffer_feerate ( None ) ;
31673179
31683180 self . pending_update_fee = Some ( ( msg. feerate_per_kw , FeeUpdateState :: RemoteAnnounced ) ) ;
31693181 self . update_time_counter += 1 ;
31703182 // If the feerate has increased over the previous dust buffer (note that
31713183 // `get_dust_buffer_feerate` considers the `pending_update_fee` status), check that we
31723184 // won't be pushed over our dust exposure limit by the feerate increase.
31733185 if feerate_over_dust_buffer {
3174- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
3175- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
3186+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
3187+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
31763188 let holder_tx_dust_exposure = inbound_stats. on_holder_tx_dust_exposure_msat + outbound_stats. on_holder_tx_dust_exposure_msat ;
31773189 let counterparty_tx_dust_exposure = inbound_stats. on_counterparty_tx_dust_exposure_msat + outbound_stats. on_counterparty_tx_dust_exposure_msat ;
31783190 if holder_tx_dust_exposure > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -3873,7 +3885,7 @@ impl<Signer: Sign> Channel<Signer> {
38733885 self . feerate_per_kw
38743886 }
38753887
3876- pub fn get_dust_buffer_feerate ( & self ) -> u32 {
3888+ pub fn get_dust_buffer_feerate ( & self , outbound_feerate_update : Option < u32 > ) -> u32 {
38773889 // When calculating our exposure to dust HTLCs, we assume that the channel feerate
38783890 // may, at any point, increase by at least 10 sat/vB (i.e 2530 sat/kWU) or 25%,
38793891 // whichever is higher. This ensures that we aren't suddenly exposed to significantly
@@ -3885,6 +3897,9 @@ impl<Signer: Sign> Channel<Signer> {
38853897 if let Some ( ( feerate, _) ) = self . pending_update_fee {
38863898 feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
38873899 }
3900+ if let Some ( feerate) = outbound_feerate_update {
3901+ feerate_per_kw = cmp:: max ( feerate_per_kw, feerate) ;
3902+ }
38883903 cmp:: max ( 2530 , feerate_per_kw * 1250 / 1000 )
38893904 }
38903905
@@ -4542,8 +4557,8 @@ impl<Signer: Sign> Channel<Signer> {
45424557 return Err ( ChannelError :: Ignore ( "Cannot send an HTLC while disconnected from channel counterparty" . to_owned ( ) ) ) ;
45434558 }
45444559
4545- let inbound_stats = self . get_inbound_pending_htlc_stats ( ) ;
4546- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
4560+ let inbound_stats = self . get_inbound_pending_htlc_stats ( None ) ;
4561+ let outbound_stats = self . get_outbound_pending_htlc_stats ( None ) ;
45474562 if outbound_stats. pending_htlcs + 1 > self . counterparty_max_accepted_htlcs as u32 {
45484563 return Err ( ChannelError :: Ignore ( format ! ( "Cannot push more than their max accepted HTLCs ({})" , self . counterparty_max_accepted_htlcs) ) ) ;
45494564 }
@@ -4563,7 +4578,7 @@ impl<Signer: Sign> Channel<Signer> {
45634578 }
45644579 }
45654580
4566- let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
4581+ let exposure_dust_limit_success_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 ) + self . counterparty_dust_limit_satoshis ;
45674582 if amount_msat / 1000 < exposure_dust_limit_success_sats {
45684583 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;
45694584 if on_counterparty_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -4572,7 +4587,7 @@ impl<Signer: Sign> Channel<Signer> {
45724587 }
45734588 }
45744589
4575- let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
4590+ let exposure_dust_limit_timeout_sats = ( self . get_dust_buffer_feerate ( None ) as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 ) + self . holder_dust_limit_satoshis ;
45764591 if amount_msat / 1000 < exposure_dust_limit_timeout_sats {
45774592 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;
45784593 if on_holder_dust_htlc_exposure_msat > self . get_max_dust_htlc_exposure_msat ( ) {
@@ -4754,13 +4769,13 @@ impl<Signer: Sign> Channel<Signer> {
47544769 }
47554770 }
47564771 }
4757-
4772+
47584773 if self . is_outbound ( ) {
47594774 // Log if we can't afford next remote commitment tx fee at pending outbound feerate update.
47604775 if let Some ( pending_feerate) = self . pending_update_fee {
47614776 assert_eq ! ( pending_feerate. 1 , FeeUpdateState :: Outbound ) ;
47624777 let next_total_fee = Channel :: < Signer > :: commit_tx_fee_sat ( pending_feerate. 0 , self . pending_inbound_htlcs . len ( ) + self . pending_outbound_htlcs . len ( ) ) ;
4763- let outbound_stats = self . get_outbound_pending_htlc_stats ( ) ;
4778+ let outbound_stats = self . get_outbound_pending_htlc_stats ( Some ( pending_feerate . 0 ) ) ;
47644779 let holder_balance_after_fee_sub_sats = ( self . value_to_self_msat / 1000 ) . checked_sub ( next_total_fee) . map ( |a| a. checked_sub ( outbound_stats. pending_htlcs_value_msat / 1000 ) ) . unwrap_or ( None ) . unwrap_or ( u64:: max_value ( ) ) ;
47654780 if holder_balance_after_fee_sub_sats < self . counterparty_selected_channel_reserve_satoshis . unwrap ( ) {
47664781 log_trace ! ( logger, "Outbound update_fee HTLC buffer overflow - counterparty should force-close this channel" ) ;
0 commit comments