From: Jeffrey Czyz Date: Sat, 13 Apr 2024 23:20:19 +0000 (-0500) Subject: Use BOLT 12 PaymentPurpose variants X-Git-Tag: v0.0.123-beta~7^2~3 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=0c52ea23dc6adfb9189f776449e78c828fa5d1f4;p=rust-lightning Use BOLT 12 PaymentPurpose variants When constructing a PaymentPurpose in ChannelManager, use the PaymentContext from OnionPayload to determine which variant to construct, including those for BOLT 12 payments. --- diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index 94df71b69..2716532e0 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -135,6 +135,34 @@ impl PaymentPurpose { PaymentPurpose::SpontaneousPayment(..) => true, } } + + pub(crate) fn from_parts( + payment_preimage: Option, payment_secret: PaymentSecret, + payment_context: Option, + ) -> 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), }; diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 4b120748a..63fa82be6 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -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(); diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index 6a0eb6cb3..0676f574f 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -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"), }; }