@@ -58,7 +58,7 @@ use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
5858use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
5959#[cfg(test)]
6060use crate::ln::outbound_payment;
61- use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration};
61+ use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration};
6262use crate::ln::wire::Encode;
6363use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice};
6464use crate::offers::invoice_error::InvoiceError;
@@ -105,7 +105,7 @@ use core::time::Duration;
105105use core::ops::Deref;
106106
107107// Re-export this for use in the public API.
108- pub use crate::ln::outbound_payment::{PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields};
108+ pub use crate::ln::outbound_payment::{Bolt12PaymentError, PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields};
109109use crate::ln::script::ShutdownScript;
110110
111111// We hold various information about HTLC relay in the HTLC objects in Channel itself:
@@ -3996,7 +3996,36 @@ where
39963996 self.pending_outbound_payments.test_set_payment_metadata(payment_id, new_payment_metadata);
39973997 }
39983998
3999- pub(super) fn send_payment_for_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> {
3999+ /// Pays the [`Bolt12Invoice`] associated with the `payment_id` encoded in its `payer_metadata`.
4000+ ///
4001+ /// The invoice's `payer_metadata` is used to authenticate that the invoice was indeed requested
4002+ /// before attempting a payment. [`Bolt12PaymentError::UnexpectedInvoice`] is returned if this
4003+ /// fails or if the encoded `payment_id` is not recognized. The latter may happen once the
4004+ /// payment is no longer tracked because the payment was attempted after:
4005+ /// - an invoice for the `payment_id` was already paid,
4006+ /// - one full [timer tick] has elapsed since initially requesting the invoice when paying an
4007+ /// offer, or
4008+ /// - the refund corresponding to the invoice has already expired.
4009+ ///
4010+ /// To retry the payment, request another invoice using a new `payment_id`.
4011+ ///
4012+ /// Attempting to pay the same invoice twice while the first payment is still pending will
4013+ /// result in a [`Bolt12PaymentError::DuplicateInvoice`].
4014+ ///
4015+ /// Otherwise, either [`Event::PaymentSent`] or [`Event::PaymentFailed`] are used to indicate
4016+ /// whether or not the payment was successful.
4017+ ///
4018+ /// [timer tick]: Self::timer_tick_occurred
4019+ pub fn send_payment_for_bolt12_invoice(&self, invoice: &Bolt12Invoice) -> Result<(), Bolt12PaymentError> {
4020+ let secp_ctx = &self.secp_ctx;
4021+ let expanded_key = &self.inbound_payment_key;
4022+ match invoice.verify(expanded_key, secp_ctx) {
4023+ Ok(payment_id) => self.send_payment_for_verified_bolt12_invoice(invoice, payment_id),
4024+ Err(()) => Err(Bolt12PaymentError::UnexpectedInvoice),
4025+ }
4026+ }
4027+
4028+ fn send_payment_for_verified_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> {
40004029 let best_block_height = self.best_block.read().unwrap().height;
40014030 let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
40024031 self.pending_outbound_payments
@@ -10287,7 +10316,7 @@ where
1028710316 self.pending_events.lock().unwrap().push_back((event, None));
1028810317 return ResponseInstruction::NoResponse;
1028910318 } else {
10290- self.send_payment_for_bolt12_invoice (&invoice, payment_id)
10319+ self.send_payment_for_verified_bolt12_invoice (&invoice, payment_id)
1029110320 .map_err(|e| {
1029210321 log_trace!(self.logger, "Failed paying invoice: {:?}", e);
1029310322 InvoiceError::from_string(format!("{:?}", e))
0 commit comments