Skip to content

Commit 9d3d326

Browse files
Add static invoice server messages and boilerplate
Because async recipients are not online to respond to invoice requests, the plan is for another node on the network that is always-online to serve static invoices on their behalf. The protocol is as follows: - Recipient is configured with blinded message paths to reach the static invoice server - On startup, recipient requests blinded message paths for inclusion in their offer from the static invoice server over the configured paths - Server replies with offer paths for the recipient - Recipient builds their offer using these paths and the corresponding static invoice and replies with the invoice - Server persists the invoice and confirms that they've persisted it, causing the recipient to cache the interactively built offer for use At pay-time, the payer sends an invoice request to the static invoice server, who replies with the static invoice after forwarding the invreq to the recipient (to give them a chance to provide a fresh invoice in case they're online). Here we add the requisite trait methods and onion messages to support this protocol.
1 parent 606d4b0 commit 9d3d326

File tree

7 files changed

+317
-7
lines changed

7 files changed

+317
-7
lines changed

fuzz/src/onion_message.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use lightning::ln::peer_handler::IgnoringMessageHandler;
1515
use lightning::ln::script::ShutdownScript;
1616
use lightning::offers::invoice::UnsignedBolt12Invoice;
1717
use lightning::onion_message::async_payments::{
18-
AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc,
18+
AsyncPaymentsMessageHandler, HeldHtlcAvailable, OfferPaths, OfferPathsRequest, ReleaseHeldHtlc,
19+
ServeStaticInvoice, StaticInvoicePersisted,
1920
};
2021
use lightning::onion_message::messenger::{
2122
CustomOnionMessageHandler, Destination, MessageRouter, MessageSendInstructions,
@@ -121,6 +122,29 @@ impl OffersMessageHandler for TestOffersMessageHandler {
121122
struct TestAsyncPaymentsMessageHandler {}
122123

123124
impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler {
125+
fn handle_offer_paths_request(
126+
&self, _message: OfferPathsRequest, _context: AsyncPaymentsContext,
127+
responder: Option<Responder>,
128+
) -> Option<(OfferPaths, ResponseInstruction)> {
129+
let responder = match responder {
130+
Some(resp) => resp,
131+
None => return None,
132+
};
133+
Some((OfferPaths { paths: Vec::new() }, responder.respond()))
134+
}
135+
fn handle_offer_paths(
136+
&self, _message: OfferPaths, _context: AsyncPaymentsContext, _responder: Option<Responder>,
137+
) -> Option<(ServeStaticInvoice, ResponseInstruction)> {
138+
None
139+
}
140+
fn handle_serve_static_invoice(
141+
&self, _message: ServeStaticInvoice, _context: AsyncPaymentsContext,
142+
) {
143+
}
144+
fn handle_static_invoice_persisted(
145+
&self, _message: StaticInvoicePersisted, _context: AsyncPaymentsContext,
146+
) {
147+
}
124148
fn handle_held_htlc_available(
125149
&self, _message: HeldHtlcAvailable, _context: AsyncPaymentsContext,
126150
responder: Option<Responder>,

lightning/src/ln/channelmanager.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ use crate::offers::offer::{Offer, OfferBuilder};
7474
use crate::offers::parse::Bolt12SemanticError;
7575
use crate::offers::refund::{Refund, RefundBuilder};
7676
use crate::offers::signer;
77-
use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
77+
use crate::onion_message::async_payments::{
78+
AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, OfferPaths,
79+
OfferPathsRequest, ReleaseHeldHtlc, ServeStaticInvoice, StaticInvoicePersisted
80+
};
7881
use crate::onion_message::dns_resolution::HumanReadableName;
7982
use crate::onion_message::messenger::{Destination, MessageRouter, Responder, ResponseInstruction, MessageSendInstructions};
8083
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
@@ -12562,6 +12565,27 @@ where
1256212565
MR::Target: MessageRouter,
1256312566
L::Target: Logger,
1256412567
{
12568+
fn handle_offer_paths_request(
12569+
&self, _message: OfferPathsRequest, _context: AsyncPaymentsContext,
12570+
_responder: Option<Responder>,
12571+
) -> Option<(OfferPaths, ResponseInstruction)> {
12572+
None
12573+
}
12574+
12575+
fn handle_offer_paths(
12576+
&self, _message: OfferPaths, _context: AsyncPaymentsContext, _responder: Option<Responder>,
12577+
) -> Option<(ServeStaticInvoice, ResponseInstruction)> {
12578+
None
12579+
}
12580+
12581+
fn handle_serve_static_invoice(
12582+
&self, _message: ServeStaticInvoice, _context: AsyncPaymentsContext,
12583+
) {}
12584+
12585+
fn handle_static_invoice_persisted(
12586+
&self, _message: StaticInvoicePersisted, _context: AsyncPaymentsContext,
12587+
) {}
12588+
1256512589
fn handle_held_htlc_available(
1256612590
&self, _message: HeldHtlcAvailable, _context: AsyncPaymentsContext,
1256712591
_responder: Option<Responder>

lightning/src/ln/peer_handler.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::util::ser::{VecWriter, Writeable, Writer};
2929
use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE};
3030
use crate::ln::wire;
3131
use crate::ln::wire::{Encode, Type};
32-
use crate::onion_message::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc};
32+
use crate::onion_message::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, OfferPaths, OfferPathsRequest, ServeStaticInvoice, ReleaseHeldHtlc, StaticInvoicePersisted};
3333
use crate::onion_message::dns_resolution::{DNSResolverMessageHandler, DNSResolverMessage, DNSSECProof, DNSSECQuery};
3434
use crate::onion_message::messenger::{CustomOnionMessageHandler, Responder, ResponseInstruction, MessageSendInstructions};
3535
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
@@ -151,6 +151,22 @@ impl OffersMessageHandler for IgnoringMessageHandler {
151151
}
152152
}
153153
impl AsyncPaymentsMessageHandler for IgnoringMessageHandler {
154+
fn handle_offer_paths_request(
155+
&self, _message: OfferPathsRequest, _context: AsyncPaymentsContext, _responder: Option<Responder>,
156+
) -> Option<(OfferPaths, ResponseInstruction)> {
157+
None
158+
}
159+
fn handle_offer_paths(
160+
&self, _message: OfferPaths, _context: AsyncPaymentsContext, _responder: Option<Responder>,
161+
) -> Option<(ServeStaticInvoice, ResponseInstruction)> {
162+
None
163+
}
164+
fn handle_serve_static_invoice(
165+
&self, _message: ServeStaticInvoice, _context: AsyncPaymentsContext
166+
) {}
167+
fn handle_static_invoice_persisted(
168+
&self, _message: StaticInvoicePersisted, _context: AsyncPaymentsContext,
169+
) {}
154170
fn handle_held_htlc_available(
155171
&self, _message: HeldHtlcAvailable, _context: AsyncPaymentsContext,
156172
_responder: Option<Responder>,

lightning/src/offers/static_invoice.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::offers::offer::{
3434
};
3535
use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
3636
use crate::types::features::{Bolt12InvoiceFeatures, OfferFeatures};
37-
use crate::util::ser::{CursorReadable, Iterable, WithoutLength, Writeable, Writer};
37+
use crate::util::ser::{CursorReadable, Iterable, Readable, WithoutLength, Writeable, Writer};
3838
use crate::util::string::PrintableString;
3939
use bitcoin::address::Address;
4040
use bitcoin::constants::ChainHash;
@@ -530,6 +530,13 @@ impl InvoiceContents {
530530
}
531531
}
532532

533+
impl Readable for StaticInvoice {
534+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
535+
let bytes: WithoutLength<Vec<u8>> = Readable::read(reader)?;
536+
Self::try_from(bytes.0).map_err(|_| DecodeError::InvalidValue)
537+
}
538+
}
539+
533540
impl Writeable for StaticInvoice {
534541
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
535542
WithoutLength(&self.bytes).write(writer)

0 commit comments

Comments
 (0)