Skip to content

Commit 124bd42

Browse files
committed
Improve prediction of commitment stats in can_send_update_fee
`ChannelContext::get_pending_htlc_stats` predicts that the set of HTLCs on the next commitment will be all the HTLCs in `ChannelContext.pending_inbound_htlcs`, and `ChannelContext.pending_outbound_htlcs`, as well as all the outbound HTLC adds in the holding cell. This is an overestimate: * Outbound HTLC removals which have been ACK'ed by the counterparty will certainly not be present in any *next* commitment, even though they remain in `pending_outbound_htlcs` (I refer to states `AwaitingRemoteRevokeToRemove` and `AwaitingRemovedRemoteRevoke`). * Outbound HTLCs in the `RemoteRemoved` state, will not be present in the next *local* commitment. * Inbound HTLCs in the `LocalRemoved` state will not be present in the next *remote* commitment. `ChannelContext::build_commitment_stats(funding, true, true, ..)` makes these errors when predicting the HTLC count on the remote commitment: * Inbound HTLCs in the state `RemoteAnnounced` are not included, but they will be in the next remote commitment transaction if the local ACK's the addition before producing the next remote commitment. * Inbound HTLCs in the state `AwaitingRemoteRevokeToAnnounce` are not included, even though the local has ACK'ed the addition. * Outbound HTLCs in the state `AwaitingRemoteRevokeToRemove` are counted, even though the local party has ACK'ed the removal. This commit replaces these functions in favor of the newly added `ChannelContext::get_next_{local, remote}_commitment_stats` methods, and fixes the issues described above. We now always calculate dust exposure using a buffer from `msg.feerate_per_kw`, and not from `max(feerate_per_kw, self.feerate_per_kw, self.pending_update_fee)`.
1 parent d36fdab commit 124bd42

File tree

1 file changed

+9
-15
lines changed

1 file changed

+9
-15
lines changed

lightning/src/ln/channel.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,8 +1116,6 @@ struct HTLCStats {
11161116
// htlc on the counterparty's commitment transaction.
11171117
extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat: Option<u64>,
11181118
on_holder_tx_dust_exposure_msat: u64,
1119-
outbound_holding_cell_msat: u64,
1120-
on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
11211119
}
11221120

11231121
/// A struct gathering data on a commitment, either local or remote.
@@ -4462,23 +4460,26 @@ where
44624460
let dust_exposure_limiting_feerate = self.get_dust_exposure_limiting_feerate(
44634461
&fee_estimator, funding.get_channel_type(),
44644462
);
4465-
let htlc_stats = self.get_pending_htlc_stats(funding, Some(feerate_per_kw), dust_exposure_limiting_feerate);
4466-
let stats = self.build_commitment_stats(funding, true, true, Some(feerate_per_kw), Some(htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize));
4467-
let holder_balance_msat = stats.local_balance_before_fee_msat - htlc_stats.outbound_holding_cell_msat;
4463+
// Include outbound update_add_htlc's in the holding cell, and those which haven't yet been ACK'ed by the counterparty (ie. LocalAnnounced HTLCs)
4464+
let include_counterparty_unknown_htlcs = true;
4465+
let next_remote_commitment_stats = self.get_next_remote_commitment_stats(funding, None, include_counterparty_unknown_htlcs, CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, feerate_per_kw, dust_exposure_limiting_feerate);
4466+
let holder_balance_msat = next_remote_commitment_stats.holder_balance_before_fee_msat.expect("The holder's balance before fees should never underflow.");
44684467
// Note that `stats.commit_tx_fee_sat` accounts for any HTLCs that transition from non-dust to dust under a higher feerate (in the case where HTLC-transactions pay endogenous fees).
4469-
if holder_balance_msat < stats.commit_tx_fee_sat * 1000 + funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
4468+
if holder_balance_msat < next_remote_commitment_stats.commit_tx_fee_sat * 1000 + funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
44704469
//TODO: auto-close after a number of failures?
44714470
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
44724471
return false;
44734472
}
44744473

44754474
// Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
44764475
let max_dust_htlc_exposure_msat = self.get_max_dust_htlc_exposure_msat(dust_exposure_limiting_feerate);
4477-
if htlc_stats.on_holder_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
4476+
if next_remote_commitment_stats.dust_exposure_msat > max_dust_htlc_exposure_msat {
44784477
log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
44794478
return false;
44804479
}
4481-
if htlc_stats.on_counterparty_tx_dust_exposure_msat > max_dust_htlc_exposure_msat {
4480+
4481+
let next_local_commitment_stats = self.get_next_local_commitment_stats(funding, None, include_counterparty_unknown_htlcs, CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, feerate_per_kw, dust_exposure_limiting_feerate);
4482+
if next_local_commitment_stats.dust_exposure_msat > max_dust_htlc_exposure_msat {
44824483
log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
44834484
return false;
44844485
}
@@ -4844,8 +4845,6 @@ where
48444845
}
48454846

48464847
let mut pending_outbound_htlcs_value_msat = 0;
4847-
let mut outbound_holding_cell_msat = 0;
4848-
let mut on_holder_tx_outbound_holding_cell_htlcs_count = 0;
48494848
let mut pending_outbound_htlcs = self.pending_outbound_htlcs.len();
48504849
{
48514850
let counterparty_dust_limit_success_sat = htlc_success_tx_fee_sat + context.counterparty_dust_limit_satoshis;
@@ -4866,16 +4865,13 @@ where
48664865
if let &HTLCUpdateAwaitingACK::AddHTLC { ref amount_msat, .. } = update {
48674866
pending_outbound_htlcs += 1;
48684867
pending_outbound_htlcs_value_msat += amount_msat;
4869-
outbound_holding_cell_msat += amount_msat;
48704868
if *amount_msat / 1000 < counterparty_dust_limit_success_sat {
48714869
on_counterparty_tx_dust_exposure_msat += amount_msat;
48724870
} else {
48734871
on_counterparty_tx_accepted_nondust_htlcs += 1;
48744872
}
48754873
if *amount_msat / 1000 < holder_dust_limit_timeout_sat {
48764874
on_holder_tx_dust_exposure_msat += amount_msat;
4877-
} else {
4878-
on_holder_tx_outbound_holding_cell_htlcs_count += 1;
48794875
}
48804876
}
48814877
}
@@ -4913,8 +4909,6 @@ where
49134909
on_counterparty_tx_dust_exposure_msat,
49144910
extra_nondust_htlc_on_counterparty_tx_dust_exposure_msat,
49154911
on_holder_tx_dust_exposure_msat,
4916-
outbound_holding_cell_msat,
4917-
on_holder_tx_outbound_holding_cell_htlcs_count,
49184912
}
49194913
}
49204914

0 commit comments

Comments
 (0)