Add OnionMessagePath wrapper struct
authorJeffrey Czyz <jkczyz@gmail.com>
Thu, 25 May 2023 20:02:10 +0000 (15:02 -0500)
committerJeffrey Czyz <jkczyz@gmail.com>
Tue, 13 Jun 2023 18:07:47 +0000 (13:07 -0500)
To avoid confusion in the upcoming MessageRouter trait, introduce an
OnionMessagePath struct that wraps the intermediate nodes and the
destination. Use this in OnionMessenger::send_onion_message.

lightning/src/onion_message/functional_tests.rs
lightning/src/onion_message/messenger.rs
lightning/src/onion_message/mod.rs

index cc83f2d2c9e2b17e47c6c2758ade3310154fb710..90243f357c36d9d3d1c9f54a88cdef375483e8e7 100644 (file)
@@ -13,7 +13,7 @@ use crate::blinded_path::BlindedPath;
 use crate::sign::{NodeSigner, Recipient};
 use crate::ln::features::InitFeatures;
 use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
-use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessenger, SendError};
+use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError};
 use crate::util::ser::{Writeable, Writer};
 use crate::util::test_utils;
 
@@ -146,7 +146,11 @@ fn one_hop() {
        let nodes = create_nodes(2);
        let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
 
-       nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), test_msg, None).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::Node(nodes[1].get_node_pk()),
+       };
+       nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
        pass_along_path(&nodes);
 }
 
@@ -155,7 +159,11 @@ fn two_unblinded_hops() {
        let nodes = create_nodes(3);
        let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
 
-       nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk()], Destination::Node(nodes[2].get_node_pk()), test_msg, None).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![nodes[1].get_node_pk()],
+               destination: Destination::Node(nodes[2].get_node_pk()),
+       };
+       nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
        pass_along_path(&nodes);
 }
 
@@ -166,8 +174,12 @@ fn two_unblinded_two_blinded() {
 
        let secp_ctx = Secp256k1::new();
        let blinded_path = BlindedPath::new_for_message(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![nodes[1].get_node_pk(), nodes[2].get_node_pk()],
+               destination: Destination::BlindedPath(blinded_path),
+       };
 
-       nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedPath(blinded_path), test_msg, None).unwrap();
+       nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
        pass_along_path(&nodes);
 }
 
@@ -178,8 +190,12 @@ fn three_blinded_hops() {
 
        let secp_ctx = Secp256k1::new();
        let blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::BlindedPath(blinded_path),
+       };
 
-       nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), test_msg, None).unwrap();
+       nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
        pass_along_path(&nodes);
 }
 
@@ -190,8 +206,12 @@ fn too_big_packet_error() {
        let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
 
        let hop_node_id = nodes[1].get_node_pk();
-       let hops = [hop_node_id; 400];
-       let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id), test_msg, None).unwrap_err();
+       let hops = vec![hop_node_id; 400];
+       let path = OnionMessagePath {
+               intermediate_nodes: hops,
+               destination: Destination::Node(hop_node_id),
+       };
+       let err = nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap_err();
        assert_eq!(err, SendError::TooBigPacket);
 }
 
@@ -204,13 +224,21 @@ fn we_are_intro_node() {
 
        let secp_ctx = Secp256k1::new();
        let blinded_path = BlindedPath::new_for_message(&[nodes[0].get_node_pk(), nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::BlindedPath(blinded_path),
+       };
 
-       nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
+       nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
        pass_along_path(&nodes);
 
        // Try with a two-hop blinded path where we are the introduction node.
        let blinded_path = BlindedPath::new_for_message(&[nodes[0].get_node_pk(), nodes[1].get_node_pk()], &*nodes[1].keys_manager, &secp_ctx).unwrap();
-       nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg), None).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::BlindedPath(blinded_path),
+       };
+       nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), None).unwrap();
        nodes.remove(2);
        pass_along_path(&nodes);
 }
@@ -225,14 +253,22 @@ fn invalid_blinded_path_error() {
        let secp_ctx = Secp256k1::new();
        let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
        blinded_path.blinded_hops.clear();
-       let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg.clone()), None).unwrap_err();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::BlindedPath(blinded_path),
+       };
+       let err = nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg.clone()), None).unwrap_err();
        assert_eq!(err, SendError::TooFewBlindedHops);
 
        // 1 hop
        let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
        blinded_path.blinded_hops.remove(0);
        assert_eq!(blinded_path.blinded_hops.len(), 1);
