Add BOLT12 LSPS2 JIT receive support#999
Open
tnull wants to merge 32 commits into
Open
Conversation
Prepare the LSPS2 client for dedicated state and storage modules. Co-Authored-By: HAL 9000
Track negotiated parameters as expiring leases so intercept identifiers cannot be reused across payments. Co-Authored-By: HAL 9000
Load cached leases in parallel at startup and remove entries that are expired or too close to expiry for safe reuse. Co-Authored-By: HAL 9000
Remove unusable leases hourly so persisted cache data cannot grow without bound. Co-Authored-By: HAL 9000
Persist negotiated parameters before making them available and consume them before constructing existing BOLT11 invoices. Co-Authored-By: HAL 9000
Move LSPS2 fee policy out of individual BOLT11 receive calls and into node configuration. A shared total limit gives every receive flow one policy across all configured liquidity sources. Co-Authored-By: HAL 9000
Prefer the cheapest eligible cached lease across configured LSPs and negotiate only when the cache has no parameters allowed by the node-wide fee policy. Co-Authored-By: HAL 9000
Make room for a dedicated offers message handler without mixing networking concerns into the public BOLT12 payment API. Co-Authored-By: HAL 9000
|
👋 Thanks for assigning @TheBlueMatt as a reviewer! |
This was referenced Jul 22, 2026
tnull
force-pushed
the
2026-07-bolt12-lsps2-ng-alt
branch
3 times, most recently
from
July 22, 2026 09:41
fc05da7 to
badf902
Compare
tnull
force-pushed
the
2026-07-bolt12-lsps2-ng-alt
branch
from
July 22, 2026 10:12
badf902 to
f83b7ed
Compare
Build against the Rust Lightning revision exposing BOLT12 invoice MPP response control. Adapt forwarded-amount handling to its non-optional event field. Co-Authored-By: HAL 9000
Persist a bounded LRU of fixed and variable payment requirements so restarts can pre-negotiate useful leases without making offer recognition depend on per-offer state. Prune expired targets to bound durable storage. Co-Authored-By: HAL 9000
Warm bounded fixed and variable lease targets when ordinary offers may need just-in-time liquidity. Cache state remains advisory so offers stay valid and cold invoice requests can negotiate on demand. Co-Authored-By: HAL 9000
Move shared payment metadata out of the BOLT11 module. This lets other protocols reuse it without a BOLT11 dependency. Co-Authored-By: HAL 9000
Keep LSPS2 path construction in LDK Node and fall back to exact- amount JIT paths only when ordinary blinded paths are unavailable. This avoids unnecessary channel opens and unsafe MPP splits. Decode node-local single-use lease metadata directly in the router so the internal wrapper needs no pluggable metadata abstraction. Co-Authored-By: HAL 9000
Install a node-local handler while preserving ChannelManager behavior. This creates an isolated integration point for asynchronous JIT replies. Co-Authored-By: HAL 9000
Feed every supported chain source into the node-local offers flow so invoice expiry and blinded-path CLTV limits use the current tip. Co-Authored-By: HAL 9000
Install the node-local LSPS2-aware router during node construction so BOLT12 responses can append negotiated JIT paths. Co-Authored-By: HAL 9000
Reuse one cached-or-negotiated lease path across invoice formats. Keep BOLT11 selection and fee-limit behavior unchanged. Co-Authored-By: HAL 9000
Verify and answer ordinary invoice requests with the node-owned offers flow while retaining ChannelManager handling for all other messages. Co-Authored-By: HAL 9000
Answer verified JIT invoice requests after asynchronously acquiring a single-use LSPS2 lease. Send the result through the onion messenger so negotiation does not depend on the ChannelManager event queue. Co-Authored-By: HAL 9000
Limit concurrently pending JIT invoice requests so an onion-message storm cannot create an unbounded number of lease negotiations. Hold a permit while requests wait for an offer lock or an LSP response. Co-Authored-By: HAL 9000
Keep built-in service parameters usable beyond the client cache safety margin so freshly negotiated leases are not rejected due to timing. Co-Authored-By: HAL 9000
Read fee limits from BOLT12 payment context metadata and reject unsupported withholding. Record accepted fees on inbound offer payments. Co-Authored-By: HAL 9000
Make same-amount and variable callers wait for one in-flight LSPS2 request, then recheck the shared cache before negotiating. Co-Authored-By: HAL 9000
Keep one usable lease ready after fixed or variable receive flows consume cached parameters. Foreground callers share the refill lock and reuse its result when it completes. Co-Authored-By: HAL 9000
After startup discovery, refill persisted fixed-amount and variable lease cache targets. Reuse valid leases and renegotiate only missing or stale entries so receiving can resume promptly after restart. Co-Authored-By: HAL 9000
Retry transient LSPS2 request failures for foreground acquisition and background cache refills. Preserve immediate errors for fee limits and unavailable liquidity sources. Co-Authored-By: HAL 9000
Try the next eligible provider when a selected LSP rejects or times out during the buy request. Skip remaining fee-menu entries from a failed provider while preserving bounded whole-round retries. Co-Authored-By: HAL 9000
Use resolved BOLT12 amounts to reject variable leases outside the payment range or total fee policy. Keep BOLT11 selection amountless until payment, while recording the exact BOLT12 fee limit. Co-Authored-By: HAL 9000
Cover fixed and variable BOLT12 offers through a real LSPS2 service. Verify node-ID offer addressing, fee withholding, fresh JIT channels, and the variable-amount single-path behavior. Co-Authored-By: HAL 9000
Extend the order-independent fee-selection scenario through a real BOLT12 payment. Also prove that BOLT11 consumption and BOLT12 response handling share the same replenished lease pool. Co-Authored-By: HAL 9000
Rebuild the receiver from its persisted store and pay the same long-lived offer again. Verify the pending offer survives and the exact cached lease is consumed before its replacement is negotiated. Co-Authored-By: HAL 9000
Pin the direct lease serialization format and ensure fixed-amount and variable-amount caches remain isolated. These focused checks complement the end-to-end BOLT11 and BOLT12 coverage. Co-Authored-By: HAL 9000
tnull
force-pushed
the
2026-07-bolt12-lsps2-ng-alt
branch
from
July 22, 2026 12:54
f83b7ed to
f872ce4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Based on https://git.rust-bitcoin.org/lightningdevkit/rust-lightning/pulls/4819.
This adds BOLT12 receive support over LSPS2 JIT channels using a node-local
OffersMessageHandlerandOffersMessageFlow.Offers retain ordinary blinded message paths and never contain an intercept SCID, allowing them to outlive individualPaymentLeases.Single-use
PaymentLeasesare persisted throughDataStore, while a bounded LRU persists fixed-amount and variableLeaseCacheTargets. Leases are restored and prefilled at startup, replenished after consumption, and periodically pruned when stale or close to expiry. Cache misses negotiate on demand with serialized requests, retries, and multi-LSP failover. BOLT11 uses the same cache.Every BOLT12 offer is eligible for JIT fallback when LSPS2 is configured. We first try ordinary payment paths and omit the JIT path entirely when existing inbound liquidity is sufficient. Otherwise, we consume or negotiate a lease and include a JIT path constrained to the full payment amount. Fixed invoices advertise MPP, variable invoices disable it, and
PaymentMetadataretains the fee policy needed to validate the LSP skim.Potential follow-ups: