X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fonion_message%2Fmessenger.rs;h=3677efda420cc8663914512ea38c732216de8f59;hb=ee17faff904b0be91902b64e2fbcb05f9db28a51;hp=b9da9246cb103bcf44eb82050bd5870f45521ae5;hpb=b9b02b48fb4dd66181f61739fa0047c29dead697;p=rust-lightning diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index b9da9246..3677efda 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -16,6 +16,7 @@ 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 super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs}; @@ -23,6 +24,7 @@ use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload use super::utils; use util::events::OnionMessageProvider; use util::logger::Logger; +use util::ser::Writeable; use core::ops::Deref; use sync::{Arc, Mutex}; @@ -69,7 +71,7 @@ use prelude::*; /// // Create a blinded route to yourself, for someone to send an onion message to. /// # let your_node_id = hop_node_id1; /// let hops = [hop_node_id3, hop_node_id4, your_node_id]; -/// let blinded_route = BlindedRoute::new::(&hops, &keys_manager, &secp_ctx).unwrap(); +/// let blinded_route = BlindedRoute::new(&hops, &keys_manager, &secp_ctx).unwrap(); /// /// // Send an empty onion message to a blinded route. /// # let intermediate_hops = [hop_node_id1, hop_node_id2]; @@ -112,7 +114,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), @@ -124,6 +126,8 @@ pub enum SendError { TooFewBlindedHops, /// Our next-hop peer was offline or does not support onion message forwarding. InvalidFirstHop, + /// Our next-hop peer's buffer was full or our total outbound buffer was full. + BufferFull, } impl OnionMessenger @@ -171,6 +175,7 @@ impl OnionMessenger 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) => { @@ -193,6 +198,29 @@ impl OnionMessenger } } +fn outbound_buffer_full(peer_node_id: &PublicKey, buffer: &HashMap>) -> bool { + const MAX_TOTAL_BUFFER_SIZE: usize = (1 << 20) * 128; + const MAX_PER_PEER_BUFFER_SIZE: usize = (1 << 10) * 256; + let mut total_buffered_bytes = 0; + let mut peer_buffered_bytes = 0; + for (pk, peer_buf) in buffer { + for om in peer_buf { + let om_len = om.serialized_length(); + if pk == peer_node_id { + peer_buffered_bytes += om_len; + } + total_buffered_bytes += om_len; + + if total_buffered_bytes >= MAX_TOTAL_BUFFER_SIZE || + peer_buffered_bytes >= MAX_PER_PEER_BUFFER_SIZE + { + return true + } + } + } + false +} + impl OnionMessageHandler for OnionMessenger where K::Target: KeysInterface, L::Target: Logger, @@ -255,8 +283,34 @@ impl OnionMessageHandler for OnionMessenger blinding_point, + None => { + let blinding_factor = { + let mut sha = Sha256::engine(); + sha.input(&msg.blinding_point.serialize()[..]); + sha.input(control_tlvs_ss.as_ref()); + Sha256::from_engine(sha).into_inner() + }; + let next_blinding_point = msg.blinding_point; + match next_blinding_point.mul_tweak(&self.secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap()) { + Ok(bp) => bp, + Err(e) => { + log_trace!(self.logger, "Failed to compute next blinding point: {}", e); + return + } + } + }, + }, + onion_routing_packet: outgoing_packet, + }; let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap(); + if outbound_buffer_full(&next_node_id, &pending_per_peer_msgs) { + log_trace!(self.logger, "Dropping forwarded onion message to peer {:?}: outbound buffer full", next_node_id); + return + } #[cfg(fuzzing)] pending_per_peer_msgs.entry(next_node_id).or_insert_with(VecDeque::new); @@ -267,30 +321,7 @@ impl OnionMessageHandler for OnionMessenger { - e.get_mut().push_back( - msgs::OnionMessage { - blinding_point: match next_blinding_override { - Some(blinding_point) => blinding_point, - None => { - let blinding_factor = { - let mut sha = Sha256::engine(); - sha.input(&msg.blinding_point.serialize()[..]); - sha.input(control_tlvs_ss.as_ref()); - Sha256::from_engine(sha).into_inner() - }; - let next_blinding_point = msg.blinding_point; - match next_blinding_point.mul_tweak(&self.secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap()) { - Ok(bp) => bp, - Err(e) => { - log_trace!(self.logger, "Failed to compute next blinding point: {}", e); - return - } - } - }, - }, - onion_routing_packet: outgoing_packet, - }, - ); + e.get_mut().push_back(onion_message); log_trace!(self.logger, "Forwarding an onion message to peer {}", next_node_id); } }; @@ -304,17 +335,30 @@ impl OnionMessageHandler for OnionMessenger Result<(), ()> { if init.features.supports_onion_messages() { let mut peers = self.pending_messages.lock().unwrap(); peers.insert(their_node_id.clone(), VecDeque::new()); } + Ok(()) } fn peer_disconnected(&self, their_node_id: &PublicKey, _no_connection_possible: bool) { let mut pending_msgs = self.pending_messages.lock().unwrap(); pending_msgs.remove(their_node_id); } + + fn provided_node_features(&self) -> NodeFeatures { + let mut features = NodeFeatures::empty(); + features.set_onion_messages_optional(); + features + } + + fn provided_init_features(&self, _their_node_id: &PublicKey) -> InitFeatures { + let mut features = InitFeatures::empty(); + features.set_onion_messages_optional(); + features + } } impl OnionMessageProvider for OnionMessenger @@ -335,14 +379,18 @@ impl OnionMessageProvider for OnionMessenger = OnionMessenger, Arc>; /// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and /// [`SimpleRefPeerManager`]. See their docs for more details. /// -///[`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager -///[`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager +/// (C-not exported) as general type aliases don't make sense in bindings. +/// +/// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager +/// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger; /// Construct onion packet payloads and keys for sending an onion message along the given