X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fonion_message%2Fmessenger.rs;h=a09c942be61fbfcb75da606e6b440bfffa37bdbc;hb=593d8c4610f082441563d4906d64175a354b1cfc;hp=9c86a44e0a0a6a80b0ded58c2d26c376c3f38f9b;hpb=7664957bc958217a98effda67428cc32f239e750;p=rust-lightning diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 9c86a44e..a09c942b 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -15,22 +15,23 @@ use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey}; -use chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager, Recipient, Sign}; -use ln::features::{InitFeatures, NodeFeatures}; -use ln::msgs::{self, OnionMessageHandler}; -use ln::onion_utils; -use ln::peer_handler::IgnoringMessageHandler; +use crate::chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager, Recipient, Sign}; +use crate::ln::features::{InitFeatures, NodeFeatures}; +use crate::ln::msgs::{self, OnionMessageHandler}; +use crate::ln::onion_utils; +use crate::ln::peer_handler::IgnoringMessageHandler; use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs}; pub use super::packet::{CustomOnionMessageContents, OnionMessageContents}; use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN}; use super::utils; -use util::events::OnionMessageProvider; -use util::logger::Logger; -use util::ser::Writeable; +use crate::util::events::OnionMessageProvider; +use crate::util::logger::Logger; +use crate::util::ser::Writeable; use core::ops::Deref; -use sync::{Arc, Mutex}; -use prelude::*; +use crate::io; +use crate::sync::{Arc, Mutex}; +use crate::prelude::*; /// A sender, receiver and forwarder of onion messages. In upcoming releases, this object will be /// used to retrieve invoices and fulfill invoice requests from [offers]. Currently, only sending @@ -47,7 +48,7 @@ use prelude::*; /// # use lightning::ln::peer_handler::IgnoringMessageHandler; /// # use lightning::onion_message::{BlindedRoute, CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger}; /// # use lightning::util::logger::{Logger, Record}; -/// # use lightning::util::ser::{MaybeReadableArgs, Writeable, Writer}; +/// # use lightning::util::ser::{Writeable, Writer}; /// # use lightning::io; /// # use std::sync::Arc; /// # struct FakeLogger {}; @@ -81,13 +82,6 @@ use prelude::*; /// your_custom_message_type /// } /// } -/// impl MaybeReadableArgs for YourCustomMessage { -/// fn read(r: &mut R, message_type: u64) -> Result, DecodeError> { -/// # unreachable!() -/// // Read your custom onion message of type `message_type` from `r`, or return `None` -/// // if the message type is unknown -/// } -/// } /// // Send a custom onion message to a node id. /// let intermediate_hops = [hop_node_id1, hop_node_id2]; /// let reply_path = None; @@ -144,7 +138,7 @@ impl Destination { /// Errors that may occur when [sending an onion message]. /// /// [sending an onion message]: OnionMessenger::send_onion_message -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum SendError { /// Errored computing onion message packet keys. Secp256k1(secp256k1::Error), @@ -156,8 +150,19 @@ pub enum SendError { TooFewBlindedHops, /// Our next-hop peer was offline or does not support onion message forwarding. InvalidFirstHop, + /// Onion message contents must have a TLV type >= 64. + InvalidMessage, /// Our next-hop peer's buffer was full or our total outbound buffer was full. BufferFull, + /// Failed to retrieve our node id from the provided [`KeysInterface`]. + /// + /// [`KeysInterface`]: crate::chain::keysinterface::KeysInterface + GetNodeIdFailed, + /// We attempted to send to a blinded route where we are the introduction node, and failed to + /// advance the blinded route to make the second hop the new introduction node. Either + /// [`KeysInterface::ecdh`] failed, we failed to tweak the current blinding point to get the + /// new blinding point, or we were attempting to send to ourselves. + BlindedRouteAdvanceFailed, } /// Handler for custom onion messages. If you are using [`SimpleArcOnionMessenger`], @@ -176,6 +181,9 @@ pub trait CustomOnionMessageHandler { type CustomMessage: CustomOnionMessageContents; /// Called with the custom message that was received. fn handle_custom_message(&self, msg: Self::CustomMessage); + /// 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>; } impl OnionMessenger @@ -199,12 +207,28 @@ impl OnionMessenger(&self, intermediate_nodes: &[PublicKey], destination: Destination, message: OnionMessageContents, reply_path: Option) -> Result<(), SendError> { + pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], mut destination: Destination, message: OnionMessageContents, reply_path: Option) -> Result<(), SendError> { if let Destination::BlindedRoute(BlindedRoute { ref blinded_hops, .. }) = destination { if blinded_hops.len() < 2 { return Err(SendError::TooFewBlindedHops); } } + let OnionMessageContents::Custom(ref msg) = message; + if msg.tlv_type() < 64 { return Err(SendError::InvalidMessage) } + + // If we are sending straight to a blinded route and we are the introduction node, we need to + // advance the blinded route by 1 hop so the second hop is the new introduction node. + if intermediate_nodes.len() == 0 { + if let Destination::BlindedRoute(ref mut blinded_route) = destination { + let our_node_id = self.keys_manager.get_node_id(Recipient::Node) + .map_err(|()| SendError::GetNodeIdFailed)?; + if blinded_route.introduction_node_id == our_node_id { + blinded_route.advance_by_one(&self.keys_manager, &self.secp_ctx) + .map_err(|()| SendError::BlindedRouteAdvanceFailed)?; + } + } + } + let blinding_secret_bytes = self.keys_manager.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 { @@ -274,7 +298,7 @@ fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap OnionMessageHandler for OnionMessenger where K::Target: KeysInterface, L::Target: Logger, - CMH::Target: CustomOnionMessageHandler, + CMH::Target: CustomOnionMessageHandler + Sized, { /// 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 @@ -303,8 +327,8 @@ impl OnionMessageHandler for Onion } } }; - match onion_utils::decode_next_hop(onion_decode_ss, &msg.onion_routing_packet.hop_data[..], - msg.onion_routing_packet.hmac, control_tlvs_ss) + match onion_utils::decode_next_untagged_hop(onion_decode_ss, &msg.onion_routing_packet.hop_data[..], + msg.onion_routing_packet.hmac, (control_tlvs_ss, &*self.custom_handler)) { Ok((Payload::Receive::<<::Target as CustomOnionMessageHandler>::CustomMessage> { message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path, @@ -486,12 +510,8 @@ fn packet_payloads_and_keys