Add PendingOutboundPayment::InvoiceReceived
authorJeffrey Czyz <jkczyz@gmail.com>
Wed, 30 Aug 2023 17:01:15 +0000 (12:01 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Thu, 7 Sep 2023 21:54:09 +0000 (16:54 -0500)
When a BOLT 12 invoice has been received, a payment attempt is made and
any errors result in abandoning the PendingOutboundPayment. This results
in generating at PaymentFailed event, which has a PaymentHash. Thus,
when receiving an invoice, transition from AwaitingInvoice to a new
InvoiceReceived state, the latter of which contains a PaymentHash such
the abandon_payment helper can still be used.

lightning/src/ln/channelmanager.rs
lightning/src/ln/outbound_payment.rs

index 85fb7852bfe3232c3753717b32124fc8129a00e6..c7aa0dd021a1a2e0c5d638dcc57dd778cbad140c 100644 (file)
@@ -1683,7 +1683,7 @@ pub enum ChannelShutdownState {
 /// These include payments that have yet to find a successful path, or have unresolved HTLCs.
 #[derive(Debug, PartialEq)]
 pub enum RecentPaymentDetails {
-       /// When an invoice was requested but not yet received, and thus a payment has not been sent.
+       /// When an invoice was requested and thus a payment has not yet been sent.
        AwaitingInvoice {
                /// Identifier for the payment to ensure idempotency.
                payment_id: PaymentId,
@@ -2423,6 +2423,10 @@ where
                                PendingOutboundPayment::AwaitingInvoice { .. } => {
                                        Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
                                },
+                               // InvoiceReceived is an intermediate state and doesn't need to be exposed
+                               PendingOutboundPayment::InvoiceReceived { .. } => {
+                                       Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
+                               },
                                PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => {
                                        Some(RecentPaymentDetails::Pending {
                                                payment_hash: *payment_hash,
@@ -8361,6 +8365,7 @@ where
                                        }
                                }
                                PendingOutboundPayment::AwaitingInvoice { .. } => {},
+                               PendingOutboundPayment::InvoiceReceived { .. } => {},
                                PendingOutboundPayment::Fulfilled { .. } => {},
                                PendingOutboundPayment::Abandoned { .. } => {},
                        }
index e154b3f0d73d9736eb7afc567d768117e8ff8202..cf60c2cf2fa8a0caad592065785187aba276b30d 100644 (file)
@@ -53,6 +53,9 @@ pub(crate) enum PendingOutboundPayment {
        AwaitingInvoice {
                timer_ticks_without_response: u8,
        },
+       InvoiceReceived {
+               payment_hash: PaymentHash,
+       },
        Retryable {
                retry_strategy: Option<Retry>,
                attempts: PaymentAttempts,
@@ -152,6 +155,7 @@ impl PendingOutboundPayment {
                match self {
                        PendingOutboundPayment::Legacy { .. } => None,
                        PendingOutboundPayment::AwaitingInvoice { .. } => None,
+                       PendingOutboundPayment::InvoiceReceived { payment_hash } => Some(*payment_hash),
                        PendingOutboundPayment::Retryable { payment_hash, .. } => Some(*payment_hash),
                        PendingOutboundPayment::Fulfilled { payment_hash, .. } => *payment_hash,
                        PendingOutboundPayment::Abandoned { payment_hash, .. } => Some(*payment_hash),
@@ -165,10 +169,8 @@ impl PendingOutboundPayment {
                                PendingOutboundPayment::Retryable { session_privs, .. } |
                                PendingOutboundPayment::Fulfilled { session_privs, .. } |
                                PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs,
-                       PendingOutboundPayment::AwaitingInvoice { .. } => {
-                               debug_assert!(false);
-                               return;
-                       },
+                       PendingOutboundPayment::AwaitingInvoice { .. } |
+                               PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); return; },
                });
                let payment_hash = self.payment_hash();
                *self = PendingOutboundPayment::Fulfilled { session_privs, payment_hash, timer_ticks_without_htlcs: 0 };
@@ -183,6 +185,12 @@ impl PendingOutboundPayment {
                                payment_hash: *payment_hash,
                                reason: Some(reason)
                        };
+               } else if let PendingOutboundPayment::InvoiceReceived { payment_hash } = self {
+                       *self = PendingOutboundPayment::Abandoned {
+                               session_privs: HashSet::new(),
+                               payment_hash: *payment_hash,
+                               reason: Some(reason)
+                       };
                }
        }
 
@@ -195,10 +203,8 @@ impl PendingOutboundPayment {
                                PendingOutboundPayment::Abandoned { session_privs, .. } => {
                                        session_privs.remove(session_priv)
                                },
-                       PendingOutboundPayment::AwaitingInvoice { .. } => {
-                               debug_assert!(false);
-                               false
-                       },
+                       PendingOutboundPayment::AwaitingInvoice { .. } |
+                               PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); false },
                };
                if remove_res {
                        if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self {
@@ -217,11 +223,9 @@ impl PendingOutboundPayment {
                        PendingOutboundPayment::Legacy { session_privs } |
                                PendingOutboundPayment::Retryable { session_privs, .. } => {
                                        session_privs.insert(session_priv)
-                               }
-                       PendingOutboundPayment::AwaitingInvoice { .. } => {
-                               debug_assert!(false);
-                               false
-                       },
+                               },
+                       PendingOutboundPayment::AwaitingInvoice { .. } |
+                               PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); false },
                        PendingOutboundPayment::Fulfilled { .. } => false,
                        PendingOutboundPayment::Abandoned { .. } => false,
                };
@@ -245,6 +249,7 @@ impl PendingOutboundPayment {
                                        session_privs.len()
                                },
                        PendingOutboundPayment::AwaitingInvoice { .. } => 0,
+                       PendingOutboundPayment::InvoiceReceived { .. } => 0,
                }
        }
 }
@@ -880,7 +885,9 @@ impl OutboundPayments {
                                                        log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
                                                        return
                                                },
-                                               PendingOutboundPayment::AwaitingInvoice { .. } => {
+                                               PendingOutboundPayment::AwaitingInvoice { .. } |
+                                                       PendingOutboundPayment::InvoiceReceived { .. } =>
+                                               {
                                                        log_error!(logger, "Payment not yet sent");
                                                        return
                                                },
@@ -1573,6 +1580,9 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
        (5, AwaitingInvoice) => {
                (0, timer_ticks_without_response, required),
        },
+       (7, InvoiceReceived) => {
+               (0, payment_hash, required),
+       },
 );
 
 #[cfg(test)]