]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Update handle_message to Accept offers_data as an Input Field
authorshaavan <shaavan.github@gmail.com>
Sat, 15 Jun 2024 13:52:28 +0000 (19:22 +0530)
committershaavan <shaavan.github@gmail.com>
Tue, 25 Jun 2024 07:47:46 +0000 (13:17 +0530)
1. Handling Offers Data:
   - Updated `handle_message` to accept `offers_data` as an input field.
   - If `offers_data` is present, it will be utilized by the handler to
     abandon outbound payments that have failed for any reason.

2. Consistency in Custom Message Handling:
   - Updated `handle_custom_message` to accept optional `custom_data`
     for consistency.
   - Note: `custom_data` will remain unused in this PR.

fuzz/src/onion_message.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/peer_handler.rs
lightning/src/onion_message/functional_tests.rs
lightning/src/onion_message/messenger.rs
lightning/src/onion_message/offers.rs

index 07d271bced1e0f07144235bcf478385e56625915..b1c6312a93991082ce1ce432697d438113743b8c 100644 (file)
@@ -6,6 +6,7 @@ use bitcoin::secp256k1::ecdsa::RecoverableSignature;
 use bitcoin::secp256k1::schnorr;
 use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
 
+use lightning::blinded_path::message::{MessageContext, OffersContext};
 use lightning::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
 use lightning::ln::features::InitFeatures;
 use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
@@ -104,7 +105,7 @@ struct TestOffersMessageHandler {}
 
 impl OffersMessageHandler for TestOffersMessageHandler {
        fn handle_message(
-               &self, _message: OffersMessage, _responder: Option<Responder>,
+               &self, _message: OffersMessage, _responder: Option<Responder>, _context: OffersContext,
        ) -> ResponseInstruction<OffersMessage> {
                ResponseInstruction::NoResponse
        }
@@ -147,7 +148,7 @@ struct TestCustomMessageHandler {}
 impl CustomOnionMessageHandler for TestCustomMessageHandler {
        type CustomMessage = TestCustomMessage;
        fn handle_custom_message(
-               &self, message: Self::CustomMessage, responder: Option<Responder>,
+               &self, message: Self::CustomMessage, responder: Option<Responder>, _context: Vec<u8>,
        ) -> ResponseInstruction<Self::CustomMessage> {
                match responder {
                        Some(responder) => responder.respond(message),
@@ -337,9 +338,14 @@ mod tests {
                super::do_test(&<Vec<u8>>::from_hex(one_hop_om).unwrap(), &logger);
                {
                        let log_entries = logger.lines.lock().unwrap();
-                       assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(),
-                                               "Received an onion message with path_id None and a reply_path: Custom(TestCustomMessage)"
-                                               .to_string())), Some(&1));
+                       assert_eq!(
+                               log_entries.get(&(
+                                       "lightning::onion_message::messenger".to_string(),
+                                       "Received an onion message with a reply_path: Custom(TestCustomMessage)"
+                                               .to_string()
+                               )),
+                               Some(&1)
+                       );
                        assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(),
                                                "Constructing onion message when responding with Custom Message to an onion message: TestCustomMessage".to_string())), Some(&1));
                        assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(),
index 6ba7396ebfe04262904640c6b041d6969e95195f..2fb741deeac8dbd36b9d9a37e227523b51f47878 100644 (file)
@@ -31,6 +31,7 @@ use bitcoin::secp256k1::{SecretKey,PublicKey};
 use bitcoin::secp256k1::Secp256k1;
 use bitcoin::{secp256k1, Sequence};
 
+use crate::blinded_path::message::OffersContext;
 use crate::blinded_path::{BlindedPath, NodeIdLookUp};
 use crate::blinded_path::message::ForwardNode;
 use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