-       let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg), None).unwrap_err();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::BlindedPath(blinded_path),
+       };
+       let err = nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), None).unwrap_err();
        assert_eq!(err, SendError::TooFewBlindedHops);
 }
 
@@ -243,8 +279,12 @@ fn reply_path() {
        let secp_ctx = Secp256k1::new();
 
        // Destination::Node
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![nodes[1].get_node_pk(), nodes[2].get_node_pk()],
+               destination: Destination::Node(nodes[3].get_node_pk()),
+       };
        let reply_path = BlindedPath::new_for_message(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
-       nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::Node(nodes[3].get_node_pk()), OnionMessageContents::Custom(test_msg.clone()), Some(reply_path)).unwrap();
+       nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg.clone()), Some(reply_path)).unwrap();
        pass_along_path(&nodes);
        // Make sure the last node successfully decoded the reply path.
        nodes[3].logger.assert_log_contains(
@@ -253,9 +293,13 @@ fn reply_path() {
 
        // Destination::BlindedPath
        let blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::BlindedPath(blinded_path),
+       };
        let reply_path = BlindedPath::new_for_message(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
 
-       nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg), Some(reply_path)).unwrap();
+       nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), Some(reply_path)).unwrap();
        pass_along_path(&nodes);
        nodes[3].logger.assert_log_contains(
                "lightning::onion_message::messenger",
@@ -279,7 +323,11 @@ fn invalid_custom_message_type() {
        }
 
        let test_msg = OnionMessageContents::Custom(InvalidCustomMessage {});
-       let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), test_msg, None).unwrap_err();
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::Node(nodes[1].get_node_pk()),
+       };
+       let err = nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap_err();
        assert_eq!(err, SendError::InvalidMessage);
 }
 
@@ -287,10 +335,14 @@ fn invalid_custom_message_type() {
 fn peer_buffer_full() {
        let nodes = create_nodes(2);
        let test_msg = TestCustomMessage {};
+       let path = OnionMessagePath {
+               intermediate_nodes: vec![],
+               destination: Destination::Node(nodes[1].get_node_pk()),
+       };
        for _ in 0..188 { // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger
-               nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
+               nodes[0].messenger.send_onion_message(path.clone(), OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
        }
-       let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), OnionMessageContents::Custom(test_msg), None).unwrap_err();
+       let err = nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), None).unwrap_err();
        assert_eq!(err, SendError::BufferFull);
 }
 
@@ -302,11 +354,15 @@ fn many_hops() {
        let nodes = create_nodes(num_nodes as u8);
        let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
 
-       let mut intermediates = vec![];
+       let mut intermediate_nodes = vec![];
        for i in 1..(num_nodes-1) {
-               intermediates.push(nodes[i].get_node_pk());
+               intermediate_nodes.push(nodes[i].get_node_pk());
        }
 
-       nodes[0].messenger.send_onion_message(&intermediates, Destination::Node(nodes[num_nodes-1].get_node_pk()), test_msg, None).unwrap();
+       let path = OnionMessagePath {
+               intermediate_nodes,
+               destination: Destination::Node(nodes[num_nodes-1].get_node_pk()),
+       };
+       nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
        pass_along_path(&nodes);
 }
index 23c9db0c45b073f3ff4c6cd7aab310f87a8db8fa..09a2307591673ce4c01dc1dfd990249c24befc92 100644 (file)
@@ -46,7 +46,7 @@ use crate::prelude::*;
 /// # use lightning::blinded_path::BlindedPath;
 /// # use lightning::sign::KeysManager;
 /// # use lightning::ln::peer_handler::IgnoringMessageHandler;
-/// # use lightning::onion_message::{CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger};
+/// # use lightning::onion_message::{CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessagePath, OnionMessenger};
 /// # use lightning::util::logger::{Logger, Record};
 /// # use lightning::util::ser::{Writeable, Writer};
 /// # use lightning::io;
@@ -84,11 +84,14 @@ use crate::prelude::*;
 ///    }
 /// }
 /// // Send a custom onion message to a node id.
