Skip to content

Commit f2909d0

Browse files
Add setter for paths to static invoice server
In future commits, as part of being an async recipient, we will interactively build offers and static invoices with an always-online node that will serve static invoices on our behalf. Here we add a setter for the blinded paths that we as an async recipient will use to contact the static invoice server to get paths to put in our offers.
1 parent ea6160d commit f2909d0

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11055,6 +11055,22 @@ where
1105511055
)
1105611056
}
1105711057

11058+
/// Sets the [`BlindedMessagePath`]s that we will use as an async recipient to interactively build
11059+
/// [`Offer`]s with a static invoice server, so the server can serve [`StaticInvoice`]s to payers
11060+
/// on our behalf when we're offline.
11061+
///
11062+
/// This method only needs to be called once when the server first takes on the recipient as a
11063+
/// client, or when the paths change, e.g. if the paths are set to expire at a particular time.
11064+
#[cfg(async_payments)]
11065+
pub fn set_paths_to_static_invoice_server(
11066+
&self, paths_to_static_invoice_server: Vec<BlindedMessagePath>,
11067+
) -> Result<(), ()> {
11068+
self.flow.set_paths_to_static_invoice_server(paths_to_static_invoice_server)?;
11069+
11070+
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
11071+
Ok(())
11072+
}
11073+
1105811074
/// Pays for an [`Offer`] using the given parameters by creating an [`InvoiceRequest`] and
1105911075
/// enqueuing it to be sent via an onion message. [`ChannelManager`] will pay the actual
1106011076
/// [`Bolt12Invoice`] once it is received.

lightning/src/offers/async_receive_offer_cache.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::util::ser::{Readable, Writeable, Writer};
2323
use core::time::Duration;
2424

2525
/// The status of this offer in the cache.
26+
#[derive(Clone)]
2627
enum OfferStatus {
2728
/// This offer has been returned to the user from the cache, so it needs to be stored until it
2829
/// expires and its invoice needs to be kept updated.
@@ -42,6 +43,7 @@ enum OfferStatus {
4243
Pending,
4344
}
4445

46+
#[derive(Clone)]
4547
struct AsyncReceiveOffer {
4648
offer: Offer,
4749
/// Whether this offer is used, ready for use, or pending invoice persistence with the static
@@ -141,8 +143,35 @@ impl AsyncReceiveOfferCache {
141143
pub(super) fn paths_to_static_invoice_server(&self) -> Vec<BlindedMessagePath> {
142144
self.paths_to_static_invoice_server.clone()
143145
}
146+
147+
/// Sets the [`BlindedMessagePath`]s that we will use as an async recipient to interactively build
148+
/// [`Offer`]s with a static invoice server, so the server can serve [`StaticInvoice`]s to payers
149+
/// on our behalf when we're offline.
150+
///
151+
/// [`StaticInvoice`]: crate::offers::static_invoice::StaticInvoice
152+
#[cfg(async_payments)]
153+
pub fn set_paths_to_static_invoice_server(
154+
&mut self, paths_to_static_invoice_server: Vec<BlindedMessagePath>,
155+
) -> Result<(), ()> {
156+
if paths_to_static_invoice_server.is_empty() {
157+
return Err(());
158+
}
159+
160+
self.paths_to_static_invoice_server = paths_to_static_invoice_server;
161+
if self.offers.is_empty() {
162+
// See `AsyncReceiveOfferCache::offers`.
163+
self.offers = vec![None; MAX_CACHED_OFFERS_TARGET];
164+
}
165+
Ok(())
166+
}
144167
}
145168

169+
// The target number of offers we want to have cached at any given time, to mitigate too much
170+
// reuse of the same offer while also limiting the amount of space our offers take up on the
171+
// server's end.
172+
#[cfg(async_payments)]
173+
const MAX_CACHED_OFFERS_TARGET: usize = 10;
174+
146175
impl Writeable for AsyncReceiveOfferCache {
147176
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
148177
write_tlv_fields!(w, {

lightning/src/offers/flow.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,27 @@ where
158158
self
159159
}
160160

161+
/// Sets the [`BlindedMessagePath`]s that we will use as an async recipient to interactively build
162+
/// [`Offer`]s with a static invoice server, so the server can serve [`StaticInvoice`]s to payers
163+
/// on our behalf when we're offline.
164+
///
165+
/// This method only needs to be called once when the server first takes on the recipient as a
166+
/// client, or when the paths change, e.g. if the paths are set to expire at a particular time.
167+
#[cfg(async_payments)]
168+
pub(crate) fn set_paths_to_static_invoice_server(
169+
&self, paths_to_static_invoice_server: Vec<BlindedMessagePath>,
170+
) -> Result<(), ()> {
171+
// Store the paths in the async receive cache so they are persisted with the cache, but also
172+
// store them in-memory in the `OffersMessageFlow` so the flow has access to them when building
173+
// onion messages to send to the static invoice server, without introducing undesirable lock
174+
// dependencies with the cache.
175+
*self.paths_to_static_invoice_server.lock().unwrap() =
176+
paths_to_static_invoice_server.clone();
177+
178+
let mut cache = self.async_receive_offer_cache.lock().unwrap();
179+
cache.set_paths_to_static_invoice_server(paths_to_static_invoice_server)
180+
}
181+
161182
/// Gets the node_id held by this [`OffersMessageFlow`]`
162183
fn get_our_node_id(&self) -> PublicKey {
163184
self.our_network_pubkey

0 commit comments

Comments
 (0)