Skip to content

Add BOLT12 support to LSPS2 flow#817

Open
tnull wants to merge 4 commits into
lightningdevkit:mainfrom
tnull:2026-03-lsps2-bolt12-router-integration
Open

Add BOLT12 support to LSPS2 flow#817
tnull wants to merge 4 commits into
lightningdevkit:mainfrom
tnull:2026-03-lsps2-bolt12-router-integration

Conversation

@tnull

@tnull tnull commented Mar 5, 2026

Copy link
Copy Markdown
Collaborator

Based on lightningdevkit/rust-lightning#4463

We implement the LSPS2 flow for BOLT12 and async payments.

@ldk-reviews-bot

ldk-reviews-bot commented Mar 5, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull tnull marked this pull request as draft March 5, 2026 13:38
@tnull tnull force-pushed the 2026-03-lsps2-bolt12-router-integration branch 2 times, most recently from c62ca3a to b0eef7c Compare March 25, 2026 09:11
@tnull tnull force-pushed the 2026-03-lsps2-bolt12-router-integration branch 2 times, most recently from 2210e23 to db9b5ae Compare April 7, 2026 16:12
@tnull tnull added this to the 0.8 milestone Apr 20, 2026
@tnull tnull force-pushed the 2026-03-lsps2-bolt12-router-integration branch from f894fad to 2fb92ba Compare June 9, 2026 11:37
@tnull tnull requested a review from jkczyz June 9, 2026 11:38
@tnull tnull marked this pull request as ready for review June 9, 2026 11:38
tnull added 4 commits June 9, 2026 14:28
Point the Rust Lightning dependency overrides at the unmerged LSPS2 PR revisions and carry the temporary API updates needed for LDK Node to compile against them.

Co-Authored-By: HAL 9000
Encode LSPS2 parameters in a shared payment metadata type so both BOLT11 invoices and BOLT12 payment contexts can carry the fee limits needed when handling intercepted payments.

Co-Authored-By: HAL 9000
Route BOLT12 payments through the LSPS2-aware router and expose JIT-channel receive flows so offers can carry the LSP invoice parameters needed for intercepted payments.

Co-Authored-By: HAL 9000
Exercise fixed, variable, and async BOLT12 receive flows with LSPS2 JIT channels so the payment metadata and fee-limit handling remain covered.

Co-Authored-By: HAL 9000
@tnull tnull force-pushed the 2026-03-lsps2-bolt12-router-integration branch from 2fb92ba to fc22dd0 Compare June 9, 2026 12:31

@jkczyz jkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like HAL 9000 likes to wrap commit messages.

Comment thread src/payment/metadata.rs

impl LSPS2Bolt12PaymentMetadataDecoder for LdkNodeLSPS2Bolt12PaymentMetadataDecoder {
fn decode_lsps2_invoice_parameters(
&self, payment_metadata: &BTreeMap<u64, Vec<u8>>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe have LdkNodeLSPS2Bolt12PaymentMetadataDecoder wrap &BTreeMap<u64, Vec<u8>>?

Comment thread src/payment/metadata.rs
Comment on lines +40 to +45
payment_metadata
.get(&LDK_NODE_BOLT12_PAYMENT_METADATA_KEY)
.and_then(|encoded| PaymentMetadata::read(&mut &encoded[..]).ok())
.and_then(|metadata| metadata.lsps2_bolt12_invoice_parameters)
.into_iter()
.collect()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this wants to return a Vec to support multiple LSPs? How do we plan to support that in PaymentMetadata?

Comment thread src/payment/bolt12.rs
Comment on lines +319 to +342
let mut offer_builder = if let Some(payment_metadata) = payment_metadata {
self.channel_manager.create_offer_builder_using_router(PaymentMetadataMessageRouter {
inner: Arc::clone(&self.message_router),
payment_metadata,
})
} else {
self.channel_manager.create_offer_builder()
}
.map_err(|e| {
log_error!(self.logger, "Failed to create offer builder: {:?}", e);
Error::OfferCreationFailed
})?;

if let Some(expiry_secs) = expiry_secs {
let absolute_expiry = (SystemTime::now() + Duration::from_secs(expiry_secs as u64))
.duration_since(UNIX_EPOCH)
.unwrap();
offer_builder = offer_builder.absolute_expiry(absolute_expiry);
}

offer_builder.description(description.to_string()).build().map_err(|e| {
log_error!(self.logger, "Failed to create offer: {:?}", e);
Error::OfferCreationFailed
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider DRY'ing this up.

Comment thread src/types.rs
Arc<Logger>,
Arc<KeysManager>,
>;
pub(crate) type MessageRouter = InnerMessageRouter;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not PaymentMetadataMessageRouter?

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.

3 participants