-/// let intermediate_hops = [hop_node_id1, hop_node_id2];
+/// let path = OnionMessagePath {
+///    intermediate_nodes: vec![hop_node_id1, hop_node_id2],
+///    destination: Destination::Node(destination_node_id),
+/// };
 /// let reply_path = None;
 /// # let your_custom_message = YourCustomMessage {};
 /// let message = OnionMessageContents::Custom(your_custom_message);
-/// onion_messenger.send_onion_message(&intermediate_hops, Destination::Node(destination_node_id), message, reply_path);
+/// onion_messenger.send_onion_message(path, message, reply_path);
 ///
 /// // Create a blinded path to yourself, for someone to send an onion message to.
 /// # let your_node_id = hop_node_id1;
@@ -96,11 +99,14 @@ use crate::prelude::*;
 /// let blinded_path = BlindedPath::new_for_message(&hops, &keys_manager, &secp_ctx).unwrap();
 ///
 /// // Send a custom onion message to a blinded path.
-/// # let intermediate_hops = [hop_node_id1, hop_node_id2];
+/// let path = OnionMessagePath {
+///    intermediate_nodes: vec![hop_node_id1, hop_node_id2],
+///    destination: Destination::BlindedPath(blinded_path),
+/// };
 /// let reply_path = None;
 /// # let your_custom_message = YourCustomMessage {};
 /// let message = OnionMessageContents::Custom(your_custom_message);
-/// onion_messenger.send_onion_message(&intermediate_hops, Destination::BlindedPath(blinded_path), message, reply_path);
+/// onion_messenger.send_onion_message(path, message, reply_path);
 /// ```
 ///
 /// [offers]: <https://github.com/lightning/bolts/pull/798>
@@ -122,7 +128,18 @@ where
        custom_handler: CMH,
 }
 
+/// A path for sending an [`msgs::OnionMessage`].
+#[derive(Clone)]
+pub struct OnionMessagePath {
+       /// Nodes on the path between the sender and the destination.
+       pub intermediate_nodes: Vec<PublicKey>,
+
+       /// The recipient of the message.
+       pub destination: Destination,
+}
+
 /// The destination of an onion message.
+#[derive(Clone)]
 pub enum Destination {
        /// We're sending this onion message to a node.
        Node(PublicKey),
@@ -216,9 +233,14 @@ where
                }
        }
 
-       /// Send an onion message with contents `message` to `destination`, routing it through `intermediate_nodes`.
+       /// Send an onion message with contents `message` to the destination of `path`.
+       ///
        /// See [`OnionMessenger`] for example usage.
-       pub fn send_onion_message<T: CustomOnionMessageContents>(&self, intermediate_nodes: &[PublicKey], mut destination: Destination, message: OnionMessageContents<T>, reply_path: Option<BlindedPath>) -> Result<(), SendError> {
+       pub fn send_onion_message<T: CustomOnionMessageContents>(
+               &self, path: OnionMessagePath, message: OnionMessageContents<T>,
+               reply_path: Option<BlindedPath>
+       ) -> Result<(), SendError> {
+               let OnionMessagePath { intermediate_nodes, mut destination } = path;
                if let Destination::BlindedPath(BlindedPath { ref blinded_hops, .. }) = destination {
                        if blinded_hops.len() < 2 {
                                return Err(SendError::TooFewBlindedHops);
@@ -252,7 +274,7 @@ where
                        }
                };
                let (packet_payloads, packet_keys) = packet_payloads_and_keys(
-                       &self.secp_ctx, intermediate_nodes, destination, message, reply_path, &blinding_secret)
+                       &self.secp_ctx, &intermediate_nodes, destination, message, reply_path, &blinding_secret)
                        .map_err(|e| SendError::Secp256k1(e))?;
 
                let prng_seed = self.entropy_source.get_secure_random_bytes();
index e0b3f5001954a052f2d14c989ef18dac96ec8282..35bf6a99e6d572dd4800f69524d63356f500ab1d 100644 (file)
@@ -27,6 +27,6 @@ mod packet;
 mod functional_tests;
 
 // Re-export structs so they can be imported with just the `onion_message::` module prefix.
-pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
 pub use self::offers::{OffersMessage, OffersMessageHandler};
 pub(crate) use self::packet::{ControlTlvs, Packet};