From: Valentine Wallace Date: Wed, 10 Jul 2024 18:55:34 +0000 (-0400) Subject: Store async payment data in PendingOutboundPayment. X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=c3ed4a2687a0dee2dea0939982128a271dde587e;p=rust-lightning Store async payment data in PendingOutboundPayment. Adds a pending outbound payment variant for async payments, which indicates that we have received a static invoice to pay and have generated a keysend preimage for the eventual payment. When the recipient comes back online, we'll transition from this new state to Retryable and actually forward the HTLCs. --- diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 730332d2e..d88bf2c4c 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -3374,6 +3374,9 @@ where PendingOutboundPayment::InvoiceReceived { .. } => { Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id }) }, + PendingOutboundPayment::StaticInvoiceReceived { .. } => { + Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id }) + }, PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => { Some(RecentPaymentDetails::Pending { payment_id: *payment_id, @@ -11722,6 +11725,7 @@ where } PendingOutboundPayment::AwaitingInvoice { .. } => {}, PendingOutboundPayment::InvoiceReceived { .. } => {}, + PendingOutboundPayment::StaticInvoiceReceived { .. } => {}, PendingOutboundPayment::Fulfilled { .. } => {}, PendingOutboundPayment::Abandoned { .. } => {}, } diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index ca0d7c17d..5849d5685 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -65,6 +65,13 @@ pub(crate) enum PendingOutboundPayment { // used anywhere. max_total_routing_fee_msat: Option, }, + StaticInvoiceReceived { + payment_hash: PaymentHash, + keysend_preimage: PaymentPreimage, + retry_strategy: Retry, + payment_release_secret: [u8; 32], + route_params: RouteParameters, + }, Retryable { retry_strategy: Option, attempts: PaymentAttempts, @@ -182,6 +189,7 @@ impl PendingOutboundPayment { PendingOutboundPayment::Legacy { .. } => None, PendingOutboundPayment::AwaitingInvoice { .. } => None, PendingOutboundPayment::InvoiceReceived { payment_hash, .. } => Some(*payment_hash), + PendingOutboundPayment::StaticInvoiceReceived { 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), @@ -196,7 +204,8 @@ impl PendingOutboundPayment { PendingOutboundPayment::Fulfilled { session_privs, .. } | PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs, PendingOutboundPayment::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); return; }, + PendingOutboundPayment::InvoiceReceived { .. } | + PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); return; }, }); let payment_hash = self.payment_hash(); *self = PendingOutboundPayment::Fulfilled { session_privs, payment_hash, timer_ticks_without_htlcs: 0 }; @@ -230,7 +239,8 @@ impl PendingOutboundPayment { session_privs.remove(session_priv) }, PendingOutboundPayment::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); false }, + PendingOutboundPayment::InvoiceReceived { .. } | + PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); false }, }; if remove_res { if let PendingOutboundPayment::Retryable { @@ -259,7 +269,8 @@ impl PendingOutboundPayment { session_privs.insert(session_priv) }, PendingOutboundPayment::AwaitingInvoice { .. } | - PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); false }, + PendingOutboundPayment::InvoiceReceived { .. } | + PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); false }, PendingOutboundPayment::Fulfilled { .. } => false, PendingOutboundPayment::Abandoned { .. } => false, }; @@ -292,6 +303,7 @@ impl PendingOutboundPayment { }, PendingOutboundPayment::AwaitingInvoice { .. } => 0, PendingOutboundPayment::InvoiceReceived { .. } => 0, + PendingOutboundPayment::StaticInvoiceReceived { .. } => 0, } } } @@ -1195,6 +1207,11 @@ impl OutboundPayments { debug_assert!(false); return }, + PendingOutboundPayment::StaticInvoiceReceived { .. } => { + log_error!(logger, "Payment already initiating"); + debug_assert!(false); + return + }, PendingOutboundPayment::Fulfilled { .. } => { log_error!(logger, "Payment already completed"); return @@ -1985,6 +2002,15 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment, (2, retry_strategy, required), (4, max_total_routing_fee_msat, option), }, + // Added in 0.0.125. Prior versions will drop these outbounds on downgrade, which is safe because + // no HTLCs are in-flight. + (9, StaticInvoiceReceived) => { + (0, payment_hash, required), + (2, keysend_preimage, required), + (4, retry_strategy, required), + (6, payment_release_secret, required), + (8, route_params, required), + }, ); #[cfg(test)]