Skip to content

Commit 2ffe5e5

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. An alterate design could be for the async recipient to publish static invoices directly without a preceding offer, e.g. on their website. Some drawbacks of this design include: 1) No fallback to regular BOLT 12 in the case that the recipient happens to be online at pay-time. Falling back to regular BOLT 12 allows the recipient to provide a fresh invoice and regain the proof-of-payment property 2) Static invoices don't fit in a QR code 3) No automatic rotation of the static invoice, which is useful in the case that payment paths become outdated due to changing fees, etc
1 parent 24063e5 commit 2ffe5e5

File tree

6 files changed

+309
-6
lines changed

6 files changed

+309
-6
lines changed

fuzz/src/onion_message.rs

Lines changed: 26 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,
@@ -124,6 +125,30 @@ impl OffersMessageHandler for TestOffersMessageHandler {
124125
struct TestAsyncPaymentsMessageHandler {}
125126

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

lightning/src/ln/channelmanager.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ use crate::offers::parse::Bolt12SemanticError;
9898
use crate::offers::refund::Refund;
9999
use crate::offers::signer;
100100
use crate::onion_message::async_payments::{
101-
AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc,
101+
AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, OfferPaths,
102+
OfferPathsRequest, ReleaseHeldHtlc, ServeStaticInvoice, StaticInvoicePersisted,
102103
};
103104
use crate::onion_message::dns_resolution::HumanReadableName;
104105
use crate::onion_message::messenger::{
@@ -13374,6 +13375,30 @@ where
1337413375
MR::Target: MessageRouter,
1337513376
L::Target: Logger,
1337613377
{
13378+
fn handle_offer_paths_request(
13379+
&self, _message: OfferPathsRequest, _context: AsyncPaymentsContext,
13380+
_responder: Option<Responder>,
13381+
) -> Option<(OfferPaths, ResponseInstruction)> {
13382+
None
13383+
}
13384+
13385+
fn handle_offer_paths(
13386+
&self, _message: OfferPaths, _context: AsyncPaymentsContext, _responder: Option<Responder>,
13387+
) -> Option<(ServeStaticInvoice, ResponseInstruction)> {
13388+
None
13389+
}
13390+
13391+
fn handle_serve_static_invoice(
13392+
&self, _message: ServeStaticInvoice, _context: AsyncPaymentsContext,
13393+
_responder: Option<Responder>,
13394+
) {
13395+
}
13396+
13397+
fn handle_static_invoice_persisted(
13398+
&self, _message: StaticInvoicePersisted, _context: AsyncPaymentsContext,
13399+
) {
13400+
}
13401+
1337713402
fn handle_held_htlc_available(
1337813403
&self, _message: HeldHtlcAvailable, _context: AsyncPaymentsContext,
1337913404
_responder: Option<Responder>,

lightning/src/ln/peer_handler.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ use crate::ln::types::ChannelId;
3131
use crate::ln::wire;
3232
use crate::ln::wire::{Encode, Type};
3333
use crate::onion_message::async_payments::{
34-
AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc,
34+
AsyncPaymentsMessageHandler, HeldHtlcAvailable, OfferPaths, OfferPathsRequest, ReleaseHeldHtlc,
35+
ServeStaticInvoice, StaticInvoicePersisted,
3536
};
3637
use crate::onion_message::dns_resolution::{
3738
DNSResolverMessage, DNSResolverMessageHandler, DNSSECProof, DNSSECQuery,
@@ -212,6 +213,26 @@ impl OffersMessageHandler for IgnoringMessageHandler {
212213
}
213214
}
214215
impl AsyncPaymentsMessageHandler for IgnoringMessageHandler {
216+
fn handle_offer_paths_request(
217+
&self, _message: OfferPathsRequest, _context: AsyncPaymentsContext,
218+
_responder: Option<Responder>,
219+
) -> Option<(OfferPaths, ResponseInstruction)> {
220+
None
221+
}
222+
fn handle_offer_paths(
223+
&self, _message: OfferPaths, _context: AsyncPaymentsContext, _responder: Option<Responder>,
224+
) -> Option<(ServeStaticInvoice, ResponseInstruction)> {
225+
None
226+
}
227+
fn handle_serve_static_invoice(
228+
&self, _message: ServeStaticInvoice, _context: AsyncPaymentsContext,
229+
_responder: Option<Responder>,
230+
) {
231+
}
232+
fn handle_static_invoice_persisted(
233+
&self, _message: StaticInvoicePersisted, _context: AsyncPaymentsContext,
234+
) {
235+
}
215236
fn handle_held_htlc_available(
216237
&self, _message: HeldHtlcAvailable, _context: AsyncPaymentsContext,
217238
_responder: Option<Responder>,

0 commit comments

Comments
 (0)