Use BOLT 12 PaymentPurpose variants
authorJeffrey Czyz <jkczyz@gmail.com>
Sat, 13 Apr 2024 23:20:19 +0000 (18:20 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Thu, 18 Apr 2024 14:15:23 +0000 (09:15 -0500)
When constructing a PaymentPurpose in ChannelManager, use the
PaymentContext from OnionPayload to determine which variant to
construct, including those for BOLT 12 payments.

lightning/src/events/mod.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/offers_tests.rs

index 94df71b69eaab51e2f074a6b81d30902a0b002f4..2716532e099a5e318596230fdacf6a0cc88be0aa 100644 (file)
@@ -135,6 +135,34 @@ impl PaymentPurpose {
                        PaymentPurpose::SpontaneousPayment(..) => true,
                }
        }
+
+       pub(crate) fn from_parts(
+               payment_preimage: Option<PaymentPreimage>, payment_secret: PaymentSecret,
+               payment_context: Option<PaymentContext>,
+       ) -> Self {
+               match payment_context {
+                       Some(PaymentContext::Unknown(_)) | None => {
+                               PaymentPurpose::Bolt11InvoicePayment {
+                                       payment_preimage,
+                                       payment_secret,
+                               }
+                       },
+                       Some(PaymentContext::Bolt12Offer(context)) => {
+                               PaymentPurpose::Bolt12OfferPayment {
+                                       payment_preimage,
+                                       payment_secret,
+                                       payment_context: context,
+                               }
+                       },
+                       Some(PaymentContext::Bolt12Refund(context)) => {
+                               PaymentPurpose::Bolt12RefundPayment {
+                                       payment_preimage,
+                                       payment_secret,
+                                       payment_context: context,
+                               }
+                       },
+               }
+       }
 }
 
 impl_writeable_tlv_based_enum!(PaymentPurpose,
@@ -1408,28 +1436,7 @@ impl MaybeReadable for Event {
                                                (11, payment_context, option),
                                        });
                                        let purpose = match payment_secret {
-                                               Some(secret) => match payment_context {
-                                                       Some(PaymentContext::Unknown(_)) | None => {
-                                                               PaymentPurpose::Bolt11InvoicePayment {
-                                                                       payment_preimage,
-                                                                       payment_secret: secret,
-                                                               }
-                                                       },
-                                                       Some(PaymentContext::Bolt12Offer(context)) => {
-                                                               PaymentPurpose::Bolt12OfferPayment {
-                                                                       payment_preimage,
-                                                                       payment_secret: secret,
-                                                                       payment_context: context,
-                                                               }
-                                                       },
-                                                       Some(PaymentContext::Bolt12Refund(context)) => {
-                                                               PaymentPurpose::Bolt12RefundPayment {
-                                                                       payment_preimage,
-                                                                       payment_secret: secret,
-                                                                       payment_context: context,
-                                                               }
-                                                       },
-                                               },
+                                               Some(secret) => PaymentPurpose::from_parts(payment_preimage, secret, payment_context),
                                                None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()),
                                                None => return Err(msgs::DecodeError::InvalidValue),
                                        };
index 4b120748ad80aef53d0adc20bfa93665caf322b2..63fa82be63e09376aede8225cc5350363543c856 100644 (file)
@@ -1566,11 +1566,11 @@ where
 /// // On the event processing thread
 /// channel_manager.process_pending_events(&|event| match event {
 ///     Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
-///         PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
+///         PaymentPurpose::Bolt12OfferPayment { payment_preimage: Some(payment_preimage), .. } => {
 ///             println!("Claiming payment {}", payment_hash);
 ///             channel_manager.claim_funds(payment_preimage);
 ///         },
-///         PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => {
+///         PaymentPurpose::Bolt12OfferPayment { payment_preimage: None, .. } => {
 ///             println!("Unknown payment hash: {}", payment_hash);
 ///         },
 ///         // ...
@@ -1718,12 +1718,12 @@ where
 /// // On the event processing thread
 /// channel_manager.process_pending_events(&|event| match event {
 ///     Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
-///            PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
+///            PaymentPurpose::Bolt12RefundPayment { payment_preimage: Some(payment_preimage), .. } => {
 ///             assert_eq!(payment_hash, known_payment_hash);
 ///             println!("Claiming payment {}", payment_hash);
 ///             channel_manager.claim_funds(payment_preimage);
 ///         },
-///            PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => {
+///            PaymentPurpose::Bolt12RefundPayment { payment_preimage: None, .. } => {
 ///             println!("Unknown payment hash: {}", payment_hash);
 ///            },
 ///         // ...
