From 840efd533468cf7cacd8b4bab27ce2db86b3eb93 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Tue, 19 Sep 2023 12:35:13 -0500 Subject: [PATCH] Generalize CustomOnionMessageContents trait Rename CustomOnionMessageContents to OnionMessageContents and use it as a trait bound on messages passed to OnionMessenger methods. This allows using the trait in an upcoming commit as a bound on the contents of PendingOnionMessage. Also, make ParsedOnionMessageContent implement OnionMessageContents so that Payload can be bounded by OnionMessageContents directly, but used when either reading a ParsedOnionMessageContent or writing a specific type of OnionMessageContents (e.g., OffersMessage). --- fuzz/src/onion_message.rs | 8 +- lightning/src/ln/peer_handler.rs | 4 +- .../src/onion_message/functional_tests.rs | 36 +++---- lightning/src/onion_message/messenger.rs | 100 ++++++++++-------- lightning/src/onion_message/mod.rs | 4 +- lightning/src/onion_message/offers.rs | 20 ++-- lightning/src/onion_message/packet.rs | 26 ++--- 7 files changed, 104 insertions(+), 94 deletions(-) diff --git a/fuzz/src/onion_message.rs b/fuzz/src/onion_message.rs index 67938aa7..57d4f697 100644 --- a/fuzz/src/onion_message.rs +++ b/fuzz/src/onion_message.rs @@ -14,7 +14,7 @@ use lightning::offers::invoice_request::UnsignedInvoiceRequest; use lightning::util::test_channel_signer::TestChannelSigner; use lightning::util::logger::Logger; use lightning::util::ser::{Readable, Writeable, Writer}; -use lightning::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessagePath, OnionMessenger}; +use lightning::onion_message::{CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger}; use crate::utils::test_logger; @@ -84,7 +84,7 @@ struct TestCustomMessage {} const CUSTOM_MESSAGE_TYPE: u64 = 4242; const CUSTOM_MESSAGE_CONTENTS: [u8; 32] = [42; 32]; -impl CustomOnionMessageContents for TestCustomMessage { +impl OnionMessageContents for TestCustomMessage { fn tlv_type(&self) -> u64 { CUSTOM_MESSAGE_TYPE } @@ -216,9 +216,9 @@ mod tests { assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(), "Received an onion message with path_id None and a reply_path".to_string())), Some(&1)); assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(), - "Sending onion message when responding to onion message with path_id None".to_string())), Some(&1)); + "Sending onion message when responding to Custom onion message with path_id None".to_string())), Some(&1)); assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(), - "Failed sending onion message when responding to onion message with path_id None: TooFewBlindedHops".to_string())), Some(&1)); + "Failed sending onion message when responding to Custom onion message with path_id None: TooFewBlindedHops".to_string())), Some(&1)); } let two_unblinded_hops_om = "020000000000000000000000000000000000000000000000000000000000000e01055600020000000000000000000000000000000000000000000000000000000000000e0135043304210202020202020202020202020202020202020202020202020202020202020202026d000000000000000000000000000000eb0000000000000000000000000000000000000000000000000000000000000036041096000000000000000000000000000000fd1092202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000"; diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index a5a6939e..84fb9748 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -29,7 +29,7 @@ use crate::util::ser::{VecWriter, Writeable, Writer}; use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep}; use crate::ln::wire; use crate::ln::wire::{Encode, Type}; -use crate::onion_message::{CustomOnionMessageContents, CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, SimpleArcOnionMessenger, SimpleRefOnionMessenger}; +use crate::onion_message::{CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, OnionMessageContents, SimpleArcOnionMessenger, SimpleRefOnionMessenger}; use crate::routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, NodeAlias}; use crate::util::atomic_counter::AtomicCounter; use crate::util::logger::Logger; @@ -131,7 +131,7 @@ impl CustomOnionMessageHandler for IgnoringMessageHandler { } } -impl CustomOnionMessageContents for Infallible { +impl OnionMessageContents for Infallible { fn tlv_type(&self) -> u64 { unreachable!(); } } diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index 319417e8..0348e4af 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -15,7 +15,7 @@ use crate::ln::msgs::{self, DecodeError, OnionMessageHandler}; use crate::sign::{NodeSigner, Recipient}; use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer}; use crate::util::test_utils; -use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, ParsedOnionMessageContents, OnionMessagePath, OnionMessenger, SendError}; +use super::{CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError}; use bitcoin::network::constants::Network; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; @@ -77,7 +77,7 @@ const CUSTOM_RESPONSE_MESSAGE_TYPE: u64 = 4343; const CUSTOM_REQUEST_MESSAGE_CONTENTS: [u8; 32] = [42; 32]; const CUSTOM_RESPONSE_MESSAGE_CONTENTS: [u8; 32] = [43; 32]; -impl CustomOnionMessageContents for TestCustomMessage { +impl OnionMessageContents for TestCustomMessage { fn tlv_type(&self) -> u64 { match self { TestCustomMessage::Request => CUSTOM_REQUEST_MESSAGE_TYPE, @@ -196,7 +196,7 @@ fn pass_along_path(path: &Vec) { #[test] fn one_hop() { let nodes = create_nodes(2); - let test_msg = ParsedOnionMessageContents::Custom(TestCustomMessage::Response); + let test_msg = TestCustomMessage::Response; let path = OnionMessagePath { intermediate_nodes: vec![], @@ -210,7 +210,7 @@ fn one_hop() { #[test] fn two_unblinded_hops() { let nodes = create_nodes(3); - let test_msg = ParsedOnionMessageContents::Custom(TestCustomMessage::Response); + let test_msg = TestCustomMessage::Response; let path = OnionMessagePath { intermediate_nodes: vec![nodes[1].get_node_pk()], @@ -224,7 +224,7 @@ fn two_unblinded_hops() { #[test] fn two_unblinded_two_blinded() { let nodes = create_nodes(5); - let test_msg = ParsedOnionMessageContents::Custom(TestCustomMessage::Response); + let test_msg = TestCustomMessage::Response; 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(); @@ -241,7 +241,7 @@ fn two_unblinded_two_blinded() { #[test] fn three_blinded_hops() { let nodes = create_nodes(4); - let test_msg = ParsedOnionMessageContents::Custom(TestCustomMessage::Response); + let test_msg = TestCustomMessage::Response; 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(); @@ -259,7 +259,7 @@ fn three_blinded_hops() { fn too_big_packet_error() { // Make sure we error as expected if a packet is too big to send. let nodes = create_nodes(2); - let test_msg = ParsedOnionMessageContents::Custom(TestCustomMessage::Response); + let test_msg = TestCustomMessage::Response; let hop_node_id = nodes[1].get_node_pk(); let hops = vec![hop_node_id; 400]; @@ -285,7 +285,7 @@ fn we_are_intro_node() { destination: Destination::BlindedPath(blinded_path), }; - nodes[0].messenger.send_onion_message(path, ParsedOnionMessageContents::Custom(test_msg.clone()), None).unwrap(); + nodes[0].messenger.send_onion_message(path, test_msg.clone(), None).unwrap(); nodes[2].custom_message_handler.expect_message(TestCustomMessage::Response); pass_along_path(&nodes); @@ -295,7 +295,7 @@ fn we_are_intro_node() { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), }; - nodes[0].messenger.send_onion_message(path, ParsedOnionMessageContents::Custom(test_msg), None).unwrap(); + nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap(); nodes[1].custom_message_handler.expect_message(TestCustomMessage::Response); nodes.remove(2); pass_along_path(&nodes); @@ -315,7 +315,7 @@ fn invalid_blinded_path_error() { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), }; - let err = nodes[0].messenger.send_onion_message(path, ParsedOnionMessageContents::Custom(test_msg.clone()), None).unwrap_err(); + let err = nodes[0].messenger.send_onion_message(path, test_msg.clone(), None).unwrap_err(); assert_eq!(err, SendError::TooFewBlindedHops); // 1 hop @@ -326,7 +326,7 @@ fn invalid_blinded_path_error() { intermediate_nodes: vec![], destination: Destination::BlindedPath(blinded_path), }; - let err = nodes[0].messenger.send_onion_message(path, ParsedOnionMessageContents::Custom(test_msg), None).unwrap_err(); + let err = nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap_err(); assert_eq!(err, SendError::TooFewBlindedHops); } @@ -342,7 +342,7 @@ fn reply_path() { 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(path, ParsedOnionMessageContents::Custom(test_msg.clone()), Some(reply_path)).unwrap(); + nodes[0].messenger.send_onion_message(path, test_msg.clone(), Some(reply_path)).unwrap(); nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request); pass_along_path(&nodes); // Make sure the last node successfully decoded the reply path. @@ -358,7 +358,7 @@ fn reply_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(path, ParsedOnionMessageContents::Custom(test_msg), Some(reply_path)).unwrap(); + nodes[0].messenger.send_onion_message(path, test_msg, Some(reply_path)).unwrap(); nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request); pass_along_path(&nodes); @@ -373,7 +373,7 @@ fn invalid_custom_message_type() { let nodes = create_nodes(2); struct InvalidCustomMessage{} - impl CustomOnionMessageContents for InvalidCustomMessage { + impl OnionMessageContents for InvalidCustomMessage { fn tlv_type(&self) -> u64 { // Onion message contents must have a TLV >= 64. 63 @@ -384,7 +384,7 @@ fn invalid_custom_message_type() { fn write(&self, _w: &mut W) -> Result<(), io::Error> { unreachable!() } } - let test_msg = ParsedOnionMessageContents::Custom(InvalidCustomMessage {}); + let test_msg = InvalidCustomMessage {}; let path = OnionMessagePath { intermediate_nodes: vec![], destination: Destination::Node(nodes[1].get_node_pk()), @@ -402,9 +402,9 @@ fn peer_buffer_full() { 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(path.clone(), ParsedOnionMessageContents::Custom(test_msg.clone()), None).unwrap(); + nodes[0].messenger.send_onion_message(path.clone(), test_msg.clone(), None).unwrap(); } - let err = nodes[0].messenger.send_onion_message(path, ParsedOnionMessageContents::Custom(test_msg), None).unwrap_err(); + let err = nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap_err(); assert_eq!(err, SendError::BufferFull); } @@ -425,7 +425,7 @@ fn many_hops() { intermediate_nodes, destination: Destination::Node(nodes[num_nodes-1].get_node_pk()), }; - nodes[0].messenger.send_onion_message(path, ParsedOnionMessageContents::Custom(test_msg), None).unwrap(); + nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap(); nodes[num_nodes-1].custom_message_handler.expect_message(TestCustomMessage::Response); pass_along_path(&nodes); } diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 074a1790..d6aa5c82 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -23,7 +23,8 @@ use crate::ln::features::{InitFeatures, NodeFeatures}; use crate::ln::msgs::{self, OnionMessage, OnionMessageHandler}; use crate::ln::onion_utils; use crate::ln::peer_handler::IgnoringMessageHandler; -pub use super::packet::{CustomOnionMessageContents, ParsedOnionMessageContents}; +pub use super::packet::OnionMessageContents; +use super::packet::ParsedOnionMessageContents; use super::offers::OffersMessageHandler; use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN}; use crate::util::logger::Logger; @@ -60,7 +61,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, MessageRouter, ParsedOnionMessageContents, OnionMessagePath, OnionMessenger}; +/// # use lightning::onion_message::{OnionMessageContents, Destination, MessageRouter, OnionMessagePath, OnionMessenger}; /// # use lightning::util::logger::{Logger, Record}; /// # use lightning::util::ser::{Writeable, Writer}; /// # use lightning::io; @@ -101,7 +102,7 @@ use crate::prelude::*; /// // Write your custom onion message to `w` /// } /// } -/// impl CustomOnionMessageContents for YourCustomMessage { +/// impl OnionMessageContents for YourCustomMessage { /// fn tlv_type(&self) -> u64 { /// # let your_custom_message_type = 42; /// your_custom_message_type @@ -113,8 +114,7 @@ use crate::prelude::*; /// destination: Destination::Node(destination_node_id), /// }; /// let reply_path = None; -/// # let your_custom_message = YourCustomMessage {}; -/// let message = ParsedOnionMessageContents::Custom(your_custom_message); +/// # let message = YourCustomMessage {}; /// onion_messenger.send_onion_message(path, message, reply_path); /// /// // Create a blinded path to yourself, for someone to send an onion message to. @@ -128,8 +128,7 @@ use crate::prelude::*; /// destination: Destination::BlindedPath(blinded_path), /// }; /// let reply_path = None; -/// # let your_custom_message = YourCustomMessage {}; -/// let message = ParsedOnionMessageContents::Custom(your_custom_message); +/// # let message = YourCustomMessage {}; /// onion_messenger.send_onion_message(path, message, reply_path); /// ``` /// @@ -244,7 +243,7 @@ pub enum SendError { pub trait CustomOnionMessageHandler { /// The message known to the handler. To support multiple message types, you may want to make this /// an enum with a variant for each supported message. - type CustomMessage: CustomOnionMessageContents; + type CustomMessage: OnionMessageContents; /// Called with the custom message that was received, returning a response to send, if any. fn handle_custom_message(&self, msg: Self::CustomMessage) -> Option; @@ -256,21 +255,20 @@ pub trait CustomOnionMessageHandler { /// A processed incoming onion message, containing either a Forward (another onion message) /// or a Receive payload with decrypted contents. -pub enum PeeledOnion { +pub enum PeeledOnion { /// Forwarded onion, with the next node id and a new onion Forward(PublicKey, OnionMessage), /// Received onion message, with decrypted contents, path_id, and reply path - Receive(ParsedOnionMessageContents, Option<[u8; 32]>, Option) + Receive(ParsedOnionMessageContents, Option<[u8; 32]>, Option) } /// Creates an [`OnionMessage`] with the given `contents` for sending to the destination of /// `path`. /// /// Returns both the node id of the peer to send the message to and the message itself. -pub fn create_onion_message( +pub fn create_onion_message( entropy_source: &ES, node_signer: &NS, secp_ctx: &Secp256k1, - path: OnionMessagePath, contents: ParsedOnionMessageContents, - reply_path: Option, + path: OnionMessagePath, contents: T, reply_path: Option, ) -> Result<(PublicKey, OnionMessage), SendError> where ES::Target: EntropySource, @@ -361,7 +359,7 @@ where onion_decode_ss, &msg.onion_routing_packet.hop_data[..], msg.onion_routing_packet.hmac, (control_tlvs_ss, custom_handler.deref(), logger.deref()) ) { - Ok((Payload::Receive::<<::Target as CustomOnionMessageHandler>::CustomMessage> { + Ok((Payload::Receive::::Target as CustomOnionMessageHandler>::CustomMessage>> { message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path, }, None)) => { Ok(PeeledOnion::Receive(message, path_id, reply_path)) @@ -452,9 +450,8 @@ where /// `path`. /// /// See [`OnionMessenger`] for example usage. - pub fn send_onion_message( - &self, path: OnionMessagePath, contents: ParsedOnionMessageContents, - reply_path: Option + pub fn send_onion_message( + &self, path: OnionMessagePath, contents: T, reply_path: Option ) -> Result<(), SendError> { let (first_node_id, onion_msg) = create_onion_message( &self.entropy_source, &self.node_signer, &self.secp_ctx, path, contents, reply_path @@ -471,9 +468,25 @@ where } } - fn find_path_and_enqueue_onion_message( - &self, contents: ParsedOnionMessageContents, destination: Destination, - log_suffix: fmt::Arguments + fn handle_onion_message_response( + &self, response: Option, reply_path: Option, log_suffix: fmt::Arguments + ) { + if let Some(response) = response { + match reply_path { + Some(reply_path) => { + self.find_path_and_enqueue_onion_message( + response, Destination::BlindedPath(reply_path), log_suffix + ); + }, + None => { + log_trace!(self.logger, "Missing reply path {}", log_suffix); + }, + } + } + } + + fn find_path_and_enqueue_onion_message( + &self, contents: T, destination: Destination, log_suffix: fmt::Arguments ) { let sender = match self.node_signer.get_node_id(Recipient::Node) { Ok(node_id) => node_id, @@ -557,33 +570,26 @@ where log_trace!(self.logger, "Received an onion message with path_id {:02x?} and {} reply_path", path_id, if reply_path.is_some() { "a" } else { "no" }); - let response = match message { + + match message { ParsedOnionMessageContents::Offers(msg) => { - self.offers_handler.handle_message(msg) - .map(|msg| ParsedOnionMessageContents::Offers(msg)) + let response = self.offers_handler.handle_message(msg); + self.handle_onion_message_response( + response, reply_path, format_args!( + "when responding to Offers onion message with path_id {:02x?}", + path_id + ) + ); }, ParsedOnionMessageContents::Custom(msg) => { - self.custom_handler.handle_custom_message(msg) - .map(|msg| ParsedOnionMessageContents::Custom(msg)) - }, - }; - if let Some(response) = response { - match reply_path { - Some(reply_path) => { - self.find_path_and_enqueue_onion_message( - response, Destination::BlindedPath(reply_path), format_args!( - "when responding to onion message with path_id {:02x?}", path_id - ) - ); - }, - None => { - log_trace!( - self.logger, - "Missing reply path when responding to onion message with path_id {:02x?}", + let response = self.custom_handler.handle_custom_message(msg); + self.handle_onion_message_response( + response, reply_path, format_args!( + "when responding to Custom onion message with path_id {:02x?}", path_id - ); - }, - } + ) + ); + }, } }, Ok(PeeledOnion::Forward(next_node_id, onion_message)) => { @@ -683,9 +689,9 @@ pub type SimpleRefOnionMessenger<'a, 'b, 'c, L> = OnionMessenger< /// Construct onion packet payloads and keys for sending an onion message along the given /// `unblinded_path` to the given `destination`. -fn packet_payloads_and_keys( - secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], destination: Destination, - message: ParsedOnionMessageContents, mut reply_path: Option, session_priv: &SecretKey +fn packet_payloads_and_keys( + secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], destination: Destination, message: T, + mut reply_path: Option, session_priv: &SecretKey ) -> Result<(Vec<(Payload, [u8; 32])>, Vec), secp256k1::Error> { let num_hops = unblinded_path.len() + destination.num_hops(); let mut payloads = Vec::with_capacity(num_hops); @@ -761,7 +767,7 @@ fn packet_payloads_and_keys(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec, prng_seed: [u8; 32]) -> Result { +fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec, prng_seed: [u8; 32]) -> Result { // Spec rationale: // "`len` allows larger messages to be sent than the standard 1300 bytes allowed for an HTLC // onion, but this should be used sparingly as it is reduces anonymity set, hence the diff --git a/lightning/src/onion_message/mod.rs b/lightning/src/onion_message/mod.rs index 59c46721..dd927923 100644 --- a/lightning/src/onion_message/mod.rs +++ b/lightning/src/onion_message/mod.rs @@ -27,7 +27,7 @@ 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, DefaultMessageRouter, Destination, MessageRouter, ParsedOnionMessageContents, OnionMessagePath, OnionMessenger, PeeledOnion, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger}; +pub use self::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, PeeledOnion, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger}; pub use self::offers::{OffersMessage, OffersMessageHandler}; -pub use self::packet::Packet; +pub use self::packet::{Packet, ParsedOnionMessageContents}; pub(crate) use self::packet::ControlTlvs; diff --git a/lightning/src/onion_message/offers.rs b/lightning/src/onion_message/offers.rs index de373bda..f5945cd5 100644 --- a/lightning/src/onion_message/offers.rs +++ b/lightning/src/onion_message/offers.rs @@ -16,6 +16,7 @@ use crate::offers::invoice_error::InvoiceError; use crate::offers::invoice_request::InvoiceRequest; use crate::offers::invoice::Bolt12Invoice; use crate::offers::parse::Bolt12ParseError; +use crate::onion_message::OnionMessageContents; use crate::util::logger::Logger; use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer}; @@ -63,15 +64,6 @@ impl OffersMessage { } } - /// The TLV record type for the message as used in an `onionmsg_tlv` TLV stream. - pub fn tlv_type(&self) -> u64 { - match self { - OffersMessage::InvoiceRequest(_) => INVOICE_REQUEST_TLV_TYPE, - OffersMessage::Invoice(_) => INVOICE_TLV_TYPE, - OffersMessage::InvoiceError(_) => INVOICE_ERROR_TLV_TYPE, - } - } - fn parse(tlv_type: u64, bytes: Vec) -> Result { match tlv_type { INVOICE_REQUEST_TLV_TYPE => Ok(Self::InvoiceRequest(InvoiceRequest::try_from(bytes)?)), @@ -81,6 +73,16 @@ impl OffersMessage { } } +impl OnionMessageContents for OffersMessage { + fn tlv_type(&self) -> u64 { + match self { + OffersMessage::InvoiceRequest(_) => INVOICE_REQUEST_TLV_TYPE, + OffersMessage::Invoice(_) => INVOICE_TLV_TYPE, + OffersMessage::InvoiceError(_) => INVOICE_ERROR_TLV_TYPE, + } + } +} + impl Writeable for OffersMessage { fn write(&self, w: &mut W) -> Result<(), io::Error> { match self { diff --git a/lightning/src/onion_message/packet.rs b/lightning/src/onion_message/packet.rs index c5411831..19ca6eb9 100644 --- a/lightning/src/onion_message/packet.rs +++ b/lightning/src/onion_message/packet.rs @@ -103,31 +103,33 @@ impl LengthReadable for Packet { /// Onion message payloads contain "control" TLVs and "data" TLVs. Control TLVs are used to route /// the onion message from hop to hop and for path verification, whereas data TLVs contain the onion /// message content itself, such as an invoice request. -pub(super) enum Payload { +pub(super) enum Payload { /// This payload is for an intermediate hop. Forward(ForwardControlTlvs), /// This payload is for the final hop. Receive { control_tlvs: ReceiveControlTlvs, reply_path: Option, - message: ParsedOnionMessageContents, + message: T, } } -/// The contents of an onion message as read from the wire. +/// The contents of an [`OnionMessage`] as read from the wire. +/// +/// [`OnionMessage`]: crate::ln::msgs::OnionMessage #[derive(Debug)] -pub enum ParsedOnionMessageContents { +pub enum ParsedOnionMessageContents { /// A message related to BOLT 12 Offers. Offers(OffersMessage), /// A custom onion message specified by the user. Custom(T), } -impl ParsedOnionMessageContents { +impl OnionMessageContents for ParsedOnionMessageContents { /// Returns the type that was used to decode the message payload. /// /// This is not exported to bindings users as methods on non-cloneable enums are not currently exportable - pub fn tlv_type(&self) -> u64 { + fn tlv_type(&self) -> u64 { match self { &ParsedOnionMessageContents::Offers(ref msg) => msg.tlv_type(), &ParsedOnionMessageContents::Custom(ref msg) => msg.tlv_type(), @@ -136,7 +138,7 @@ impl ParsedOnionMessageContents { } /// This is not exported to bindings users as methods on non-cloneable enums are not currently exportable -impl Writeable for ParsedOnionMessageContents { +impl Writeable for ParsedOnionMessageContents { fn write(&self, w: &mut W) -> Result<(), io::Error> { match self { ParsedOnionMessageContents::Offers(msg) => Ok(msg.write(w)?), @@ -145,8 +147,8 @@ impl Writeable for ParsedOnionMessageContents } } -/// The contents of a custom onion message. -pub trait CustomOnionMessageContents: Writeable { +/// The contents of an onion message. +pub trait OnionMessageContents: Writeable { /// Returns the TLV type identifying the message contents. MUST be >= 64. fn tlv_type(&self) -> u64; } @@ -172,7 +174,7 @@ pub(super) enum ReceiveControlTlvs { } // Uses the provided secret to simultaneously encode and encrypt the unblinded control TLVs. -impl Writeable for (Payload, [u8; 32]) { +impl Writeable for (Payload, [u8; 32]) { fn write(&self, w: &mut W) -> Result<(), io::Error> { match &self.0 { Payload::Forward(ForwardControlTlvs::Blinded(encrypted_bytes)) => { @@ -211,8 +213,8 @@ impl Writeable for (Payload, [u8; 32]) { } // Uses the provided secret to simultaneously decode and decrypt the control TLVs and data TLV. -impl -ReadableArgs<(SharedSecret, &H, &L)> for Payload<::CustomMessage> { +impl ReadableArgs<(SharedSecret, &H, &L)> +for Payload::CustomMessage>> { fn read(r: &mut R, args: (SharedSecret, &H, &L)) -> Result { let (encrypted_tlvs_ss, handler, logger) = args; -- 2.30.2