Skip to content

fix: rescale HTLC in-flight caps on splice promotion#15

Open
martinsaposnic wants to merge 1 commit intolsp-0.2.0from
fix/splice-htlc-max-in-flight
Open

fix: rescale HTLC in-flight caps on splice promotion#15
martinsaposnic wants to merge 1 commit intolsp-0.2.0from
fix/splice-htlc-max-in-flight

Conversation

@martinsaposnic
Copy link
Copy Markdown

Summary

Fixes HTLC-in-flight caps not being recomputed on splice promotion. Without this, any HTLC larger than the pre-splice channel's advertised cap is rejected after a splice-in, breaking LSPS4 JIT splice flows.

Symptoms observed

  • Sender: HTLCMaximum inside send_htlc, surfaces as TemporaryChannelFailure(0x1007) to the payer.
  • Receiver: Remote HTLC add would put them over our max HTLC value (<pre-splice cap>), force-closes the channel.

The receiver case is the severe one: channel lost along with any pending fees.

Root cause

On splice promotion (the core::mem::swap(&mut self.funding, funding) in channel.rs), holder_max_htlc_value_in_flight_msat and counterparty_max_htlc_value_in_flight_msat stay pinned at their pre-splice values. The assumption that channel_value is immutable no longer holds once splicing is in play.

Fix

Rescale both caps proportionally to the channel-value change on splice promotion.

Test change

Also tightens test_splice_in's post-splice assertion. The existing check was assert!(htlc_limit_msat > initial_channel_value_sat) which compares msats to sats and passes vacuously even with the bug.

E2E validation

Reproduced on regtest with LSPS4 JIT splice:

amount status
3x small (200, 400, 800 sat) pass
80k sat (triggers splice, grows channel 50k -> 167.6k) pass
3x small (300, 600, 900 sat) pass
120k sat (second splice, grows channel 167.6k -> 344k) pass

Without the fix, the 80k and 120k payments force-closed the receiver's channel.

Checklist

  • cargo check -p lightning passes
  • Reproducer validated on regtest with LSP + embedded LDK node (both sides must have this fix)
  • Upstream version of this fix to be filed separately at lightningdevkit/rust-lightning

When a splice promotes a new FundingScope, `holder_max_htlc_value_in_flight_msat`
and `counterparty_max_htlc_value_in_flight_msat` stay pinned at their pre-splice
values instead of scaling with the new channel capacity. Any HTLC larger than
the pre-splice cap is rejected:
- on the sender with HTLCMaximum inside send_htlc
- on the receiver with "Remote HTLC add would put them over our max HTLC
  value", which force-closes the channel

Both manifestations break LSPS4 JIT splice flows where the client's embedded
node first opens a small JIT channel, then splices in capacity when a larger
payment arrives. The receiver force-close is particularly damaging because
it destroys the channel along with any pending fees.

Rescale both caps proportionally to the channel-value change on splice
promotion. Also tightens the test_splice_in assertions (the previous check
compared msats to sats).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants