Skip to content

Commit e99e05b

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 b52f1b4 commit e99e05b

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};
@@ -12559,6 +12562,27 @@ where
1255912562
MR::Target: MessageRouter,
1256012563
L::Target: Logger,
1256112564
{
12565+
fn handle_offer_paths_request(
12566+
&self, _message: OfferPathsRequest, _context: AsyncPaymentsContext,
12567+
_responder: Option<Responder>,
12568+
) -> Option<(OfferPaths, ResponseInstruction)> {
12569+
None
12570+
}
12571+
12572+
fn handle_offer_paths(
12573+
&self, _message: OfferPaths, _context: AsyncPaymentsContext, _responder: Option<Responder>,
12574+
) -> Option<(ServeStaticInvoice, ResponseInstruction)> {
12575+
None
12576+
}
12577+
12578+
fn handle_serve_static_invoice(
12579+
&self, _message: ServeStaticInvoice, _context: AsyncPaymentsContext,
12580+
) {}
12581+
12582+
fn handle_static_invoice_persisted(
12583+
&self, _message: StaticInvoicePersisted, _context: AsyncPaymentsContext,
12584+
) {}
12585+
1256212586
fn handle_held_htlc_available(
1256312587
&self, _message: HeldHtlcAvailable, _context: AsyncPaymentsContext,
1256412588
_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
@@ -33,7 +33,7 @@ use crate::offers::offer::{
3333
};
3434
use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage};
3535
use crate::types::features::{Bolt12InvoiceFeatures, OfferFeatures};
36-
use crate::util::ser::{CursorReadable, Iterable, WithoutLength, Writeable, Writer};
36+
use crate::util::ser::{CursorReadable, Iterable, Readable, WithoutLength, Writeable, Writer};
3737
use crate::util::string::PrintableString;
3838
use bitcoin::address::Address;
3939
use bitcoin::constants::ChainHash;
@@ -529,6 +529,13 @@ impl InvoiceContents {
529529
}
530530
}
531531

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

0 commit comments

Comments
 (0)