Unify get_{inbound,outbound}_pending_htlc_stats

In most cases we already call both in a pair, and in fact always
consolidate some of the returned values across both accessors, so
there's not much reason to have them be separate methods.

Here we merge them.
This commit is contained in:
Matt Corallo 2024-03-27 02:14:50 +00:00
parent 8701b1bbe3
commit 2937000051

View file

@ -998,14 +998,16 @@ enum HTLCInitiator {
RemoteOffered, RemoteOffered,
} }
/// An enum gathering stats on pending HTLCs, either inbound or outbound side. /// Current counts of various HTLCs, useful for calculating current balances available exactly.
struct HTLCStats { struct HTLCStats {
pending_htlcs: u32, pending_inbound_htlcs: usize,
pending_htlcs_value_msat: u64, pending_outbound_htlcs: usize,
pending_inbound_htlcs_value_msat: u64,
pending_outbound_htlcs_value_msat: u64,
on_counterparty_tx_dust_exposure_msat: u64, on_counterparty_tx_dust_exposure_msat: u64,
on_holder_tx_dust_exposure_msat: u64, on_holder_tx_dust_exposure_msat: u64,
holding_cell_msat: u64, outbound_holding_cell_msat: u64,
on_holder_tx_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
} }
/// An enum gathering stats on commitment transaction, either local or remote. /// An enum gathering stats on commitment transaction, either local or remote.
@ -2738,86 +2740,81 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
self.counterparty_forwarding_info.clone() self.counterparty_forwarding_info.clone()
} }
/// Returns a HTLCStats about inbound pending htlcs /// Returns a HTLCStats about pending htlcs
fn get_inbound_pending_htlc_stats(&self, outbound_feerate_update: Option<u32>) -> HTLCStats { fn get_pending_htlc_stats(&self, outbound_feerate_update: Option<u32>) -> HTLCStats {
let context = self; let context = self;
let mut stats = HTLCStats { let uses_0_htlc_fee_anchors = self.get_channel_type().supports_anchors_zero_fee_htlc_tx();
pending_htlcs: context.pending_inbound_htlcs.len() as u32,
pending_htlcs_value_msat: 0,
on_counterparty_tx_dust_exposure_msat: 0,
on_holder_tx_dust_exposure_msat: 0,
holding_cell_msat: 0,
on_holder_tx_holding_cell_htlcs_count: 0,
};
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if uses_0_htlc_fee_anchors {
(0, 0) (0, 0)
} else { } else {
let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64; let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64;
(dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000, (dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000,
dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000) dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000)
}; };
let mut on_holder_tx_dust_exposure_msat = 0;
let mut on_counterparty_tx_dust_exposure_msat = 0;
let mut pending_inbound_htlcs_value_msat = 0;
{
let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis; let counterparty_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.counterparty_dust_limit_satoshis;
let holder_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis; let holder_dust_limit_success_sat = htlc_success_dust_limit + context.holder_dust_limit_satoshis;
for ref htlc in context.pending_inbound_htlcs.iter() { for ref htlc in context.pending_inbound_htlcs.iter() {
stats.pending_htlcs_value_msat += htlc.amount_msat; pending_inbound_htlcs_value_msat += htlc.amount_msat;
if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat { if htlc.amount_msat / 1000 < counterparty_dust_limit_timeout_sat {
stats.on_counterparty_tx_dust_exposure_msat += htlc.amount_msat; on_counterparty_tx_dust_exposure_msat += htlc.amount_msat;
} }
if htlc.amount_msat / 1000 < holder_dust_limit_success_sat { if htlc.amount_msat / 1000 < holder_dust_limit_success_sat {
stats.on_holder_tx_dust_exposure_msat += htlc.amount_msat; on_holder_tx_dust_exposure_msat += htlc.amount_msat;
} }
} }
stats }
}
/// Returns a HTLCStats about pending outbound htlcs, *including* pending adds in our holding cell. let mut pending_outbound_htlcs_value_msat = 0;
fn get_outbound_pending_htlc_stats(&self, outbound_feerate_update: Option<u32>) -> HTLCStats { let mut outbound_holding_cell_msat = 0;
let context = self; let mut on_holder_tx_outbound_holding_cell_htlcs_count = 0;
let mut stats = HTLCStats { let mut pending_outbound_htlcs = self.pending_outbound_htlcs.len();
pending_htlcs: context.pending_outbound_htlcs.len() as u32, {
pending_htlcs_value_msat: 0,
on_counterparty_tx_dust_exposure_msat: 0,
on_holder_tx_dust_exposure_msat: 0,
holding_cell_msat: 0,
on_holder_tx_holding_cell_htlcs_count: 0,
};
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
(0, 0)
} else {
let dust_buffer_feerate = context.get_dust_buffer_feerate(outbound_feerate_update) as u64;
(dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000,
dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000)
};
let counterparty_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis; let counterparty_dust_limit_success_sat = htlc_success_dust_limit + context.counterparty_dust_limit_satoshis;
let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis; let holder_dust_limit_timeout_sat = htlc_timeout_dust_limit + context.holder_dust_limit_satoshis;
for ref htlc in context.pending_outbound_htlcs.iter() { for ref htlc in context.pending_outbound_htlcs.iter() {
stats.pending_htlcs_value_msat += htlc.amount_msat; pending_outbound_htlcs_value_msat += htlc.amount_msat;
if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat { if htlc.amount_msat / 1000 < counterparty_dust_limit_success_sat {
stats.on_counterparty_tx_dust_exposure_msat += htlc.amount_msat; on_counterparty_tx_dust_exposure_msat += htlc.amount_msat;
} }
if htlc.amount_msat / 1000 < holder_dust_limit_timeout_sat { if htlc.amount_msat / 1000 < holder_dust_limit_timeout_sat {
stats.on_holder_tx_dust_exposure_msat += htlc.amount_msat; on_holder_tx_dust_exposure_msat += htlc.amount_msat;
} }
} }
for update in context.holding_cell_htlc_updates.iter() { for update in context.holding_cell_htlc_updates.iter() {
if let &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, .. } = update { if let &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, .. } = update {
stats.pending_htlcs += 1; pending_outbound_htlcs += 1;
stats.pending_htlcs_value_msat += amount_msat; pending_outbound_htlcs_value_msat += amount_msat;
stats.holding_cell_msat += amount_msat; outbound_holding_cell_msat += amount_msat;
if *amount_msat / 1000 < counterparty_dust_limit_success_sat { if *amount_msat / 1000 < counterparty_dust_limit_success_sat {
stats.on_counterparty_tx_dust_exposure_msat += amount_msat; on_counterparty_tx_dust_exposure_msat += amount_msat;
} }
if *amount_msat / 1000 < holder_dust_limit_timeout_sat { if *amount_msat / 1000 < holder_dust_limit_timeout_sat {
stats.on_holder_tx_dust_exposure_msat += amount_msat; on_holder_tx_dust_exposure_msat += amount_msat;
} else { } else {
stats.on_holder_tx_holding_cell_htlcs_count += 1; on_holder_tx_outbound_holding_cell_htlcs_count += 1;
} }
} }
} }
stats }
HTLCStats {
pending_inbound_htlcs: self.pending_inbound_htlcs.len(),
pending_outbound_htlcs,
pending_inbound_htlcs_value_msat,
pending_outbound_htlcs_value_msat,
on_counterparty_tx_dust_exposure_msat,
on_holder_tx_dust_exposure_msat,
outbound_holding_cell_msat,
on_holder_tx_outbound_holding_cell_htlcs_count,
}
} }
/// Returns information on all pending inbound HTLCs. /// Returns information on all pending inbound HTLCs.
@ -2923,8 +2920,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
{ {
let context = &self; let context = &self;
// Note that we have to handle overflow due to the above case. // Note that we have to handle overflow due to the above case.
let inbound_stats = context.get_inbound_pending_htlc_stats(None); let htlc_stats = context.get_pending_htlc_stats(None);
let outbound_stats = context.get_outbound_pending_htlc_stats(None);
let mut balance_msat = context.value_to_self_msat; let mut balance_msat = context.value_to_self_msat;
for ref htlc in context.pending_inbound_htlcs.iter() { for ref htlc in context.pending_inbound_htlcs.iter() {
@ -2932,10 +2928,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
balance_msat += htlc.amount_msat; balance_msat += htlc.amount_msat;
} }
} }
balance_msat -= outbound_stats.pending_htlcs_value_msat; balance_msat -= htlc_stats.pending_outbound_htlcs_value_msat;
let outbound_capacity_msat = context.value_to_self_msat let outbound_capacity_msat = context.value_to_self_msat
.saturating_sub(outbound_stats.pending_htlcs_value_msat) .saturating_sub(htlc_stats.pending_outbound_htlcs_value_msat)
.saturating_sub( .saturating_sub(
context.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) * 1000); context.counterparty_selected_channel_reserve_satoshis.unwrap_or(0) * 1000);
@ -2995,7 +2991,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
let holder_selected_chan_reserve_msat = context.holder_selected_channel_reserve_satoshis * 1000; let holder_selected_chan_reserve_msat = context.holder_selected_channel_reserve_satoshis * 1000;
let remote_balance_msat = (context.channel_value_satoshis * 1000 - context.value_to_self_msat) let remote_balance_msat = (context.channel_value_satoshis * 1000 - context.value_to_self_msat)
.saturating_sub(inbound_stats.pending_htlcs_value_msat); .saturating_sub(htlc_stats.pending_inbound_htlcs_value_msat);
if remote_balance_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat + anchor_outputs_value_msat { if remote_balance_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat + anchor_outputs_value_msat {
// If another HTLC's fee would reduce the remote's balance below the reserve limit // If another HTLC's fee would reduce the remote's balance below the reserve limit
@ -3021,18 +3017,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
(context.counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000, (context.counterparty_dust_limit_satoshis + dust_buffer_feerate * htlc_success_tx_weight(context.get_channel_type()) / 1000,
context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000) context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(context.get_channel_type()) / 1000)
}; };
let on_counterparty_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat; if htlc_stats.on_counterparty_tx_dust_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
remaining_msat_below_dust_exposure_limit = remaining_msat_below_dust_exposure_limit =
Some(max_dust_htlc_exposure_msat.saturating_sub(on_counterparty_dust_htlc_exposure_msat)); Some(max_dust_htlc_exposure_msat.saturating_sub(htlc_stats.on_counterparty_tx_dust_exposure_msat));
dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000); dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000);
} }
let on_holder_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat; if htlc_stats.on_holder_tx_dust_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
if on_holder_dust_htlc_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat.try_into().unwrap_or(i64::max_value()) {
remaining_msat_below_dust_exposure_limit = Some(cmp::min( remaining_msat_below_dust_exposure_limit = Some(cmp::min(
remaining_msat_below_dust_exposure_limit.unwrap_or(u64::max_value()), remaining_msat_below_dust_exposure_limit.unwrap_or(u64::max_value()),
max_dust_htlc_exposure_msat.saturating_sub(on_holder_dust_htlc_exposure_msat))); max_dust_htlc_exposure_msat.saturating_sub(htlc_stats.on_holder_tx_dust_exposure_msat)));
dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000); dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000);
} }
@ -3045,16 +3039,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
} }
available_capacity_msat = cmp::min(available_capacity_msat, available_capacity_msat = cmp::min(available_capacity_msat,
context.counterparty_max_htlc_value_in_flight_msat - outbound_stats.pending_htlcs_value_msat); context.counterparty_max_htlc_value_in_flight_msat - htlc_stats.pending_outbound_htlcs_value_msat);
if outbound_stats.pending_htlcs + 1 > context.counterparty_max_accepted_htlcs as u32 { if htlc_stats.pending_outbound_htlcs + 1 > context.counterparty_max_accepted_htlcs as usize {
available_capacity_msat = 0; available_capacity_msat = 0;
} }
AvailableBalances { AvailableBalances {
inbound_capacity_msat: cmp::max(context.channel_value_satoshis as i64 * 1000 inbound_capacity_msat: cmp::max(context.channel_value_satoshis as i64 * 1000
- context.value_to_self_msat as i64 - context.value_to_self_msat as i64
- context.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64 - htlc_stats.pending_inbound_htlcs_value_msat as i64
- context.holder_selected_channel_reserve_satoshis as i64 * 1000, - context.holder_selected_channel_reserve_satoshis as i64 * 1000,
0) as u64, 0) as u64,
outbound_capacity_msat, outbound_capacity_msat,
@ -4143,11 +4137,11 @@ impl<SP: Deref> Channel<SP> where
return Err(ChannelError::Close(format!("Remote side tried to send less than our minimum HTLC value. Lower limit: ({}). Actual: ({})", self.context.holder_htlc_minimum_msat, msg.amount_msat))); return Err(ChannelError::Close(format!("Remote side tried to send less than our minimum HTLC value. Lower limit: ({}). Actual: ({})", self.context.holder_htlc_minimum_msat, msg.amount_msat)));
} }
let inbound_stats = self.context.get_inbound_pending_htlc_stats(None); let htlc_stats = self.context.get_pending_htlc_stats(None);
if inbound_stats.pending_htlcs + 1 > self.context.holder_max_accepted_htlcs as u32 { if htlc_stats.pending_inbound_htlcs + 1 > self.context.holder_max_accepted_htlcs as usize {
return Err(ChannelError::Close(format!("Remote tried to push more than our max accepted HTLCs ({})", self.context.holder_max_accepted_htlcs))); return Err(ChannelError::Close(format!("Remote tried to push more than our max accepted HTLCs ({})", self.context.holder_max_accepted_htlcs)));
} }
if inbound_stats.pending_htlcs_value_msat + msg.amount_msat > self.context.holder_max_htlc_value_in_flight_msat { if htlc_stats.pending_inbound_htlcs_value_msat + msg.amount_msat > self.context.holder_max_htlc_value_in_flight_msat {
return Err(ChannelError::Close(format!("Remote HTLC add would put them over our max HTLC value ({})", self.context.holder_max_htlc_value_in_flight_msat))); return Err(ChannelError::Close(format!("Remote HTLC add would put them over our max HTLC value ({})", self.context.holder_max_htlc_value_in_flight_msat)));
} }
@ -4173,7 +4167,7 @@ impl<SP: Deref> Channel<SP> where
} }
let pending_value_to_self_msat = let pending_value_to_self_msat =
self.context.value_to_self_msat + inbound_stats.pending_htlcs_value_msat - removed_outbound_total_msat; self.context.value_to_self_msat + htlc_stats.pending_inbound_htlcs_value_msat - removed_outbound_total_msat;
let pending_remote_value_msat = let pending_remote_value_msat =
self.context.channel_value_satoshis * 1000 - pending_value_to_self_msat; self.context.channel_value_satoshis * 1000 - pending_value_to_self_msat;
if pending_remote_value_msat < msg.amount_msat { if pending_remote_value_msat < msg.amount_msat {
@ -4995,12 +4989,11 @@ impl<SP: Deref> Channel<SP> where
} }
// Before proposing a feerate update, check that we can actually afford the new fee. // Before proposing a feerate update, check that we can actually afford the new fee.
let inbound_stats = self.context.get_inbound_pending_htlc_stats(Some(feerate_per_kw)); let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw));
let outbound_stats = self.context.get_outbound_pending_htlc_stats(Some(feerate_per_kw));
let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number);
let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger); let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger);
let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + outbound_stats.on_holder_tx_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000; let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000;
let holder_balance_msat = commitment_stats.local_balance_msat - outbound_stats.holding_cell_msat; let holder_balance_msat = commitment_stats.local_balance_msat - htlc_stats.outbound_holding_cell_msat;
if holder_balance_msat < buffer_fee_msat + self.context.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 { if holder_balance_msat < buffer_fee_msat + self.context.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
//TODO: auto-close after a number of failures? //TODO: auto-close after a number of failures?
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw); log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
@ -5008,14 +5001,12 @@ impl<SP: Deref> Channel<SP> where
} }
// Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`. // Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator); let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
if holder_tx_dust_exposure > max_dust_htlc_exposure_msat { if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw); log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
return None; return None;
} }
if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat { if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw); log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
return None; return None;
} }
@ -5249,18 +5240,15 @@ impl<SP: Deref> Channel<SP> where
self.context.update_time_counter += 1; self.context.update_time_counter += 1;
// Check that we won't be pushed over our dust exposure limit by the feerate increase. // Check that we won't be pushed over our dust exposure limit by the feerate increase.
if !self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { if !self.context.channel_type.supports_anchors_zero_fee_htlc_tx() {
let inbound_stats = self.context.get_inbound_pending_htlc_stats(None); let htlc_stats = self.context.get_pending_htlc_stats(None);
let outbound_stats = self.context.get_outbound_pending_htlc_stats(None);
let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator); let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
if holder_tx_dust_exposure > max_dust_htlc_exposure_msat { if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)", return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)",
msg.feerate_per_kw, holder_tx_dust_exposure))); msg.feerate_per_kw, htlc_stats.on_holder_tx_dust_exposure_msat)));
} }
if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat { if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)", return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)",
msg.feerate_per_kw, counterparty_tx_dust_exposure))); msg.feerate_per_kw, htlc_stats.on_counterparty_tx_dust_exposure_msat)));
} }
} }
Ok(()) Ok(())
@ -6105,8 +6093,7 @@ impl<SP: Deref> Channel<SP> where
return Err(("Shutdown was already sent", 0x4000|8)) return Err(("Shutdown was already sent", 0x4000|8))
} }
let inbound_stats = self.context.get_inbound_pending_htlc_stats(None); let htlc_stats = self.context.get_pending_htlc_stats(None);
let outbound_stats = self.context.get_outbound_pending_htlc_stats(None);
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator); let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() { let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
(0, 0) (0, 0)
@ -6117,7 +6104,7 @@ impl<SP: Deref> Channel<SP> where
}; };
let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis; let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis;
if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats { if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats {
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; let on_counterparty_tx_dust_htlc_exposure_msat = htlc_stats.on_counterparty_tx_dust_exposure_msat + msg.amount_msat;
if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat { if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx", log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat); on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
@ -6127,7 +6114,7 @@ impl<SP: Deref> Channel<SP> where
let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis; let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis;
if msg.amount_msat / 1000 < exposure_dust_limit_success_sats { if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
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; let on_holder_tx_dust_htlc_exposure_msat = htlc_stats.on_holder_tx_dust_exposure_msat + msg.amount_msat;
if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat { if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx", log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat); on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
@ -6151,7 +6138,7 @@ impl<SP: Deref> Channel<SP> where
} }
let pending_value_to_self_msat = let pending_value_to_self_msat =
self.context.value_to_self_msat + inbound_stats.pending_htlcs_value_msat - removed_outbound_total_msat; self.context.value_to_self_msat + htlc_stats.pending_inbound_htlcs_value_msat - removed_outbound_total_msat;
let pending_remote_value_msat = let pending_remote_value_msat =
self.context.channel_value_satoshis * 1000 - pending_value_to_self_msat; self.context.channel_value_satoshis * 1000 - pending_value_to_self_msat;