Add an InvoiceRequestFailed event
authorJeffrey Czyz <jkczyz@gmail.com>
Tue, 18 Jul 2023 19:41:50 +0000 (14:41 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Thu, 7 Sep 2023 16:08:53 +0000 (11:08 -0500)
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
lightning/src/ln/channelmanager.rs
pending_changelog/invoice_request_failed_downgrade.txt [new file with mode: 0644]

index f4f7a7cca9a5ad33c5346351d769763193220916..bb98e271597309d057ca4712b394e302b35cddc3 100644 (file)
@@ -508,6 +508,14 @@ pub enum Event {
                /// serialized prior to LDK version 0.0.117.
                sender_intended_total_msat: Option<u64>,
        },
+       /// 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.
index cff9837fcebb8f437e911f2872057e5a490631f6..b0f4ef4e094d7d7d8d89014a94cff17e3afd1699 100644 (file)
@@ -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 (file)
index 0000000..d701cef
--- /dev/null
@@ -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.