public make_onion_message static method on OnionMessenger
authorEvan Feenstra <evanfeenstra@gmail.com>
Fri, 15 Sep 2023 22:47:23 +0000 (15:47 -0700)
committerEvan Feenstra <evanfeenstra@gmail.com>
Wed, 20 Sep 2023 20:42:35 +0000 (13:42 -0700)
lightning/src/ln/msgs.rs
lightning/src/onion_message/messenger.rs
lightning/src/onion_message/mod.rs
lightning/src/onion_message/packet.rs

index c617d97fe52705c8673c6f4a68f331bb8ed644a6..e4cc1f1955fe65ccacc62d9efc97c85ab94968af 100644 (file)
@@ -631,7 +631,8 @@ pub struct UpdateAddHTLC {
 pub struct OnionMessage {
        /// Used in decrypting the onion packet's payload.
        pub blinding_point: PublicKey,
-       pub(crate) onion_routing_packet: onion_message::Packet,
+       /// The full onion packet including hop data, pubkey, and hmac
+       pub onion_routing_packet: onion_message::Packet,
 }
 
 /// An [`update_fulfill_htlc`] message to be sent to or received from a peer.
index 1a6e2614b72910976e8aef5ff434dc10eff495bf..2a9c830d38bec8e7a56e6e4cb98c6389f6cce60b 100644 (file)
@@ -283,6 +283,36 @@ where
                &self, path: OnionMessagePath, message: OnionMessageContents<T>,
                reply_path: Option<BlindedPath>
        ) -> Result<(), SendError> {
+               let (introduction_node_id, onion_msg) = Self::create_onion_message(
+                       &self.entropy_source, 
+                       &self.node_signer, 
+                       &self.secp_ctx, 
+                       path, 
+                       message, 
+                       reply_path
+               )?;
+
+               let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
+               if outbound_buffer_full(&introduction_node_id, &pending_per_peer_msgs) { return Err(SendError::BufferFull) }
+               match pending_per_peer_msgs.entry(introduction_node_id) {
+                       hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
+                       hash_map::Entry::Occupied(mut e) => {
+                               e.get_mut().push_back(onion_msg);
+                               Ok(())
+                       }
+               }
+       }
+
+       /// Create an onion message with contents `message` to the destination of `path`.
+       /// Returns (introduction_node_id, onion_msg)
+       pub fn create_onion_message<T: CustomOnionMessageContents>(
+               entropy_source: &ES, 
+               node_signer: &NS,
+               secp_ctx: &Secp256k1<secp256k1::All>,
+               path: OnionMessagePath, 
+               message: OnionMessageContents<T>,
+               reply_path: Option<BlindedPath>, 
+       ) -> Result<(PublicKey, msgs::OnionMessage), SendError> {
                let OnionMessagePath { intermediate_nodes, mut destination } = path;
                if let Destination::BlindedPath(BlindedPath { ref blinded_hops, .. }) = destination {
                        if blinded_hops.len() < 2 {
@@ -296,43 +326,38 @@ where
                // advance the blinded path by 1 hop so the second hop is the new introduction node.
                if intermediate_nodes.len() == 0 {
                        if let Destination::BlindedPath(ref mut blinded_path) = destination {
-                               let our_node_id = self.node_signer.get_node_id(Recipient::Node)
+                               let our_node_id = node_signer.get_node_id(Recipient::Node)
                                        .map_err(|()| SendError::GetNodeIdFailed)?;
                                if blinded_path.introduction_node_id == our_node_id {
-                                       advance_path_by_one(blinded_path, &self.node_signer, &self.secp_ctx)
+                                       advance_path_by_one(blinded_path, node_signer, &secp_ctx)
                                                .map_err(|()| SendError::BlindedPathAdvanceFailed)?;
                                }
                        }
                }
 
-               let blinding_secret_bytes = self.entropy_source.get_secure_random_bytes();
+               let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
                let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
                let (introduction_node_id, blinding_point) = if intermediate_nodes.len() != 0 {
-                       (intermediate_nodes[0], PublicKey::from_secret_key(&self.secp_ctx, &blinding_secret))
+                       (intermediate_nodes[0], PublicKey::from_secret_key(&secp_ctx, &blinding_secret))
                } else {
                        match destination {
-                               Destination::Node(pk) => (pk, PublicKey::from_secret_key(&self.secp_ctx, &blinding_secret)),
+                               Destination::Node(pk) => (pk, PublicKey::from_secret_key(&secp_ctx, &blinding_secret)),
                                Destination::BlindedPath(BlindedPath { introduction_node_id, blinding_point, .. }) =>
                                        (introduction_node_id, blinding_point),
                        }
                };
                let (packet_payloads, packet_keys) = packet_payloads_and_keys(
-                       &self.secp_ctx, &intermediate_nodes, destination, message, reply_path, &blinding_secret)
+                       &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();
+               let prng_seed = entropy_source.get_secure_random_bytes();
                let onion_routing_packet = construct_onion_message_packet(
                        packet_payloads, packet_keys, prng_seed).map_err(|()| SendError::TooBigPacket)?;
 
-               let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
-               if outbound_buffer_full(&introduction_node_id, &pending_per_peer_msgs) { return Err(SendError::BufferFull) }
-               match pending_per_peer_msgs.entry(introduction_node_id) {
-                       hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
-                       hash_map::Entry::Occupied(mut e) => {
-                               e.get_mut().push_back(msgs::OnionMessage { blinding_point, onion_routing_packet });
-                               Ok(())
-                       }
-               }
+               Ok((introduction_node_id, msgs::OnionMessage {
+                       blinding_point,
+                       onion_routing_packet
+               }))
        }
 
        fn respond_with_onion_message<T: CustomOnionMessageContents>(
index 806f832ff73f557de046d08ebe67e5d87e0a028f..ae8bae1fb14fe9e7781c7343b4812892758f85b4 100644 (file)
@@ -29,4 +29,5 @@ mod functional_tests;
 // Re-export structs so they can be imported with just the `onion_message::` module prefix.
 pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
 pub use self::offers::{OffersMessage, OffersMessageHandler};
-pub(crate) use self::packet::{ControlTlvs, Packet};
+pub use self::packet::Packet;
+pub(crate) use self::packet::ControlTlvs;
index a76371b39eb9fa12769e2144fb6cdd02067b70f7..d19bd30edd212be4b19286d5ef5f0bf0f1870a8f 100644 (file)
@@ -32,16 +32,22 @@ use crate::prelude::*;
 pub(super) const SMALL_PACKET_HOP_DATA_LEN: usize = 1300;
 pub(super) const BIG_PACKET_HOP_DATA_LEN: usize = 32768;
 
+/// Packet of hop data for next peer
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub(crate) struct Packet {
-       pub(super) version: u8,
-       pub(super) public_key: PublicKey,
+pub struct Packet {
+       /// Bolt 04 version number
+       pub version: u8,
+       /// A random sepc256k1 point, used to build the ECDH shared secret to decrypt hop_data
+       pub public_key: PublicKey,
+       /// Encrypted payload for the next hop
+       //
        // Unlike the onion packets used for payments, onion message packets can have payloads greater
        // than 1300 bytes.
        // TODO: if 1300 ends up being the most common size, optimize this to be:
        // enum { ThirteenHundred([u8; 1300]), VarLen(Vec<u8>) }
-       pub(super) hop_data: Vec<u8>,
-       pub(super) hmac: [u8; 32],
+       pub hop_data: Vec<u8>,
+       /// HMAC to verify the integrity of hop_data
+       pub hmac: [u8; 32],
 }
 
 impl onion_utils::Packet for Packet {