Include HTLCs unknown by remote in `can_accept_incoming_htlc` stats
What changed, and why it matters
This change makes the Lightning node more cautious when deciding whether to accept a forwarded payment (HTLC). Previously, the node only counted HTLCs that the counterparty already knew about when checking channel capacity limits. Now it also counts HTLCs that have been announced locally but not yet acknowledged by the remote side. This prevents the node from accepting a new forward that could push the channel over its limits once those in-flight HTLCs are committed, reducing the risk of being unable to fulfill obligations or being forced into an unfavorable state.
Review related test coverage for `can_accept_incoming_htlc` with pending un-ACKed outbound HTLCs and anchor/zero-fee channels. Consider whether the same conservative treatment is needed in other commitment-stat calculations (e.g., counterparty-side stats) and monitor for any regressions in forwarding throughput.
Security signals we found
Change in HTLC acceptance policy affecting channel balance/fee calculations
Explicit commit-message rationale about conservative forwarding to avoid future commitment issues
Modification of anchor/non-anchor commitment fee-spike buffer logic context
Potential prevention of local commitment over-allocation / insufficient reserve scenarios
Evidence from the diff
In Channel::can_accept_incoming_htlc, the local commitment statistics calculation previously excluded HTLCs not yet known to the counterparty (LocalAnnounced HTLCs in the holding cell / un-ACKed outbound update_add_htlcs) by setting include_counterparty_unknown_htlcs = false. The patch flips this to true, so these pending HTLCs are included in the next_local_commitment_stats used to evaluate whether an incoming HTLC can be accepted. The rationale is that these HTLCs may soon be committed, and since only a single HTLC is being failed (not the whole channel), a conservative acceptance policy is preferable.
Changed components
lightning/src/ln/channel.rsChannel::can_accept_incoming_htlcHTLC forwarding / acceptance logicLocal commitment statistics calculationInspect captured patch +5 / −3
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 53da7b4..61e402e 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -5026,9 +5026,11 @@ where
// doesn't exist on the receiver's side, only on the sender's.
let fee_spike_buffer_htlc =
if funding.get_channel_type().supports_anchor_zero_fee_commitments() { 0 } else { 1 };
- // Do not include outbound update_add_htlc's in the holding cell, or those which haven't yet been ACK'ed
- // by the counterparty (ie. LocalAnnounced HTLCs)
- let include_counterparty_unknown_htlcs = false;
+ // While these HTLCs may currently be unknown to our counterparty, they can
+ // end up in commitments soon. Moreover, we are considering failing a
+ // single HTLC here, not the entire channel, so we opt to be conservative
+ // in what we accept to forward.
+ let include_counterparty_unknown_htlcs = true;
// A `None` `HTLCCandidate` is used as in this case because we're already accounting for
// the incoming HTLC as it has been fully committed by both sides.
let next_local_commitment_stats = self
Why this scored 61/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.