Skip to content

Commit 0ff5708

Browse files
committed
Utility for creating and sending InvoiceRequests
Add a utility to ChannelManager for creating an InvoiceRequest for an Offer such that derived keys are used for the payer id. This allows for stateless verification of any Invoice messages before it is paid. Also tracks future payments using the given PaymentId such that the corresponding Invoice is paid only once.
1 parent 6a7beb4 commit 0ff5708

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
5656
use crate::ln::outbound_payment;
5757
use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs};
5858
use crate::ln::wire::Encode;
59-
use crate::offers::offer::{DerivedMetadata, OfferBuilder};
59+
use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder};
6060
use crate::offers::parse::Bolt12SemanticError;
6161
use crate::offers::refund::RefundBuilder;
62-
use crate::onion_message::{OffersMessage, PendingOnionMessage};
62+
use crate::onion_message::{Destination, OffersMessage, PendingOnionMessage};
6363
use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider, WriteableEcdsaChannelSigner};
6464
use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
6565
use crate::util::wakers::{Future, Notifier};
@@ -6880,6 +6880,70 @@ where
68806880
Ok(builder)
68816881
}
68826882

6883+
/// Creates an [`InvoiceRequest`] for an [`Offer`] from the given parameters and enqueues it to
6884+
/// be sent via an onion message.
6885+
///
6886+
/// Uses [`InvoiceRequestBuilder`] such that the [`InvoiceRequest`] it builds is recognized by
6887+
/// the [`ChannelManager`] when handling [`Bolt12Invoice`] messages for the request.
6888+
///
6889+
/// The provided `payment_id` is used to ensure that only one invoice is paid for the request.
6890+
///
6891+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
6892+
/// [`InvoiceRequestBuilder`]: crate::offers::invoice_request::InvoiceRequestBuilder
6893+
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
6894+
pub fn request_invoice(
6895+
&self, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
6896+
payer_note: Option<String>, payment_id: PaymentId, retry_strategy: Retry
6897+
) -> Result<(), Bolt12SemanticError> {
6898+
let expanded_key = &self.inbound_payment_key;
6899+
let entropy = &*self.entropy_source;
6900+
let secp_ctx = &self.secp_ctx;
6901+
6902+
let builder = offer.request_invoice_deriving_payer_id(
6903+
expanded_key, entropy, secp_ctx, payment_id
6904+
)?;
6905+
let builder = match quantity {
6906+
None => builder,
6907+
Some(quantity) => builder.quantity(quantity)?,
6908+
};
6909+
let builder = match amount_msats {
6910+
None => builder,
6911+
Some(amount_msats) => builder.amount_msats(amount_msats)?,
6912+
};
6913+
let builder = match payer_note {
6914+
None => builder,
6915+
Some(payer_note) => builder.payer_note(payer_note),
6916+
};
6917+
6918+
let invoice_request = builder.build_and_sign()?;
6919+
let reply_path = self.create_one_hop_blinded_path();
6920+
6921+
self.pending_outbound_payments
6922+
.add_new_awaiting_invoice(payment_id, retry_strategy)
6923+
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
6924+
6925+
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
6926+
if offer.paths().is_empty() {
6927+
let message = PendingOnionMessage {
6928+
contents: OffersMessage::InvoiceRequest(invoice_request),
6929+
destination: Destination::Node(offer.signing_pubkey()),
6930+
reply_path: Some(reply_path),
6931+
};
6932+
pending_offers_messages.push(message);
6933+
} else {
6934+
for path in offer.paths() {
6935+
let message = PendingOnionMessage {
6936+
contents: OffersMessage::InvoiceRequest(invoice_request.clone()),
6937+
destination: Destination::BlindedPath(path.clone()),
6938+
reply_path: Some(reply_path.clone()),
6939+
};
6940+
pending_offers_messages.push(message);
6941+
}
6942+
}
6943+
6944+
Ok(())
6945+
}
6946+
68836947
/// Gets a payment secret and payment hash for use in an invoice given to a third party wishing
68846948
/// to pay us.
68856949
///

0 commit comments

Comments
 (0)