Skip to content

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

Open
martinsaposnic wants to merge 1 commit intolsp-0.2.0_accept-underpaying-htlcs_with_timing_logsfrom
fix/splice-htlc-max-in-flight-timing-logs
Open

fix: rescale HTLC in-flight caps on splice promotion#17
martinsaposnic wants to merge 1 commit intolsp-0.2.0_accept-underpaying-htlcs_with_timing_logsfrom
fix/splice-htlc-max-in-flight-timing-logs

Conversation

@martinsaposnic
Copy link
Copy Markdown

Summary

Cherry-pick of #15 onto the lsp-0.2.0_accept-underpaying-htlcs_with_timing_logs branch.

This is the rust-lightning branch actually consumed by @moneydevkit/lightning-js (via ldk-node branch lsp-0.7.0_accept-underpaying-htlcs_with_timing_logs, rev 4309f479, which pins rust-lightning rev 070b31d93). Without this fix merged HERE, every lightning-js build on npm force-closes channels on splice in production.

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. Because lightning-js runs on the client/receiver side, this branch is where the receiver-side fix lands.

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. Also tightens test_splice_in's assertion (it compared msats to sats and passed vacuously).

E2E validation

Full regtest run with LSPS4 JIT splice, LSP on #15 + client (bitcoin-ibd) on this patch:

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

Pre-fix: receiver force-closed the channel on the 80k splice payment.

Checklist

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