Skip to content

Commit bb658c2

Browse files
committed
Remove extra sum of tx fee dust on the counterparty tx dust exposure
Previously, `get_pending_htlc_stats` did not account for the inbound htlc because `can_accept_incoming_htlc` was called before the htlc was irrevocably committed. But after commit d8d9dc7, `can_accept_incoming_htlc` is called only when the htlc is irrevocably committed, hence `get_pending_htlc_stats` does account for the inbound htlc. Nonetheless, in the case of a non-dust htlc, our calculation of the counterparty tx dust exposure still assumed that `get_pending_htlc_stats` did not account for the inbound htlc, causing us to add the dust exposure due to that inbound htlc twice. This commit removes this extra sum.
1 parent b1fc7d8 commit bb658c2

File tree

2 files changed

+19
-31
lines changed

2 files changed

+19
-31
lines changed

lightning/src/ln/channel.rs

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7303,6 +7303,8 @@ impl<SP: Deref> FundedChannel<SP> where
73037303
})
73047304
}
73057305

7306+
/// When this function is called, the HTLC is already irrevocably committed to the channel;
7307+
/// this function determines whether to fail the HTLC, or forward / claim it.
73067308
pub fn can_accept_incoming_htlc<F: Deref, L: Deref>(
73077309
&self, msg: &msgs::UpdateAddHTLC, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L
73087310
) -> Result<(), (&'static str, u16)>
@@ -7317,33 +7319,19 @@ impl<SP: Deref> FundedChannel<SP> where
73177319
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
73187320
let htlc_stats = self.context.get_pending_htlc_stats(None, dust_exposure_limiting_feerate);
73197321
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
7320-
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
7321-
(0, 0)
7322+
let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat;
7323+
if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
7324+
// Note that the total dust exposure includes both the dust HTLCs and the excess mining fees of the counterparty commitment transaction
7325+
log_info!(logger, "Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx",
7326+
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7327+
return Err(("Exceeded our total dust exposure limit on counterparty commitment tx", 0x1000|7))
7328+
}
7329+
let htlc_success_dust_limit = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
7330+
0
73227331
} else {
73237332
let dust_buffer_feerate = self.context.get_dust_buffer_feerate(None) as u64;
7324-
(dust_buffer_feerate * htlc_timeout_tx_weight(self.context.get_channel_type()) / 1000,
7325-
dust_buffer_feerate * htlc_success_tx_weight(self.context.get_channel_type()) / 1000)
7333+
dust_buffer_feerate * htlc_success_tx_weight(self.context.get_channel_type()) / 1000
73267334
};
7327-
let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis;
7328-
if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats {
7329-
let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat;
7330-
if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
7331-
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
7332-
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
7333-
return Err(("Exceeded our dust exposure limit on counterparty commitment tx", 0x1000|7))
7334-
}
7335-
} else {
7336-
let htlc_dust_exposure_msat =
7337-
per_outbound_htlc_counterparty_commit_tx_fee_msat(self.context.feerate_per_kw, &self.context.channel_type);
7338-
let counterparty_tx_dust_exposure =
7339-
htlc_stats.on_counterparty_tx_dust_exposure_msat.saturating_add(htlc_dust_exposure_msat);
7340-
if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
7341-
log_info!(logger, "Cannot accept value that would put our exposure to tx fee dust at {} over the limit {} on counterparty commitment tx",
7342-
counterparty_tx_dust_exposure, max_dust_htlc_exposure_msat);
7343-
return Err(("Exceeded our tx fee dust exposure limit on counterparty commitment tx", 0x1000|7))
7344-
}
7345-
}
7346-
73477335
let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis;
73487336
if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
73497337
let on_holder_tx_dust_htlc_exposure_msat = htlc_stats.on_holder_tx_dust_exposure_msat;

lightning/src/ln/functional_tests.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10300,13 +10300,13 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
1030010300
} else { 0 };
1030110301
let initial_feerate = if apply_excess_fee { 253 * 2 } else { 253 };
1030210302
let expected_dust_buffer_feerate = initial_feerate + 2530;
10303-
let mut commitment_tx_cost = commit_tx_fee_msat(initial_feerate - 253, nondust_htlc_count_in_limit, &ChannelTypeFeatures::empty());
10304-
commitment_tx_cost +=
10303+
let mut commitment_tx_cost_msat = commit_tx_fee_msat(initial_feerate - 253, nondust_htlc_count_in_limit, &ChannelTypeFeatures::empty());
10304+
commitment_tx_cost_msat +=
1030510305
if on_holder_tx {
1030610306
htlc_success_tx_weight(&ChannelTypeFeatures::empty())
1030710307
} else {
1030810308
htlc_timeout_tx_weight(&ChannelTypeFeatures::empty())
10309-
} * (initial_feerate as u64 - 253) / 1000 * nondust_htlc_count_in_limit;
10309+
} * (initial_feerate as u64 - 253) * nondust_htlc_count_in_limit;
1031010310
{
1031110311
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
1031210312
*feerate_lock = initial_feerate;
@@ -10315,8 +10315,8 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
1031510315
// Default test fee estimator rate is 253 sat/kw, so we set the multiplier to 5_000_000 / 253
1031610316
// to get roughly the same initial value as the default setting when this test was
1031710317
// originally written.
10318-
MaxDustHTLCExposure::FeeRateMultiplier((5_000_000 + commitment_tx_cost) / 253)
10319-
} else { MaxDustHTLCExposure::FixedLimitMsat(5_000_000 + commitment_tx_cost) };
10318+
MaxDustHTLCExposure::FeeRateMultiplier((5_000_000 + commitment_tx_cost_msat) / 253)
10319+
} else { MaxDustHTLCExposure::FixedLimitMsat(5_000_000 + commitment_tx_cost_msat) };
1032010320
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1032110321
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(config), None]);
1032210322
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -10460,8 +10460,8 @@ fn do_test_max_dust_htlc_exposure(dust_outbound_balance: bool, exposure_breach_e
1046010460
} else {
1046110461
// Outbound dust balance: 5200 sats
1046210462
nodes[0].logger.assert_log("lightning::ln::channel",
10463-
format!("Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
10464-
dust_htlc_on_counterparty_tx_msat * dust_htlc_on_counterparty_tx + commitment_tx_cost + 4,
10463+
format!("Cannot accept value that would put our total dust exposure at {} over the limit {} on counterparty commitment tx",
10464+
dust_htlc_on_counterparty_tx_msat * dust_htlc_on_counterparty_tx + commitment_tx_cost_msat + 4,
1046510465
max_dust_htlc_exposure_msat), 1);
1046610466
}
1046710467
} else if exposure_breach_event == ExposureEvent::AtUpdateFeeOutbound {

0 commit comments

Comments
 (0)