Repository navigation
Description
Support batched JIT channel funding in the LSPS2 service
Motivation
We're running LDK Server's experimental LSPS2 service (#52) as an LSP backend, with an operator-policy layer on top. bLIP-52 / LSPS2 explicitly anticipates batching multiple JIT channel opens into a single funding transaction, and since on-chain fees dominate the cost of small JIT opens, batching is the main lever for lowering the minimum economical channel size an LSP can offer.
Current behavior
LDK Server / ldk-node funds one channel per transaction: on FundingGenerationReady, a single funding tx is built from the internal wallet and funding_transaction_generated is called. ChannelManager::batch_funding_transaction_generated exists in rust-lightning but is never surfaced, and the event handler isn't pluggable — so batching can't be layered on from outside without a fork.
Interaction with the LSPS2 trust model
The bound on any batching/accumulation window depends on client_trusts_lsp (see also the client-trusts-LSP flow discussion in ldk-node#479), and this shapes the API that would be needed:
client_trusts_lsp=true(our deployment): broadcast can be deferred until after clients claim, so the accumulation window is not bounded by settlement latency. However, batch composition freezes at the first preimage release: clients release preimages against zero-conf commitment transactions spending a specific funding outpoint, and rebuilding the batch tx would change the txid and invalidate outpoints that clients have already settled against. Nothing in LSPS2 supports re-negotiating funding with a client who has already given up a preimage. So: broadcast is deferrable, but eviction/rebuild only applies before any member settles.client_trusts_lsp=false(spec default): the funding tx must be broadcast before asking any client to release a preimage, so the window is additionally bounded by the first payment that needs to settle.- Mixed batches: a single
client_trusts_lsp=falsemember collapses the whole batch's window back to that member's settlement time, so the policy layer should segregate batches by trust mode.
Upstream API gap: batch_funding_transaction_generated, like its single-channel sibling, hands the tx to ChannelManager for broadcast once counterparty signatures arrive. The client_trusts_lsp=true flow needs a manual-broadcast variant — the batch analogue of unsafe_manual_funding_transaction_generated / FundingTxBroadcastSafe, which the single-channel LSPS2 service path already uses. As far as we can tell no batch equivalent exists, so this is really two pieces of work: surfacing batching in ldk-node / LDK Server, and a batch manual-broadcast API upstream in rust-lightning.
Other constraints we're aware of
- LDK's batch funding API currently covers V1 opens only (no dual-funded/V2), and a batched V1 funding tx isn't RBF-able. Batch size is therefore a risk/latency knob as much as a fee knob.
- Non-RBF + deliberately deferred broadcast means the feerate chosen at build time can be stale at broadcast time. The batch tx should always carry an LSP change output so CPFP is available, and a max-deferral deadline should force broadcast before the estimate degrades too far.
- While broadcast is withheld, the funding inputs must be reserved so the LSP's own wallet can't accidentally double-spend them, and claimed-but-unbroadcast channels should count against the zero-conf exposure limit.
Activity
joostjager commentedon Jul 28, 2026
I am looking at this through the lens of helping drive adoption in the near term. A few questions I have:
I agree that batching may become important at greater scale or during a higher-fee market. I am less certain that it is currently a significant driver of adoption, unless an operator already expects substantial concurrent JIT-channel volume.
f3r10 commentedon Jul 30, 2026
This is really relevant to a project I've been building (https://github.com/f3r10/lightning-ecommerce, a self-custodial JIT-channel checkout flow on top of LDK/LSPS2) — right now it is not possible to offer small-ticket items because the funding tx fee alone makes a small JIT channel uneconomical for the LSP side. So I'd love to understand this better, and eventually help if that's useful.
A few things I'm trying to wrap my head around:
LSPS2ServiceConfigis just passed through inldk-server/src/util/config.rs), and the actualFundingGenerationReadyhandling lives in ldk-node'sevent.rs/liquidity/service/lsps2.rs. Is the expectation that this work mostly happens upstream in ldk-node (and rust-lightning for the batch broadcast-safe API), with ldk-server only needing to expose new config once that lands? Or is there ldk-server-specific work I'm not seeing?client_trusts_lsp=true(funding_transaction_generated_manual_broadcast+ aset_funding_tx_broadcast_safe-style call). Would batching for theclient_trusts_lsp=falsecase (broadcast immediately, no new upstream API needed) be a reasonable smaller first step, separate from the harder deferred/batched-broadcast case forclient_trusts_lsp=true?FundingGenerationReadyevents over a fixed window or up to a max batch size before callingbatch_funding_transaction_generated, and eats the latency cost for early joiners? Curious if there's already a preferred design here (or prior art from other LSP implementations) before someone goes and builds something that doesn't match what you have in mind.Happy to dig further and take a stab at an initial implementation (probably starting with the simpler
client_trusts_lsp=falsebatching path in ldk-node) if that's a direction the maintainers want explored. @ConorOkus @benthecarmanConorOkus commentedon Aug 6, 2026
Hi @f3r10, most of this work will happen upstream in ldk-node/rust-lightning. What solution do you feel makes most sense for your project? We have not looked into this in too much detail yet, so we are open to suggestions.
f3r10 commentedon Aug 10, 2026
Some context on why I care about this: I'm building lightning-ecommerce, a self-custodial payment library so merchants can accept Lightning payments without managing on-chain reserves or channels themselves — LSPS2 JIT channels are the core mechanism, opened on-demand when a customer's payment arrives. The problem is that small-ticket items break this in two separate ways: this issue (funding tx fee makes a small JIT channel uneconomical for the LSP to open at all), and a related one I filed after debugging it directly — ldk-node#913, where even a channel that does get opened can fail to forward the first HTLC because the default 1000-sat channel reserve eats most of the usable capacity on a minimal-size JIT channel. Both point at the same gap: JIT channels aren't really usable yet for small payments.
For my use case specifically,
client_trusts_lsp=falsebatching seems like the more sensible starting point:batch_funding_transaction_generatedalready exists and works today for the immediate-broadcast path, so this needs no new upstream primitive — just accumulation logic in ldk-node's event handling to groupFundingGenerationReadyevents into one funding tx before calling it.client_trusts_lsp=truebatching would need a new batch-aware manual-broadcast API (there's nobatch_..._manual_broadcastequivalent upstream currently), and it couples settlement across customers — one slow-to-claim customer in the batch would stall broadcast, and therefore checkout completion, for everyone else in it. For a merchant checkout flow where speed matters, that coupling is a real cost, not just an implementation nuisance.Happy to take a first pass at the accumulation logic for the
client_trusts_lsp=falsepath in ldk-node's event handling, if that's useful @ConorOkus