From d5c244ae18582a7a14dfd6ba01cfa0ebc049c957 Mon Sep 17 00:00:00 2001 From: shaavan Date: Wed, 27 Nov 2024 18:57:56 +0530 Subject: [PATCH] Move send_payment_for_bolt12_invoice to flow.rs --- lightning/src/events/mod.rs | 4 +- lightning/src/ln/channelmanager.rs | 70 +++++++----------------------- lightning/src/ln/offers_tests.rs | 8 ++-- lightning/src/offers/flow.rs | 65 ++++++++++++++++++++++++--- lightning/src/util/config.rs | 4 +- 5 files changed, 84 insertions(+), 67 deletions(-) diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index c2561213716..223c57b12dd 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -871,7 +871,7 @@ pub enum Event { /// received. /// /// This event will only be generated if [`UserConfig::manually_handle_bolt12_invoices`] is set. - /// Use [`ChannelManager::send_payment_for_bolt12_invoice`] to pay the invoice or + /// Use [`OffersMessageFlow::send_payment_for_bolt12_invoice`] to pay the invoice or /// [`ChannelManager::abandon_payment`] to abandon the associated payment. See those docs for /// further details. /// @@ -882,7 +882,7 @@ pub enum Event { /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest /// [`Refund`]: crate::offers::refund::Refund /// [`UserConfig::manually_handle_bolt12_invoices`]: crate::util::config::UserConfig::manually_handle_bolt12_invoices - /// [`ChannelManager::send_payment_for_bolt12_invoice`]: crate::ln::channelmanager::ChannelManager::send_payment_for_bolt12_invoice + /// [`OffersMessageFlow::send_payment_for_bolt12_invoice`]: crate::offers::flow::OffersMessageFlow::send_payment_for_bolt12_invoice /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment InvoiceReceived { /// The `payment_id` associated with payment for the invoice. diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 5046dca3a85..6d9adfccdd3 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -33,7 +33,7 @@ use bitcoin::secp256k1::Secp256k1; use bitcoin::{secp256k1, Sequence, Weight}; use crate::events::FundingInfo; -use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, MessageForwardNode, OffersContext}; +use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, MessageForwardNode}; use crate::blinded_path::NodeIdLookUp; use crate::blinded_path::message::BlindedMessagePath; use crate::blinded_path::payment::{BlindedPaymentPath, PaymentConstraints, PaymentContext, ReceiveTlvs}; @@ -438,11 +438,15 @@ impl Ord for ClaimableHTLC { pub trait Verification { /// Constructs an HMAC to include in [`OffersContext`] for the data along with the given /// [`Nonce`]. + /// + /// [`OffersContext`]: crate::blinded_path::message::OffersContext fn hmac_for_offer_payment( &self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Hmac; /// Authenticates the data using an HMAC and a [`Nonce`] taken from an [`OffersContext`]. + /// + /// [`OffersContext`]: crate::blinded_path::message::OffersContext fn verify_for_offer_payment( &self, hmac: Hmac, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Result<(), ()>; @@ -451,6 +455,8 @@ pub trait Verification { impl Verification for PaymentHash { /// Constructs an HMAC to include in [`OffersContext::InboundPayment`] for the payment hash /// along with the given [`Nonce`]. + /// + /// [`OffersContext::InboundPayment`]: crate::blinded_path::message::OffersContext::InboundPayment fn hmac_for_offer_payment( &self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Hmac { @@ -459,6 +465,8 @@ impl Verification for PaymentHash { /// Authenticates the payment id using an HMAC and a [`Nonce`] taken from an /// [`OffersContext::InboundPayment`]. + /// + /// [`OffersContext::InboundPayment`]: crate::blinded_path::message::OffersContext::InboundPayment fn verify_for_offer_payment( &self, hmac: Hmac, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Result<(), ()> { @@ -499,6 +507,8 @@ impl PaymentId { impl Verification for PaymentId { /// Constructs an HMAC to include in [`OffersContext::OutboundPayment`] for the payment id /// along with the given [`Nonce`]. + /// + /// [`OffersContext::OutboundPayment`]: crate::blinded_path::message::OffersContext::OutboundPayment fn hmac_for_offer_payment( &self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Hmac { @@ -507,6 +517,8 @@ impl Verification for PaymentId { /// Authenticates the payment id using an HMAC and a [`Nonce`] taken from an /// [`OffersContext::OutboundPayment`]. + /// + /// [`OffersContext::OutboundPayment`]: crate::blinded_path::message::OffersContext::OutboundPayment fn verify_for_offer_payment( &self, hmac: Hmac, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, ) -> Result<(), ()> { @@ -4376,35 +4388,6 @@ where self.pending_outbound_payments.test_set_payment_metadata(payment_id, new_payment_metadata); } - /// Pays the [`Bolt12Invoice`] associated with the `payment_id` encoded in its `payer_metadata`. - /// - /// The invoice's `payer_metadata` is used to authenticate that the invoice was indeed requested - /// before attempting a payment. [`Bolt12PaymentError::UnexpectedInvoice`] is returned if this - /// fails or if the encoded `payment_id` is not recognized. The latter may happen once the - /// payment is no longer tracked because the payment was attempted after: - /// - an invoice for the `payment_id` was already paid, - /// - one full [timer tick] has elapsed since initially requesting the invoice when paying an - /// offer, or - /// - the refund corresponding to the invoice has already expired. - /// - /// To retry the payment, request another invoice using a new `payment_id`. - /// - /// Attempting to pay the same invoice twice while the first payment is still pending will - /// result in a [`Bolt12PaymentError::DuplicateInvoice`]. - /// - /// Otherwise, either [`Event::PaymentSent`] or [`Event::PaymentFailed`] are used to indicate - /// whether or not the payment was successful. - /// - /// [timer tick]: Self::timer_tick_occurred - pub fn send_payment_for_bolt12_invoice( - &self, invoice: &Bolt12Invoice, context: Option<&OffersContext>, - ) -> Result<(), Bolt12PaymentError> { - match self.verify_bolt12_invoice(invoice, context) { - Ok(payment_id) => self.send_payment_for_verified_bolt12_invoice(invoice, payment_id), - Err(()) => Err(Bolt12PaymentError::UnexpectedInvoice), - } - } - #[cfg(async_payments)] fn initiate_async_payment( &self, invoice: &StaticInvoice, payment_id: PaymentId @@ -9528,15 +9511,10 @@ pub trait OffersMessageCommons { /// Get the vector of peers that can be used for a blinded path fn get_peer_for_blinded_path(&self) -> Vec; - /// Verify bolt12 invoice - fn verify_bolt12_invoice( - &self, invoice: &Bolt12Invoice, context: Option<&OffersContext>, - ) -> Result; - /// Gets the current configuration applied to all new channels. fn get_current_default_configuration(&self) -> &UserConfig; - /// Send payment for verified bolt12 invoice + /// Send Payment for verified BOLT12 Invoice fn send_payment_for_verified_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError>; /// Add new pending event @@ -9658,31 +9636,15 @@ where .collect::>() } - fn verify_bolt12_invoice( - &self, invoice: &Bolt12Invoice, context: Option<&OffersContext>, - ) -> Result { - let secp_ctx = &self.secp_ctx; - let expanded_key = &self.inbound_payment_key; - - match context { - None if invoice.is_for_refund_without_paths() => { - invoice.verify_using_metadata(expanded_key, secp_ctx) - }, - Some(&OffersContext::OutboundPayment { payment_id, nonce, .. }) => { - invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx) - }, - _ => Err(()), - } - } - fn get_current_default_configuration(&self) -> &UserConfig { &self.default_configuration } fn send_payment_for_verified_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> { let best_block_height = self.best_block.read().unwrap().height; - let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let features = self.bolt12_invoice_features(); + let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); + self.pending_outbound_payments .send_payment_for_bolt12_invoice( invoice, payment_id, &self.router, self.list_usable_channels(), features, diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index 144edf336b2..e7ad78eba95 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -1201,9 +1201,9 @@ fn pays_bolt12_invoice_asynchronously() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); } - assert!(bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()).is_ok()); + assert!(bob.offers_handler.send_payment_for_bolt12_invoice(&invoice, context.as_ref()).is_ok()); assert_eq!( - bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), + bob.offers_handler.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), Err(Bolt12PaymentError::DuplicateInvoice), ); @@ -1214,7 +1214,7 @@ fn pays_bolt12_invoice_asynchronously() { expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id); assert_eq!( - bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), + bob.offers_handler.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), Err(Bolt12PaymentError::DuplicateInvoice), ); @@ -1223,7 +1223,7 @@ fn pays_bolt12_invoice_asynchronously() { } assert_eq!( - bob.node.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), + bob.offers_handler.send_payment_for_bolt12_invoice(&invoice, context.as_ref()), Err(Bolt12PaymentError::UnexpectedInvoice), ); } diff --git a/lightning/src/offers/flow.rs b/lightning/src/offers/flow.rs index bd6b94f1439..f82077b270d 100644 --- a/lightning/src/offers/flow.rs +++ b/lightning/src/offers/flow.rs @@ -650,6 +650,62 @@ where } } +impl OffersMessageFlow +where + ES::Target: EntropySource, + OMC::Target: OffersMessageCommons, + MR::Target: MessageRouter, + L::Target: Logger, +{ + fn verify_bolt12_invoice( + &self, invoice: &Bolt12Invoice, context: Option<&OffersContext>, + ) -> Result { + let secp_ctx = &self.secp_ctx; + let expanded_key = &self.commons.get_expanded_key(); + + match context { + None if invoice.is_for_refund_without_paths() => { + invoice.verify_using_metadata(expanded_key, secp_ctx) + }, + Some(&OffersContext::OutboundPayment { payment_id, nonce, .. }) => { + invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx) + }, + _ => Err(()), + } + } + + /// Pays the [`Bolt12Invoice`] associated with the `payment_id` encoded in its `payer_metadata`. + /// + /// The invoice's `payer_metadata` is used to authenticate that the invoice was indeed requested + /// before attempting a payment. [`Bolt12PaymentError::UnexpectedInvoice`] is returned if this + /// fails or if the encoded `payment_id` is not recognized. The latter may happen once the + /// payment is no longer tracked because the payment was attempted after: + /// - an invoice for the `payment_id` was already paid, + /// - one full [timer tick] has elapsed since initially requesting the invoice when paying an + /// offer, or + /// - the refund corresponding to the invoice has already expired. + /// + /// To retry the payment, request another invoice using a new `payment_id`. + /// + /// Attempting to pay the same invoice twice while the first payment is still pending will + /// result in a [`Bolt12PaymentError::DuplicateInvoice`]. + /// + /// Otherwise, either [`Event::PaymentSent`] or [`Event::PaymentFailed`] are used to indicate + /// whether or not the payment was successful. + /// + /// [timer tick]: crate::ln::channelmanager::ChannelManager::timer_tick_occurred + pub fn send_payment_for_bolt12_invoice( + &self, invoice: &Bolt12Invoice, context: Option<&OffersContext>, + ) -> Result<(), Bolt12PaymentError> { + match self.verify_bolt12_invoice(invoice, context) { + Ok(payment_id) => { + self.commons.send_payment_for_verified_bolt12_invoice(invoice, payment_id) + }, + Err(()) => Err(Bolt12PaymentError::UnexpectedInvoice), + } + } +} + impl OffersMessageHandler for OffersMessageFlow where @@ -833,11 +889,10 @@ where } }, OffersMessage::Invoice(invoice) => { - let payment_id = - match self.commons.verify_bolt12_invoice(&invoice, context.as_ref()) { - Ok(payment_id) => payment_id, - Err(()) => return None, - }; + let payment_id = match self.verify_bolt12_invoice(&invoice, context.as_ref()) { + Ok(payment_id) => payment_id, + Err(()) => return None, + }; let logger = WithContext::from(&self.logger, None, None, Some(invoice.payment_hash())); diff --git a/lightning/src/util/config.rs b/lightning/src/util/config.rs index 14529327ef2..72d70ba8533 100644 --- a/lightning/src/util/config.rs +++ b/lightning/src/util/config.rs @@ -859,14 +859,14 @@ pub struct UserConfig { /// /// When set to `true`, [`Event::InvoiceReceived`] will be generated for each received /// [`Bolt12Invoice`] instead of being automatically paid after verification. Use - /// [`ChannelManager::send_payment_for_bolt12_invoice`] to pay the invoice or + /// [`OffersMessageFlow::send_payment_for_bolt12_invoice`] to pay the invoice or /// [`ChannelManager::abandon_payment`] to abandon the associated payment. /// /// Default value: `false` /// /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice /// [`Event::InvoiceReceived`]: crate::events::Event::InvoiceReceived - /// [`ChannelManager::send_payment_for_bolt12_invoice`]: crate::ln::channelmanager::ChannelManager::send_payment_for_bolt12_invoice + /// [`OffersMessageFlow::send_payment_for_bolt12_invoice`]: crate::offers::flow::OffersMessageFlow::send_payment_for_bolt12_invoice /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment pub manually_handle_bolt12_invoices: bool, }