Skip to content

Commit 8de58c1

Browse files
committed
f: Create IncludedHTLC type to express dust-vs-nondust information to TxBuilder
1 parent 2f19710 commit 8de58c1

File tree

3 files changed

+55
-37
lines changed

3 files changed

+55
-37
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -654,23 +654,6 @@ impl HTLCOutputInCommitment {
654654
&& self.cltv_expiry == other.cltv_expiry
655655
&& self.payment_hash == other.payment_hash
656656
}
657-
658-
pub(crate) fn is_dust(
659-
&self, feerate_per_kw: u32, broadcaster_dust_limit_sat: u64, features: &ChannelTypeFeatures,
660-
) -> bool {
661-
let htlc_tx_fee_sat = if features.supports_anchors_zero_fee_htlc_tx() {
662-
0
663-
} else {
664-
let htlc_tx_weight = if self.offered {
665-
htlc_timeout_tx_weight(features)
666-
} else {
667-
htlc_success_tx_weight(features)
668-
};
669-
// As required by the spec, round down
670-
feerate_per_kw as u64 * htlc_tx_weight / 1000
671-
};
672-
self.amount_msat / 1000 < broadcaster_dust_limit_sat + htlc_tx_fee_sat
673-
}
674657
}
675658

676659
impl_writeable_tlv_based!(HTLCOutputInCommitment, {

lightning/src/ln/channel.rs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,15 @@ impl OutboundHTLCOutput {
450450
}
451451
}
452452

453+
#[derive(Clone, Debug)]
454+
pub(crate) struct IncludedHTLC {
455+
pub offered: bool,
456+
pub amount_msat: u64,
457+
pub cltv_expiry: u32,
458+
pub payment_hash: PaymentHash,
459+
pub is_dust: bool,
460+
}
461+
453462
/// See AwaitingRemoteRevoke ChannelState for more info
454463
#[cfg_attr(test, derive(Clone, Debug, PartialEq))]
455464
enum HTLCUpdateAwaitingACK {
@@ -4572,7 +4581,8 @@ where
45724581
let feerate_per_kw = self.get_commitment_feerate(funding, generated_by_local);
45734582

45744583
let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
4575-
let mut htlcs_included: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs);
4584+
let mut htlc_source_table: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs);
4585+
let mut htlcs_included: Vec<IncludedHTLC> = Vec::with_capacity(num_htlcs);
45764586
let mut value_to_self_msat_offset = 0;
45774587

45784588
log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for channel {} for {}, generated by {} with fee {}...",
@@ -4588,15 +4598,29 @@ where
45884598
amount_msat: $htlc.amount_msat,
45894599
cltv_expiry: $htlc.cltv_expiry,
45904600
payment_hash: $htlc.payment_hash,
4591-
transaction_output_index: None
4601+
transaction_output_index: None,
4602+
}
4603+
}
4604+
}
4605+
4606+
macro_rules! get_included_htlc {
4607+
($htlc: expr, $offered: expr, $is_dust: expr) => {
4608+
IncludedHTLC {
4609+
offered: $offered,
4610+
amount_msat: $htlc.amount_msat,
4611+
cltv_expiry: $htlc.cltv_expiry,
4612+
payment_hash: $htlc.payment_hash,
4613+
is_dust: $is_dust,
45924614
}
45934615
}
45944616
}
45954617

