X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fonion_message%2Fmessenger.rs;h=cf0f9e086b5c41a12c2e9b1b5e27f3a03949fae7;hb=1f399b0984d591019320459d804cbad859c608ae;hp=d6aa5c82ca5bc526118b539c53b95eedbeb37688;hpb=840efd533468cf7cacd8b4bab27ce2db86b3eb93;p=rust-lightning diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index d6aa5c82..cf0f9e08 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -19,6 +19,8 @@ use crate::blinded_path::BlindedPath; use crate::blinded_path::message::{advance_path_by_one, ForwardTlvs, ReceiveTlvs}; use crate::blinded_path::utils; use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient}; +#[cfg(not(c_bindings))] +use crate::ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager}; use crate::ln::features::{InitFeatures, NodeFeatures}; use crate::ln::msgs::{self, OnionMessage, OnionMessageHandler}; use crate::ln::onion_utils; @@ -153,6 +155,38 @@ where custom_handler: CMH, } +/// An [`OnionMessage`] for [`OnionMessenger`] to send. +/// +/// These are obtained when released from [`OnionMessenger`]'s handlers after which they are +/// enqueued for sending. +#[cfg(not(c_bindings))] +pub struct PendingOnionMessage { + /// The message contents to send in an [`OnionMessage`]. + pub contents: T, + + /// The destination of the message. + pub destination: Destination, + + /// A reply path to include in the [`OnionMessage`] for a response. + pub reply_path: Option, +} + +#[cfg(c_bindings)] +/// An [`OnionMessage`] for [`OnionMessenger`] to send. +/// +/// These are obtained when released from [`OnionMessenger`]'s handlers after which they are +/// enqueued for sending. +pub type PendingOnionMessage = (T, Destination, Option); + +pub(crate) fn new_pending_onion_message( + contents: T, destination: Destination, reply_path: Option +) -> PendingOnionMessage { + #[cfg(not(c_bindings))] + return PendingOnionMessage { contents, destination, reply_path }; + #[cfg(c_bindings)] + return (contents, destination, reply_path); +} + /// A trait defining behavior for routing an [`OnionMessage`]. pub trait MessageRouter { /// Returns a route for sending an [`OnionMessage`] to the given [`Destination`]. @@ -161,14 +195,18 @@ pub trait MessageRouter { ) -> Result; } -/// A [`MessageRouter`] that always fails. +/// A [`MessageRouter`] that can only route to a directly connected [`Destination`]. pub struct DefaultMessageRouter; impl MessageRouter for DefaultMessageRouter { fn find_path( - &self, _sender: PublicKey, _peers: Vec, _destination: Destination + &self, _sender: PublicKey, peers: Vec, destination: Destination ) -> Result { - Err(()) + if peers.contains(&destination.first_node()) { + Ok(OnionMessagePath { intermediate_nodes: vec![], destination }) + } else { + Err(()) + } } } @@ -198,6 +236,13 @@ impl Destination { Destination::BlindedPath(BlindedPath { blinded_hops, .. }) => blinded_hops.len(), } } + + fn first_node(&self) -> PublicKey { + match self { + Destination::Node(node_id) => *node_id, + Destination::BlindedPath(BlindedPath { introduction_node_id: node_id, .. }) => *node_id, + } + } } /// Errors that may occur when [sending an onion message]. @@ -210,8 +255,8 @@ pub enum SendError { /// Because implementations such as Eclair will drop onion messages where the message packet /// exceeds 32834 bytes, we refuse to send messages where the packet exceeds this size. TooBigPacket, - /// The provided [`Destination`] was an invalid [`BlindedPath`], due to having fewer than two - /// blinded hops. + /// The provided [`Destination`] was an invalid [`BlindedPath`] due to not having any blinded + /// hops. TooFewBlindedHops, /// Our next-hop peer was offline or does not support onion message forwarding. InvalidFirstHop, @@ -246,11 +291,27 @@ pub trait CustomOnionMessageHandler { type CustomMessage: OnionMessageContents; /// 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, msg: Self::CustomMessage) -> Option; /// Read a custom message of type `message_type` from `buffer`, returning `Ok(None)` if the /// message type is unknown. fn read_custom_message(&self, message_type: u64, buffer: &mut R) -> Result, msgs::DecodeError>; + + /// Releases any [`Self::CustomMessage`]s that need to be sent. + /// + /// Typically, this is used for messages initiating a message flow rather than in response to + /// another message. The latter should use the return value of [`Self::handle_custom_message`]. + #[cfg(not(c_bindings))] + fn release_pending_custom_messages(&self) -> Vec>; + + /// Releases any [`Self::CustomMessage`]s that need to be sent. + /// + /// Typically, this is used for messages initiating a message flow rather than in response to + /// another message. The latter should use the return value of [`Self::handle_custom_message`]. + #[cfg(c_bindings)] + fn release_pending_custom_messages(&self) -> Vec<(Self::CustomMessage, Destination, Option)>; } /// A processed incoming onion message, containing either a Forward (another onion message) @@ -276,7 +337,7 @@ where { let OnionMessagePath { intermediate_nodes, mut destination } = path; if let Destination::BlindedPath(BlindedPath { ref blinded_hops, .. }) = destination { - if blinded_hops.len() < 2 { + if blinded_hops.is_empty() { return Err(SendError::TooFewBlindedHops); } } @@ -321,11 +382,13 @@ where })) } -/// Decode one layer of an incoming onion message -/// Returns either a Forward (another onion message), or Receive (decrypted content) -pub fn peel_onion( - node_signer: NS, secp_ctx: &Secp256k1, logger: L, custom_handler: CMH, - msg: &OnionMessage, +/// Decode one layer of an incoming [`OnionMessage`]. +/// +/// Returns either the next layer of the onion for forwarding or the decrypted content for the +/// receiver. +pub fn peel_onion_message( + msg: &OnionMessage, secp_ctx: &Secp256k1, node_signer: NS, logger: L, + custom_handler: CMH, ) -> Result::Target as CustomOnionMessageHandler>::CustomMessage>, ()> where NS::Target: NodeSigner, @@ -475,7 +538,7 @@ where match reply_path { Some(reply_path) => { self.find_path_and_enqueue_onion_message( - response, Destination::BlindedPath(reply_path), log_suffix + response, Destination::BlindedPath(reply_path), None, log_suffix ); }, None => { @@ -486,7 +549,8 @@ where } fn find_path_and_enqueue_onion_message( - &self, contents: T, destination: Destination, log_suffix: fmt::Arguments + &self, contents: T, destination: Destination, reply_path: Option, + log_suffix: fmt::Arguments ) { let sender = match self.node_signer.get_node_id(Recipient::Node) { Ok(node_id) => node_id, @@ -507,7 +571,7 @@ where log_trace!(self.logger, "Sending onion message {}", log_suffix); - if let Err(e) = self.send_onion_message(path, contents, None) { + if let Err(e) = self.send_onion_message(path, contents, reply_path) { log_trace!(self.logger, "Failed sending onion message {}: {:?}", log_suffix, e); return; } @@ -559,12 +623,9 @@ where OMH::Target: OffersMessageHandler, CMH::Target: CustomOnionMessageHandler, { - /// Handle an incoming onion message. Currently, if a message was destined for us we will log, but - /// soon we'll delegate the onion message to a handler that can generate invoices or send - /// payments. fn handle_onion_message(&self, _peer_node_id: &PublicKey, msg: &OnionMessage) { - match peel_onion( - &*self.node_signer, &self.secp_ctx, &*self.logger, &*self.custom_handler, msg + match peel_onion_message( + msg, &self.secp_ctx, &*self.node_signer, &*self.logger, &*self.custom_handler ) { Ok(PeeledOnion::Receive(message, path_id, reply_path)) => { log_trace!(self.logger, @@ -644,7 +705,32 @@ where features } + // Before returning any messages to send for the peer, this method will see if any messages were + // enqueued in the handler by users, find a path to the corresponding blinded path's introduction + // node, and then enqueue the message for sending to the first peer in the full path. fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option { + // Enqueue any initiating `OffersMessage`s to send. + for message in self.offers_handler.release_pending_messages() { + #[cfg(not(c_bindings))] + let PendingOnionMessage { contents, destination, reply_path } = message; + #[cfg(c_bindings)] + let (contents, destination, reply_path) = message; + self.find_path_and_enqueue_onion_message( + contents, destination, reply_path, format_args!("when sending OffersMessage") + ); + } + + // Enqueue any initiating `CustomMessage`s to send. + for message in self.custom_handler.release_pending_custom_messages() { + #[cfg(not(c_bindings))] + let PendingOnionMessage { contents, destination, reply_path } = message; + #[cfg(c_bindings)] + let (contents, destination, reply_path) = message; + self.find_path_and_enqueue_onion_message( + contents, destination, reply_path, format_args!("when sending CustomMessage") + ); + } + let mut pending_msgs = self.pending_messages.lock().unwrap(); if let Some(msgs) = pending_msgs.get_mut(&peer_node_id) { return msgs.pop_front() @@ -658,32 +744,36 @@ where /// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and /// [`SimpleArcPeerManager`]. See their docs for more details. /// -/// This is not exported to bindings users as `Arc`s don't make sense in bindings. +/// This is not exported to bindings users as type aliases aren't supported in most languages. /// /// [`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager /// [`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager -pub type SimpleArcOnionMessenger = OnionMessenger< +#[cfg(not(c_bindings))] +pub type SimpleArcOnionMessenger = OnionMessenger< Arc, Arc, Arc, Arc, - IgnoringMessageHandler, + Arc>, IgnoringMessageHandler >; /// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and /// [`SimpleRefPeerManager`]. See their docs for more details. /// -/// This is not exported to bindings users as general type aliases don't make sense in bindings. +/// This is not exported to bindings users as type aliases aren't supported in most languages. /// /// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager /// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager -pub type SimpleRefOnionMessenger<'a, 'b, 'c, L> = OnionMessenger< +#[cfg(not(c_bindings))] +pub type SimpleRefOnionMessenger< + 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, M, T, F, L +> = OnionMessenger< &'a KeysManager, &'a KeysManager, &'b L, - &'c DefaultMessageRouter, - IgnoringMessageHandler, + &'i DefaultMessageRouter, + &'j SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L>, IgnoringMessageHandler >;