Skip to content

Commit ade9f8e

Browse files
Util for blinded paths to configure an async recipient
As part of serving static invoices to payers on behalf of often-offline recipients, these recipients need a way to contact the static invoice server to retrieve blinded paths to include in their offers. Add a utility to create blinded paths for this purpose as a static invoice server. The recipient will be configured with the resulting paths and use them to request offer paths on startup.
1 parent 638b41b commit ade9f8e

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,24 @@ pub enum OffersContext {
405405
/// [`AsyncPaymentsMessage`]: crate::onion_message::async_payments::AsyncPaymentsMessage
406406
#[derive(Clone, Debug)]
407407
pub enum AsyncPaymentsContext {
408+
/// Context used by a [`BlindedMessagePath`] provided out-of-band to an async recipient, where the
409+
/// context is provided back to the static invoice server in corresponding [`OfferPathsRequest`]s.
410+
///
411+
/// [`OfferPathsRequest`]: crate::onion_message::async_payments::OfferPathsRequest
412+
OfferPathsRequest {
413+
/// An identifier for the async recipient that is requesting blinded paths to include in their
414+
/// [`Offer::paths`]. This ID will be surfaced when the async recipient eventually sends a
415+
/// corresponding [`ServeStaticInvoice`] message, and can be used to rate limit the recipient.
416+
///
417+
/// [`Offer::paths`]: crate::offers::offer::Offer::paths
418+
/// [`ServeStaticInvoice`]: crate::onion_message::async_payments::ServeStaticInvoice
419+
recipient_id: Vec<u8>,
420+
/// An optional field indicating the time as duration since the Unix epoch at which this path
421+
/// expires and messages sent over it should be ignored.
422+
///
423+
/// Useful to timeout async recipients that are no longer supported as clients.
424+
path_absolute_expiry: Option<core::time::Duration>,
425+
},
408426
/// Context used by a reply path to an [`OfferPathsRequest`], provided back to us as an async
409427
/// recipient in corresponding [`OfferPaths`] messages from the static invoice server.
410428
///
@@ -528,6 +546,10 @@ impl_writeable_tlv_based_enum!(AsyncPaymentsContext,
528546
(0, offer_id, required),
529547
(2, path_absolute_expiry, required),
530548
},
549+
(4, OfferPathsRequest) => {
550+
(0, recipient_id, required),
551+
(2, path_absolute_expiry, option),
552+
},
531553
);
532554

533555
/// Contains a simple nonce for use in a blinded path's context.

lightning/src/ln/channelmanager.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11499,6 +11499,34 @@ where
1149911499
inbound_payment::get_payment_preimage(payment_hash, payment_secret, expanded_key)
1150011500
}
1150111501

11502+
/// [`BlindedMessagePath`]s for an async recipient to communicate with this node and interactively
11503+
/// build [`Offer`]s and [`StaticInvoice`]s for receiving async payments.
11504+
///
11505+
/// ## Usage
11506+
/// 1. Static invoice server calls [`Self::blinded_paths_for_async_recipient`]
11507+
/// 2. Static invoice server communicates the resulting paths out-of-band to the async recipient,
11508+
/// who calls [`Self::set_paths_to_static_invoice_server`] to configure themselves with these
11509+
/// paths
11510+
/// 3. Async recipient automatically sends [`OfferPathsRequest`]s over the configured paths, and
11511+
/// uses the resulting paths from the server's [`OfferPaths`] response to build their async
11512+
/// receive offer
11513+
///
11514+
/// If `relative_expiry` is unset, the [`BlindedMessagePath`]s will never expire.
11515+
///
11516+
/// Returns the paths that the recipient should be configured with via
11517+
/// [`Self::set_paths_to_static_invoice_server`].
11518+
///
11519+
/// The provided `recipient_id` must uniquely identify the recipient, and will be surfaced later
11520+
/// when the recipient provides us with a static invoice to persist and serve to payers on their
11521+
/// behalf.
11522+
#[cfg(async_payments)]
11523+
pub fn blinded_paths_for_async_recipient(
11524+
&self, recipient_id: Vec<u8>, relative_expiry: Option<Duration>,
11525+
) -> Result<Vec<BlindedMessagePath>, ()> {
11526+
let peers = self.get_peers_for_blinded_path();
11527+
self.flow.blinded_paths_for_async_recipient(recipient_id, relative_expiry, peers)
11528+
}
11529+
1150211530
#[cfg(any(test, async_payments))]
1150311531
pub(super) fn duration_since_epoch(&self) -> Duration {
1150411532
#[cfg(not(feature = "std"))]

lightning/src/offers/flow.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,34 @@ impl<MR: Deref> OffersMessageFlow<MR>
250250
where
251251
MR::Target: MessageRouter,
252252
{
253+
/// [`BlindedMessagePath`]s for an async recipient to communicate with this node and interactively
254+
/// build [`Offer`]s and [`StaticInvoice`]s for receiving async payments.
255+
///
256+
/// If `relative_expiry` is unset, the [`BlindedMessagePath`]s will never expire.
257+
///
258+
/// Returns the paths that the recipient should be configured with via
259+
/// [`Self::set_paths_to_static_invoice_server`].
260+
///
261+
/// Errors if blinded path creation fails or the provided `recipient_id` is larger than 1KiB.
262+
#[cfg(async_payments)]
263+
pub(crate) fn blinded_paths_for_async_recipient(
264+
&self, recipient_id: Vec<u8>, relative_expiry: Option<Duration>,
265+
peers: Vec<MessageForwardNode>,
266+
) -> Result<Vec<BlindedMessagePath>, ()> {
267+
if recipient_id.len() > 1024 {
268+
return Err(());
269+
}
270+
271+
let path_absolute_expiry =
272+
relative_expiry.map(|exp| exp.saturating_add(self.duration_since_epoch()));
273+
274+
let context = MessageContext::AsyncPayments(AsyncPaymentsContext::OfferPathsRequest {
275+
recipient_id,
276+
path_absolute_expiry,
277+
});
278+
self.create_blinded_paths(peers, context)
279+
}
280+
253281
/// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on
254282
/// the path's intended lifetime.
255283
///

0 commit comments

Comments
 (0)