@@ -5530,7 +5530,7 @@ where
                                                                match payment_secrets.entry(payment_hash) {
                                                                        hash_map::Entry::Vacant(_) => {
                                                                                match claimable_htlc.onion_payload {
-                                                                                       OnionPayload::Invoice { .. } => {
+                                                                                       OnionPayload::Invoice { ref payment_context, .. } => {
                                                                                                let payment_data = payment_data.unwrap();
                                                                                                let (payment_preimage, min_final_cltv_expiry_delta) = match inbound_payment::verify(payment_hash, &payment_data, self.highest_seen_timestamp.load(Ordering::Acquire) as u64, &self.inbound_payment_key, &self.logger) {
                                                                                                        Ok(result) => result,
@@ -5547,10 +5547,11 @@ where
                                                                                                                fail_htlc!(claimable_htlc, payment_hash);
                                                                                                        }
                                                                                                }
-                                                                                               let purpose = events::PaymentPurpose::Bolt11InvoicePayment {
-                                                                                                       payment_preimage: payment_preimage.clone(),
-                                                                                                       payment_secret: payment_data.payment_secret,
-                                                                                               };
+                                                                                               let purpose = events::PaymentPurpose::from_parts(
+                                                                                                       payment_preimage.clone(),
+                                                                                                       payment_data.payment_secret,
+                                                                                                       payment_context.clone(),
+                                                                                               );
                                                                                                check_total_value!(purpose);
                                                                                        },
                                                                                        OnionPayload::Spontaneous(preimage) => {
@@ -5560,10 +5561,13 @@ where
                                                                                }
                                                                        },
                                                                        hash_map::Entry::Occupied(inbound_payment) => {
-                                                                               if let OnionPayload::Spontaneous(_) = claimable_htlc.onion_payload {
-                                                                                       log_trace!(self.logger, "Failing new keysend HTLC with payment_hash {} because we already have an inbound payment with the same payment hash", &payment_hash);
-                                                                                       fail_htlc!(claimable_htlc, payment_hash);
-                                                                               }
+                                                                               let payment_context = match claimable_htlc.onion_payload {
+                                                                                       OnionPayload::Spontaneous(_) => {
+                                                                                               log_trace!(self.logger, "Failing new keysend HTLC with payment_hash {} because we already have an inbound payment with the same payment hash", &payment_hash);
+                                                                                               fail_htlc!(claimable_htlc, payment_hash);
+                                                                                       },
+                                                                                       OnionPayload::Invoice { ref payment_context, .. } => payment_context,
+                                                                               };
                                                                                let payment_data = payment_data.unwrap();
                                                                                if inbound_payment.get().payment_secret != payment_data.payment_secret {
                                                                                        log_trace!(self.logger, "Failing new HTLC with payment_hash {} as it didn't match our expected payment secret.", &payment_hash);
@@ -5573,10 +5577,11 @@ where
                                                                                                &payment_hash, payment_data.total_msat, inbound_payment.get().min_value_msat.unwrap());
                                                                                        fail_htlc!(claimable_htlc, payment_hash);
                                                                                } else {
-                                                                                       let purpose = events::PaymentPurpose::Bolt11InvoicePayment {
-                                                                                               payment_preimage: inbound_payment.get().payment_preimage,
-                                                                                               payment_secret: payment_data.payment_secret,
-                                                                                       };
+                                                                                       let purpose = events::PaymentPurpose::from_parts(
+                                                                                               inbound_payment.get().payment_preimage,
+                                                                                               payment_data.payment_secret,
+                                                                                               payment_context.clone(),
+                                                                                       );
                                                                                        let payment_claimable_generated = check_total_value!(purpose);
                                                                                        if payment_claimable_generated {
                                                                                                inbound_payment.remove_entry();
index 6a0eb6cb3b1e515d034e0e41d6487fb24484e480..0676f574fa333b931129457389155f06a1480dca 100644 (file)
@@ -43,7 +43,7 @@
 use bitcoin::network::constants::Network;
 use core::time::Duration;
 use crate::blinded_path::{BlindedPath, IntroductionNode};
-use crate::events::{Event, MessageSendEventsProvider, PaymentPurpose};
+use crate::events::{Event, MessageSendEventsProvider};
 use crate::ln::channelmanager::{PaymentId, RecentPaymentDetails, Retry, self};
 use crate::ln::functional_test_utils::*;
 use crate::ln::msgs::{ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement};
@@ -154,12 +154,11 @@ fn route_bolt12_payment<'a, 'b, 'c>(
 fn claim_bolt12_payment<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>]) {
        let recipient = &path[path.len() - 1];
        match get_event!(recipient, Event::PaymentClaimable) {
-               Event::PaymentClaimable {
-                       purpose: PaymentPurpose::Bolt11InvoicePayment {
-                               payment_preimage: Some(payment_preimage), ..
-                       }, ..
-               } => claim_payment(node, path, payment_preimage),
-               _ => panic!(),
+               Event::PaymentClaimable { purpose, .. } => match purpose.preimage() {
+                       Some(payment_preimage) => claim_payment(node, path, payment_preimage),
+                       None => panic!("No preimage in Event::PaymentClaimable"),
+               },
+               _ => panic!("No Event::PaymentClaimable"),
        };
 }