45964618
macro_rules! add_htlc_output {
4597-
($htlc: expr, $outbound: expr, $source: expr) => {
4598-
let htlc_in_tx = get_htlc_in_commitment!($htlc, $outbound == local);
4599-
htlcs_included.push((htlc_in_tx, $source));
4619+
($htlc: expr, $outbound: expr, $source: expr, $is_dust: expr) => {
4620+
let table_htlc = get_htlc_in_commitment!($htlc, $outbound == local);
4621+
let included_htlc = get_included_htlc!($htlc, $outbound == local, $is_dust);
4622+
htlc_source_table.push((table_htlc, $source));
4623+
htlcs_included.push(included_htlc);
46004624
}
46014625
}
46024626

@@ -4606,7 +4630,8 @@ where
46064630
for htlc in self.pending_inbound_htlcs.iter() {
46074631
if htlc.state.included_in_commitment(generated_by_local) {
46084632
log_trace!(logger, " ...including inbound {} HTLC {} (hash {}) with value {}", htlc.state, htlc.htlc_id, htlc.payment_hash, htlc.amount_msat);
4609-
add_htlc_output!(htlc, false, None);
4633+
let is_dust = htlc.is_dust(local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type());
4634+
add_htlc_output!(htlc, false, None, is_dust);
46104635
} else {
46114636
log_trace!(logger, " ...not including inbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, htlc.payment_hash, htlc.amount_msat, htlc.state);
46124637
if let Some(preimage) = htlc.state.preimage() {
@@ -4622,7 +4647,8 @@ where
46224647
}
46234648
if htlc.state.included_in_commitment(generated_by_local) {
46244649
log_trace!(logger, " ...including outbound {} HTLC {} (hash {}) with value {}", htlc.state, htlc.htlc_id, htlc.payment_hash, htlc.amount_msat);
4625-
add_htlc_output!(htlc, true, Some(&htlc.source));
4650+
let is_dust = htlc.is_dust(local, feerate_per_kw, broadcaster_dust_limit_sat, funding.get_channel_type());
4651+
add_htlc_output!(htlc, true, Some(&htlc.source), is_dust);
46264652
} else {
46274653
log_trace!(logger, " ...not including outbound HTLC {} (hash {}) with value {} due to state ({})", htlc.htlc_id, htlc.payment_hash, htlc.amount_msat, htlc.state);
46284654
if htlc.state.preimage().is_some() {
@@ -4646,7 +4672,7 @@ where
46464672
&funding.channel_transaction_parameters,
46474673
&self.secp_ctx,
46484674
value_to_self_with_offset_msat,
4649-
htlcs_included.iter().map(|(htlc, _source)| htlc).cloned().collect(),
4675+
htlcs_included,
46504676
feerate_per_kw,
46514677
broadcaster_dust_limit_sat,
46524678
logger,
@@ -4659,7 +4685,7 @@ where
46594685
// This brute-force search is O(n^2) over ~1k HTLCs in the worst case. This case is very
46604686
// rare at the moment.
46614687
for nondust_htlc in tx.nondust_htlcs() {
4662-
let htlc = htlcs_included
4688+
let htlc = htlc_source_table
46634689
.iter_mut()
46644690
.filter(|(htlc, _source)| htlc.transaction_output_index.is_none())
46654691
.find_map(|(htlc, _source)| {
@@ -4675,7 +4701,7 @@ where
46754701

46764702
// This places the non-dust HTLC-source pairs first, in the order they appear in the
46774703
// commitment transaction, followed by the dust HTLC-source pairs.
4678-
htlcs_included.sort_unstable_by(|(htlc_a, _), (htlc_b, _)| {
4704+
htlc_source_table.sort_unstable_by(|(htlc_a, _), (htlc_b, _)| {
46794705
match (htlc_a.transaction_output_index, htlc_b.transaction_output_index) {
46804706
// `None` is smaller than `Some`, but we want `Some` ordered before `None` in the vector
46814707
(None, Some(_)) => cmp::Ordering::Greater,
@@ -4687,7 +4713,7 @@ where
46874713
CommitmentData {
46884714
tx,
46894715
stats,
4690-
htlcs_included,
4716+
htlcs_included: htlc_source_table,
46914717
inbound_htlc_preimages,
46924718
outbound_htlc_preimages,
46934719
}

lightning/src/sign/tx_builder.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1};
77
use crate::ln::chan_utils::{
88
commit_tx_fee_sat, ChannelTransactionParameters, CommitmentTransaction, HTLCOutputInCommitment,
99
};
10-
use crate::ln::channel::{CommitmentStats, ANCHOR_OUTPUT_VALUE_SATOSHI};
10+
use crate::ln::channel::{CommitmentStats, IncludedHTLC, ANCHOR_OUTPUT_VALUE_SATOSHI};
1111
use crate::prelude::*;
1212
use crate::types::features::ChannelTypeFeatures;
1313
use crate::util::logger::Logger;
@@ -21,7 +21,7 @@ pub(crate) trait TxBuilder {
2121
fn build_commitment_transaction<L: Deref>(
2222
&self, local: bool, commitment_number: u64, per_commitment_point: &PublicKey,
2323
channel_parameters: &ChannelTransactionParameters, secp_ctx: &Secp256k1<secp256k1::All>,
24-
value_to_self_msat: u64, htlcs_in_tx: Vec<HTLCOutputInCommitment>, feerate_per_kw: u32,
24+
value_to_self_msat: u64, htlcs_in_tx: Vec<IncludedHTLC>, feerate_per_kw: u32,
2525
broadcaster_dust_limit_satoshis: u64, logger: &L,
2626
) -> (CommitmentTransaction, CommitmentStats)
2727
where
@@ -72,7 +72,7 @@ impl TxBuilder for SpecTxBuilder {
7272
fn build_commitment_transaction<L: Deref>(
7373
&self, local: bool, commitment_number: u64, per_commitment_point: &PublicKey,
7474
channel_parameters: &ChannelTransactionParameters, secp_ctx: &Secp256k1<secp256k1::All>,
75-
value_to_self_msat: u64, mut htlcs_in_tx: Vec<HTLCOutputInCommitment>, feerate_per_kw: u32,
75+
value_to_self_msat: u64, mut htlcs_in_tx: Vec<IncludedHTLC>, feerate_per_kw: u32,
7676
broadcaster_dust_limit_satoshis: u64, logger: &L,
7777
) -> (CommitmentTransaction, CommitmentStats)
7878
where
@@ -89,11 +89,7 @@ impl TxBuilder for SpecTxBuilder {
8989
} else {
9090
remote_htlc_total_msat += htlc.amount_msat;
9191
}
92-
if htlc.is_dust(
93-
feerate_per_kw,
94-
broadcaster_dust_limit_satoshis,
95-
&channel_parameters.channel_type_features,
96-
) {
92+
if htlc.is_dust {
9793
log_trace!(
9894
logger,
9995
" ...trimming {} HTLC with value {}sat, hash {}, due to dust limit {}",
@@ -182,7 +178,20 @@ impl TxBuilder for SpecTxBuilder {
182178
to_broadcaster_value_sat,
183179
to_countersignatory_value_sat,
184180
feerate_per_kw,
185-
htlcs_in_tx,
181+
htlcs_in_tx
182+
.into_iter()
183+
.map(|htlc| {
184+
// We filtered out all dust HTLCs above
185+
debug_assert!(!htlc.is_dust);
186+
HTLCOutputInCommitment {
187+
offered: htlc.offered,
188+
amount_msat: htlc.amount_msat,
189+
cltv_expiry: htlc.cltv_expiry,
190+
payment_hash: htlc.payment_hash,
191+
transaction_output_index: None,
192+
}
193+
})
194+
.collect(),
186195
&directed_parameters,
187196
secp_ctx,
188197
);

0 commit comments

Comments
 (0)