@@ -10251,10 +10252,17 @@ where
        R::Target: Router,
        L::Target: Logger,
 {
-       fn handle_message(&self, message: OffersMessage, responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
+       fn handle_message(&self, message: OffersMessage, responder: Option<Responder>, context: OffersContext) -> ResponseInstruction<OffersMessage> {
                let secp_ctx = &self.secp_ctx;
                let expanded_key = &self.inbound_payment_key;
 
+               let abandon_if_payment = |context| {
+                       match context {
+                               OffersContext::OutboundPayment { payment_id } => self.abandon_payment(payment_id),
+                               _ => {},
+                       }
+               };
+
                match message {
                        OffersMessage::InvoiceRequest(invoice_request) => {
                                let responder = match responder {
@@ -10367,14 +10375,25 @@ where
                                };
 
                                match result {
-                                       Ok(()) => ResponseInstruction::NoResponse,
-                                       Err(e) => match responder {
-                                               Some(responder) => responder.respond(OffersMessage::InvoiceError(e)),
-                                               None => {
-                                                       log_trace!(self.logger, "No reply path for sending invoice error: {:?}", e);
-                                                       ResponseInstruction::NoResponse
-                                               },
-                                       },
+                                       Err(err) => {
+                                               match responder {
+                                                       Some(responder) => {
+                                                               abandon_if_payment(context);
+                                                               responder.respond(OffersMessage::InvoiceError(err))
+                                                       }
+                                                       None => {
+                                                               abandon_if_payment(context);
+                                                               log_trace!(
+                                                                       self.logger,
+                                                                       "A error response was generated, but there is no reply_path specified \
+                                                                       for sending the response. Error: {}",
+                                                                       err
+                                                               );
+                                                               return ResponseInstruction::NoResponse;
+                                                       }
+                                               }
+                                       }
+                                       Ok(_) => return ResponseInstruction::NoResponse,
                                }
                        },
                        #[cfg(async_payments)]
@@ -10389,6 +10408,7 @@ where
                                }
                        },
                        OffersMessage::InvoiceError(invoice_error) => {
+                               abandon_if_payment(context);
                                log_trace!(self.logger, "Received invoice_error: {}", invoice_error);
                                ResponseInstruction::NoResponse
                        },
index 9a026d709cffa95a2dc66120ee80f0a6c6a89b29..ac33929110902b97a5e0ff5f6d00a90b2a9be344 100644 (file)
@@ -18,6 +18,7 @@
 use bitcoin::blockdata::constants::ChainHash;
 use bitcoin::secp256k1::{self, Secp256k1, SecretKey, PublicKey};
 
+use crate::blinded_path::message::OffersContext;
 use crate::sign::{NodeSigner, Recipient};
 use crate::events::{MessageSendEvent, MessageSendEventsProvider};
 use crate::ln::types::ChannelId;
@@ -145,7 +146,7 @@ impl OnionMessageHandler for IgnoringMessageHandler {
 }
 
 impl OffersMessageHandler for IgnoringMessageHandler {
-       fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
+       fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>, _context: OffersContext) -> ResponseInstruction<OffersMessage> {
                ResponseInstruction::NoResponse
        }
 }
@@ -159,7 +160,7 @@ impl AsyncPaymentsMessageHandler for IgnoringMessageHandler {
 }
 impl CustomOnionMessageHandler for IgnoringMessageHandler {
        type CustomMessage = Infallible;
-       fn handle_custom_message(&self, _message: Self::CustomMessage, _responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
+       fn handle_custom_message(&self, _message: Self::CustomMessage, _responder: Option<Responder>, _context: Vec<u8>) -> ResponseInstruction<Self::CustomMessage> {
                // Since we always return `None` in the read the handle method should never be called.
                unreachable!();
        }
index b169f21f52ede1042bbbd3f7bd0aaaf273bb6750..390a22e91c0e4b02cee50b5a9c8fa11d11196baa 100644 (file)
@@ -10,7 +10,7 @@
 //! Onion message testing and test utilities live here.
 
 use crate::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
-use crate::blinded_path::message::ForwardNode;
+use crate::blinded_path::message::{ForwardNode, OffersContext};
 use crate::events::{Event, EventsProvider};
 use crate::ln::features::{ChannelFeatures, InitFeatures};
 use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
@@ -76,7 +76,7 @@ impl Drop for MessengerNode {
 struct TestOffersMessageHandler {}
 
 impl OffersMessageHandler for TestOffersMessageHandler {
-       fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>) -> ResponseInstruction<OffersMessage> {
+       fn handle_message(&self, _message: OffersMessage, _responder: Option<Responder>, _context: OffersContext) -> ResponseInstruction<OffersMessage> {
                ResponseInstruction::NoResponse
        }
 }
@@ -174,7 +174,7 @@ impl Drop for TestCustomMessageHandler {
 
 impl CustomOnionMessageHandler for TestCustomMessageHandler {
        type CustomMessage = TestCustomMessage;
-       fn handle_custom_message(&self, msg: Self::CustomMessage, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
+       fn handle_custom_message(&self, msg: Self::CustomMessage, responder: Option<Responder>, _context: Vec<u8>) -> ResponseInstruction<Self::CustomMessage> {
                let expectation = self.get_next_expectation();
                assert_eq!(msg, expectation.expect);
 
@@ -437,7 +437,7 @@ fn async_response_over_one_blinded_hop() {
 
        // 5. Expect Alice to receive the message and create a response instruction for it.
        alice.custom_message_handler.expect_message(message.clone());
-       let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, responder);
+       let response_instruction = nodes[0].custom_message_handler.handle_custom_message(message, responder, Vec::new());
 
        // 6. Simulate Alice asynchronously responding back to Bob with a response.
        assert_eq!(
@@ -470,7 +470,7 @@ fn async_response_with_reply_path_succeeds() {
        // Alice asynchronously responds to Bob, expecting a response back from him.
        let responder = Responder::new(reply_path);
        alice.custom_message_handler.expect_message_and_response(message.clone());
-       let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder));
+       let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder), Vec::new());
 
        assert_eq!(
                alice.messenger.handle_onion_message_response(response_instruction),
@@ -508,7 +508,7 @@ fn async_response_with_reply_path_fails() {
        disconnect_peers(alice, bob);
        let responder = Responder::new(reply_path);
        alice.custom_message_handler.expect_message_and_response(message.clone());
-       let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder));
+       let response_instruction = alice.custom_message_handler.handle_custom_message(message, Some(responder), Vec::new());
 
        assert_eq!(
                alice.messenger.handle_onion_message_response(response_instruction),
index 3bd5c08c9e22272ca19472a5e946976c259ade66..2158ef3ff03b9647fb4a892d9857f5e542807273 100644 (file)
@@ -16,7 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
 
 use crate::blinded_path::{BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp};
-use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, ReceiveTlvs, MessageContext};
+use crate::blinded_path::message::{advance_path_by_one, ForwardNode, ForwardTlvs, MessageContext, OffersContext, ReceiveTlvs};
 use crate::blinded_path::utils;
 use crate::events::{Event, EventHandler, EventsProvider};
 use crate::sign::{EntropySource, NodeSigner, Recipient};
@@ -768,7 +768,7 @@ pub trait CustomOnionMessageHandler {
        /// Called with the custom message that was received, returning a response to send, if any.
        ///
        /// The returned [`Self::CustomMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
-       fn handle_custom_message(&self, message: Self::CustomMessage, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage>;
+       fn handle_custom_message(&self, message: Self::CustomMessage, responder: Option<Responder>, context: Vec<u8>) -> ResponseInstruction<Self::CustomMessage>;
 
        /// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the
        /// message type is unknown.
@@ -1446,7 +1446,7 @@ where
        fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage) {
                let logger = WithContext::from(&self.logger, Some(*peer_node_id), None, None);
                match self.peel_onion_message(msg) {
-                       Ok(PeeledOnion::Receive(message, _recipient_data, reply_path)) => {
+                       Ok(PeeledOnion::Receive(message, context, reply_path)) => {
                                log_trace!(
                                        logger,
                                        "Received an onion message with {} reply_path: {:?}",
@@ -1455,7 +1455,15 @@ where
                                let responder = reply_path.map(Responder::new);
                                match message {
                                        ParsedOnionMessageContents::Offers(msg) => {
-                                               let response_instructions = self.offers_handler.handle_message(msg, responder);
+                                               let context = match context {
+                                                       None => OffersContext::Unknown {},
+                                                       Some(MessageContext::Offers(context)) => context,
+                                                       Some(MessageContext::Custom(_)) => {
+                                                               debug_assert!(false, "Shouldn't have triggered this case.");
+                                                               return
+                                                       }
+                                               };
+                                               let response_instructions = self.offers_handler.handle_message(msg, responder, context);
                                                let _ = self.handle_onion_message_response(response_instructions);
                                        },
                                        #[cfg(async_payments)]
@@ -1470,7 +1478,15 @@ where
                                                self.async_payments_handler.release_held_htlc(msg);
                                        },
                                        ParsedOnionMessageContents::Custom(msg) => {
-                                               let response_instructions = self.custom_handler.handle_custom_message(msg, responder);
+                                               let context = match context {
+                                                       None => vec![],
+                                                       Some(MessageContext::Custom(data)) => data,
+                                                       Some(MessageContext::Offers(_)) => {
+                                                               debug_assert!(false, "Shouldn't have triggered this case.");
+                                                               return
+                                                       }
+                                               };
+                                               let response_instructions = self.custom_handler.handle_custom_message(msg, responder, context);
                                                let _ = self.handle_onion_message_response(response_instructions);
                                        },
                                }
index 397f4b8a72b7a827b8bb0543f78a076cd9eb2210..0666c5687a069eecd9db41e9732086abbcbc24be 100644 (file)
@@ -10,6 +10,7 @@
 //! Message handling for BOLT 12 Offers.
 
 use core::fmt;
+use crate::blinded_path::message::OffersContext;
 use crate::io::{self, Read};
 use crate::ln::msgs::DecodeError;
 use crate::offers::invoice_error::InvoiceError;
@@ -44,7 +45,7 @@ pub trait OffersMessageHandler {
        /// The returned [`OffersMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
        ///
        /// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
-       fn handle_message(&self, message: OffersMessage, responder: Option<Responder>) -> ResponseInstruction<OffersMessage>;
+       fn handle_message(&self, message: OffersMessage, responder: Option<Responder>, context: OffersContext) -> ResponseInstruction<OffersMessage>;
 
        /// Releases any [`OffersMessage`]s that need to be sent.
        ///