From 6d0c5f00ba315981e83994774dc50c5c31d4e5ae Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Tue, 18 Jul 2023 14:41:50 -0500 Subject: [PATCH] Add an InvoiceRequestFailed event When an invoice is requested but either receives an error or never receives a response, surface an event to indicate to the user that the corresponding future payment has failed. --- lightning/src/events/mod.rs | 25 +++++++++++++++++++ lightning/src/ln/channelmanager.rs | 20 +++++++++++---- .../invoice_request_failed_downgrade.txt | 3 +++ 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 pending_changelog/invoice_request_failed_downgrade.txt diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index f4f7a7cca..bb98e2715 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -508,6 +508,14 @@ pub enum Event { /// serialized prior to LDK version 0.0.117. sender_intended_total_msat: Option, }, + /// Indicates a request for an invoice failed to yield a response in a reasonable amount of time + /// or was explicitly abandoned by [`ChannelManager::abandon_payment`]. + /// + /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment + InvoiceRequestFailed { + /// The `payment_id` to have been associated with payment for the requested invoice. + payment_id: PaymentId, + }, /// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target /// and we got back the payment preimage for it). /// @@ -1148,6 +1156,12 @@ impl Writeable for Event { (8, funding_txo, required), }); }, + &Event::InvoiceRequestFailed { ref payment_id } => { + 33u8.write(writer)?; + write_tlv_fields!(writer, { + (0, payment_id, required), + }) + }, // Note that, going forward, all new events must only write data inside of // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write // data via `write_tlv_fields`. @@ -1535,6 +1549,17 @@ impl MaybeReadable for Event { }; f() }, + 33u8 => { + let f = || { + _init_and_read_len_prefixed_tlv_fields!(reader, { + (0, payment_id, required), + }); + Ok(Some(Event::InvoiceRequestFailed { + payment_id: payment_id.0.unwrap(), + })) + }; + f() + }, // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue. // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt // reads. diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index cff9837fc..b0f4ef4e0 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -3381,10 +3381,12 @@ where } - /// Signals that no further retries for the given payment should occur. Useful if you have a + /// Signals that no further attempts for the given payment should occur. Useful if you have a /// pending outbound payment with retries remaining, but wish to stop retrying the payment before /// retries are exhausted. /// + /// # Event Generation + /// /// If no [`Event::PaymentFailed`] event had been generated before, one will be generated as soon /// as there are no remaining pending HTLCs for this payment. /// @@ -3392,11 +3394,19 @@ where /// wait until you receive either a [`Event::PaymentFailed`] or [`Event::PaymentSent`] event to /// determine the ultimate status of a payment. /// - /// If an [`Event::PaymentFailed`] event is generated and we restart without this - /// [`ChannelManager`] having been persisted, another [`Event::PaymentFailed`] may be generated. + /// # Requested Invoices /// - /// [`Event::PaymentFailed`]: events::Event::PaymentFailed - /// [`Event::PaymentSent`]: events::Event::PaymentSent + /// In the case of paying a [`Bolt12Invoice`], abandoning the payment prior to receiving the + /// invoice will result in an [`Event::InvoiceRequestFailed`] and prevent any attempts at paying + /// it once received. The other events may only be generated once the invoice has been received. + /// + /// # Restart Behavior + /// + /// If an [`Event::PaymentFailed`] is generated and we restart without first persisting the + /// [`ChannelManager`], another [`Event::PaymentFailed`] may be generated; likewise for + /// [`Event::InvoiceRequestFailed`]. + /// + /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn abandon_payment(&self, payment_id: PaymentId) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments.abandon_payment(payment_id, PaymentFailureReason::UserAbandoned, &self.pending_events); diff --git a/pending_changelog/invoice_request_failed_downgrade.txt b/pending_changelog/invoice_request_failed_downgrade.txt new file mode 100644 index 000000000..d701cef04 --- /dev/null +++ b/pending_changelog/invoice_request_failed_downgrade.txt @@ -0,0 +1,3 @@ +## Backwards Compatibility + +* If an `Event::InvoiceRequestFailed` was generated for a BOLT 12 payment (#2371), downgrading will result in the payment silently failing if the event had not been processed yet. -- 2.39.5