@@ -46,7 +46,7 @@ use crate::ln::chan_utils::{
46
46
HolderCommitmentTransaction, ChannelTransactionParameters,
47
47
CounterpartyChannelTransactionParameters, MAX_HTLCS,
48
48
get_commitment_transaction_number_obscure_factor,
49
- ClosingTransaction, commit_tx_fee_sat, per_outbound_htlc_counterparty_commit_tx_fee_msat,
49
+ ClosingTransaction, commit_tx_fee_sat,
50
50
};
51
51
use crate::ln::chan_utils;
52
52
use crate::ln::onion_utils::HTLCFailReason;
@@ -866,6 +866,10 @@ struct HTLCStats {
866
866
pending_inbound_htlcs_value_msat: u64,
867
867
pending_outbound_htlcs_value_msat: u64,
868
868
on_counterparty_tx_dust_exposure_msat: u64,
869
+ // If the counterparty sets a feerate on the channel in excess of our dust_exposure_limiting_feerate,
870
+ // this will be set to the dust exposure that would result from us adding an additional nondust outbound
871
+ // htlc on the counterparty's commitment transaction.
872
+ extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat: Option<u64>,
869
873
on_holder_tx_dust_exposure_msat: u64,
870
874
outbound_holding_cell_msat: u64,
871
875
on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
@@ -3794,27 +3798,21 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3794
3798
.or(self.pending_update_fee.map(|(fee, _)| fee))
3795
3799
.unwrap_or(self.feerate_per_kw)
3796
3800
.checked_sub(dust_exposure_limiting_feerate);
3797
- if let Some(excess_feerate) = excess_feerate_opt {
3798
- let on_counterparty_tx_nondust_htlcs =
3799
- on_counterparty_tx_accepted_nondust_htlcs + on_counterparty_tx_offered_nondust_htlcs;
3800
- on_counterparty_tx_dust_exposure_msat +=
3801
- commit_tx_fee_sat(excess_feerate, on_counterparty_tx_nondust_htlcs, &self.channel_type) * 1000;
3802
- if !self.channel_type.supports_anchors_zero_fee_htlc_tx() {
3803
- on_counterparty_tx_dust_exposure_msat +=
3804
- on_counterparty_tx_accepted_nondust_htlcs as u64 * htlc_success_tx_weight(&self.channel_type)
3805
- * excess_feerate as u64 / 1000;
3806
- on_counterparty_tx_dust_exposure_msat +=
3807
- on_counterparty_tx_offered_nondust_htlcs as u64 * htlc_timeout_tx_weight(&self.channel_type)
3808
- * excess_feerate as u64 / 1000;
3809
- }
3810
- }
3801
+ let extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat = excess_feerate_opt.map(|excess_feerate| {
3802
+ let extra_htlc_dust_exposure = on_counterparty_tx_dust_exposure_msat
3803
+ + chan_utils::commit_and_htlc_tx_fees_sat(excess_feerate, on_counterparty_tx_accepted_nondust_htlcs + 1, on_counterparty_tx_offered_nondust_htlcs, &self.channel_type) * 1000;
3804
+ on_counterparty_tx_dust_exposure_msat
3805
+ += chan_utils::commit_and_htlc_tx_fees_sat(excess_feerate, on_counterparty_tx_accepted_nondust_htlcs, on_counterparty_tx_offered_nondust_htlcs, &self.channel_type) * 1000;
3806
+ extra_htlc_dust_exposure
3807
+ });
3811
3808
3812
3809
HTLCStats {
3813
3810
pending_inbound_htlcs: self.pending_inbound_htlcs.len(),
3814
3811
pending_outbound_htlcs,
3815
3812
pending_inbound_htlcs_value_msat,
3816
3813
pending_outbound_htlcs_value_msat,
3817
3814
on_counterparty_tx_dust_exposure_msat,
3815
+ extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat,
3818
3816
on_holder_tx_dust_exposure_msat,
3819
3817
outbound_holding_cell_msat,
3820
3818
on_holder_tx_outbound_holding_cell_htlcs_count,
@@ -4019,13 +4017,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4019
4017
context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000)
4020
4018
};
4021
4019
4022
- let excess_feerate_opt = self.feerate_per_kw.checked_sub(dust_exposure_limiting_feerate);
4023
- if let Some(excess_feerate) = excess_feerate_opt {
4024
- let htlc_dust_exposure_msat =
4025
- per_outbound_htlc_counterparty_commit_tx_fee_msat(excess_feerate, &context.channel_type);
4026
- let nondust_htlc_counterparty_tx_dust_exposure =
4027
- htlc_stats.on_counterparty_tx_dust_exposure_msat.saturating_add(htlc_dust_exposure_msat);
4028
- if nondust_htlc_counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
4020
+ if let Some(extra_htlc_dust_exposure) = htlc_stats.extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat {
4021
+ if extra_htlc_dust_exposure > max_dust_htlc_exposure_msat {
4029
4022
// If adding an extra HTLC would put us over the dust limit in total fees, we cannot
4030
4023
// send any non-dust HTLCs.
4031
4024
available_capacity_msat = cmp::min(available_capacity_msat, htlc_success_dust_limit * 1000);
@@ -7486,6 +7479,8 @@ impl<SP: Deref> FundedChannel<SP> where
7486
7479
})
7487
7480
}
7488
7481
7482
+ /// When this function is called, the HTLC is already irrevocably committed to the channel;
7483
+ /// this function determines whether to fail the HTLC, or forward / claim it.
7489
7484
pub fn can_accept_incoming_htlc<F: Deref, L: Deref>(
7490
7485
&self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L
7491
7486
) -> Result<(), (&'static str, u16)>
@@ -7500,33 +7495,19 @@ impl<SP: Deref> FundedChannel<SP> where
7500
7495
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
7501
7496
let htlc_stats = self.context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
7502
7497
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
7503
- let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
7504
- (0, 0)
7498
+ let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat;
7499
+ if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
7500
+ // Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction
7501
+ log_info!(logger, "Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx",
7502
+ on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7503
+ return Err(("Exceeded our total dust exposure limit on counterparty commitment tx", 0x1000|7))
7504
+ }
7505
+ let htlc_success_dust_limit = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
7506
+ 0
7505
7507
} else {
7506
7508
let dust_buffer_feerate = self.context.get_dust_buffer_feerate(None) as u64;
7507
- (dust_buffer_feerate * htlc_timeout_tx_weight(self.context.get_channel_type()) / 1000,
7508
- dust_buffer_feerate * htlc_success_tx_weight(self.context.get_channel_type()) / 1000)
7509
+ dust_buffer_feerate * htlc_success_tx_weight(self.context.get_channel_type()) / 1000
7509
7510
};
7510
- let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis;
7511
- if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats {
7512
- let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat;
7513
- if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
7514
- log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
7515
- on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7516
- return Err(("Exceeded our dust exposure limit on counterparty commitment tx", 0x1000|7))
7517
- }
7518
- } else {
7519
- let htlc_dust_exposure_msat =
7520
- per_outbound_htlc_counterparty_commit_tx_fee_msat(self.context.feerate_per_kw, &self.context.channel_type);
7521
- let counterparty_tx_dust_exposure =
7522
- htlc_stats.on_counterparty_tx_dust_exposure_msat.saturating_add(htlc_dust_exposure_msat);
7523
- if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
7524
- log_info!(logger, "Cannot accept value that would put our exposure to tx fee dust at {} over the limit {} on counterparty commitment tx",
7525
- counterparty_tx_dust_exposure, max_dust_htlc_exposure_msat);
7526
- return Err(("Exceeded our tx fee dust exposure limit on counterparty commitment tx", 0x1000|7))
7527
- }
7528
- }
7529
-
7530
7511
let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis;
7531
7512
if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
7532
7513
let on_holder_tx_dust_htlc_exposure_msat = htlc_stats.on_holder_tx_dust_exposure_msat;
0 commit comments