Skip to content

Commit 6efa91b

Browse files
committed
Account for zero fee HTLC transaction within dust limit calculation
With the zero fee HTLC transaction anchors variant, HTLCs can no longer be trimmed due to their amount being too low to have a mempool valid HTLC transaction. Now they can only be trimmed based on the dust limit of each party within the channel.
1 parent b8cc9ce commit 6efa91b

File tree

1 file changed

+64
-14
lines changed

1 file changed

+64
-14
lines changed

lightning/src/ln/channel.rs

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,7 +1466,12 @@ impl<Signer: Sign> Channel<Signer> {
14661466
($htlc: expr, $outbound: expr, $source: expr, $state_name: expr) => {
14671467
if $outbound == local { // "offered HTLC output"
14681468
let htlc_in_tx = get_htlc_in_commitment!($htlc, true);
1469-
if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + (feerate_per_kw as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) {
1469+
let htlc_tx_fee = if self.opt_anchors() {
1470+
0
1471+
} else {
1472+
feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000
1473+
};
1474+
if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee {
14701475
log_trace!(logger, " ...including {} {} HTLC {} (hash {}) with value {}", if $outbound { "outbound" } else { "inbound" }, $state_name, $htlc.htlc_id, log_bytes!($htlc.payment_hash.0), $htlc.amount_msat);
14711476
included_non_dust_htlcs.push((htlc_in_tx, $source));
14721477
} else {
@@ -1475,7 +1480,12 @@ impl<Signer: Sign> Channel<Signer> {
14751480
}
14761481
} else {
14771482
let htlc_in_tx = get_htlc_in_commitment!($htlc, false);
1478-
if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + (feerate_per_kw as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) {
1483+
let htlc_tx_fee = if self.opt_anchors() {
1484+
0
1485+
} else {
1486+
feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000
1487+
};
1488+
if $htlc.amount_msat / 1000 >= broadcaster_dust_limit_satoshis + htlc_tx_fee {
14791489
log_trace!(logger, " ...including {} {} HTLC {} (hash {}) with value {}", if $outbound { "outbound" } else { "inbound" }, $state_name, $htlc.htlc_id, log_bytes!($htlc.payment_hash.0), $htlc.amount_msat);
14801490
included_non_dust_htlcs.push((htlc_in_tx, $source));
14811491
} else {
@@ -2396,8 +2406,15 @@ impl<Signer: Sign> Channel<Signer> {
23962406
on_holder_tx_holding_cell_htlcs_count: 0,
23972407
};
23982408

2399-
let counterparty_dust_limit_timeout_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
2400-
let holder_dust_limit_success_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
2409+
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() {
2410+
(0, 0)
2411+
} else {
2412+
let dust_buffer_feerate = self.get_dust_buffer_feerate(outbound_feerate_update) as u64;
2413+
(dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000,
2414+
dust_buffer_feerate * htlc_success_tx_weight(false) / 1000)
2415+
};
2416+
let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.counterparty_dust_limit_satoshis;
2417+
let holder_dust_limit_success_sat = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
24012418
for ref htlc in self.pending_inbound_htlcs.iter() {
24022419
stats.pending_htlcs_value_msat += htlc.amount_msat;
24032420
if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
@@ -2421,8 +2438,15 @@ impl<Signer: Sign> Channel<Signer> {
24212438
on_holder_tx_holding_cell_htlcs_count: 0,
24222439
};
24232440

2424-
let counterparty_dust_limit_success_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
2425-
let holder_dust_limit_timeout_sat = (self.get_dust_buffer_feerate(outbound_feerate_update) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
2441+
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() {
2442+
(0, 0)
2443+
} else {
2444+
let dust_buffer_feerate = self.get_dust_buffer_feerate(outbound_feerate_update) as u64;
2445+
(dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000,
2446+
dust_buffer_feerate * htlc_success_tx_weight(false) / 1000)
2447+
};
2448+
let counterparty_dust_limit_success_sat = htlc_success_dust_limit + self.counterparty_dust_limit_satoshis;
2449+
let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis;
24262450
for ref htlc in self.pending_outbound_htlcs.iter() {
24272451
stats.pending_htlcs_value_msat += htlc.amount_msat;
24282452
if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat {
@@ -2512,8 +2536,14 @@ impl<Signer: Sign> Channel<Signer> {
25122536
fn next_local_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
25132537
assert!(self.is_outbound());
25142538

2515-
let real_dust_limit_success_sat = (self.feerate_per_kw as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
2516-
let real_dust_limit_timeout_sat = (self.feerate_per_kw as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
2539+
let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() {
2540+
(0, 0)
2541+
} else {
2542+
(self.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000,
2543+
self.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000)
2544+
};
2545+
let real_dust_limit_success_sat = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
2546+
let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis;
25172547

25182548
let mut addl_htlcs = 0;
25192549
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
@@ -2603,8 +2633,14 @@ impl<Signer: Sign> Channel<Signer> {
26032633
fn next_remote_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
26042634
assert!(!self.is_outbound());
26052635

2606-
let real_dust_limit_success_sat = (self.feerate_per_kw as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
2607-
let real_dust_limit_timeout_sat = (self.feerate_per_kw as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
2636+
let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() {
2637+
(0, 0)
2638+
} else {
2639+
(self.feerate_per_kw as u64 * htlc_success_tx_weight(false) / 1000,
2640+
self.feerate_per_kw as u64 * htlc_timeout_tx_weight(false) / 1000)
2641+
};
2642+
let real_dust_limit_success_sat = htlc_success_dust_limit + self.counterparty_dust_limit_satoshis;
2643+
let real_dust_limit_timeout_sat = htlc_timeout_dust_limit + self.counterparty_dust_limit_satoshis;
26082644

26092645
let mut addl_htlcs = 0;
26102646
if fee_spike_buffer_htlc.is_some() { addl_htlcs += 1; }
@@ -2727,7 +2763,14 @@ impl<Signer: Sign> Channel<Signer> {
27272763
}
27282764
}
27292765

2730-
let exposure_dust_limit_timeout_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
2766+
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.opt_anchors() {
2767+
(0, 0)
2768+
} else {
2769+
let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64;
2770+
(dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000,
2771+
dust_buffer_feerate * htlc_success_tx_weight(false) / 1000)
2772+
};
2773+
let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.counterparty_dust_limit_satoshis;
27312774
if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats {
27322775
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;
27332776
if on_counterparty_tx_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {
@@ -2737,7 +2780,7 @@ impl<Signer: Sign> Channel<Signer> {
27372780
}
27382781
}
27392782

2740-
let exposure_dust_limit_success_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
2783+
let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.holder_dust_limit_satoshis;
27412784
if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
27422785
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;
27432786
if on_holder_tx_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {
@@ -5441,7 +5484,14 @@ impl<Signer: Sign> Channel<Signer> {
54415484
}
54425485
}
54435486

5444-
let exposure_dust_limit_success_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_success_tx_weight(self.opt_anchors()) / 1000) + self.counterparty_dust_limit_satoshis;
5487+
let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if self.opt_anchors() {
5488+
(0, 0)
5489+
} else {
5490+
let dust_buffer_feerate = self.get_dust_buffer_feerate(None) as u64;
5491+
(dust_buffer_feerate * htlc_success_tx_weight(false) / 1000,
5492+
dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000)
5493+
};
5494+
let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.counterparty_dust_limit_satoshis;
54455495
if amount_msat / 1000 < exposure_dust_limit_success_sats {
54465496
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;
54475497
if on_counterparty_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {
@@ -5450,7 +5500,7 @@ impl<Signer: Sign> Channel<Signer> {
54505500
}
54515501
}
54525502

5453-
let exposure_dust_limit_timeout_sats = (self.get_dust_buffer_feerate(None) as u64 * htlc_timeout_tx_weight(self.opt_anchors()) / 1000) + self.holder_dust_limit_satoshis;
5503+
let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.holder_dust_limit_satoshis;
54545504
if amount_msat / 1000 < exposure_dust_limit_timeout_sats {
54555505
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;
54565506
if on_holder_dust_htlc_exposure_msat > self.get_max_dust_htlc_exposure_msat() {

0 commit comments

Comments
 (0)