Don't construct OnionMessage while holding peer lock
[rust-lightning] / lightning / src / onion_message / messenger.rs
index f4cb57f28df3410949a67b8ffb3f7f7e48cc6ae1..a3320f10d21091a0faa3131f3125384cc51b871f 100644 (file)
 //! LDK sends, receives, and forwards onion messages via the [`OnionMessenger`]. See its docs for
 //! more information.
 
-use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
+use bitcoin::hashes::{Hash, HashEngine};
+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, Sign};
-use ln::msgs;
+use chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager, Recipient, Sign};
+use ln::msgs::{self, OnionMessageHandler};
 use ln::onion_utils;
 use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
 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 core::ops::Deref;
@@ -25,16 +29,63 @@ use sync::{Arc, Mutex};
 use 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].
+/// used to retrieve invoices and fulfill invoice requests from [offers]. Currently, only sending
+/// and receiving empty onion messages is supported.
+///
+/// # Example
+///
+/// ```
+/// # extern crate bitcoin;
+/// # use bitcoin::hashes::_export::_core::time::Duration;
+/// # use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
+/// # use lightning::chain::keysinterface::{InMemorySigner, KeysManager, KeysInterface};
+/// # use lightning::onion_message::{BlindedRoute, Destination, OnionMessenger};
+/// # use lightning::util::logger::{Logger, Record};
+/// # use std::sync::Arc;
+/// # struct FakeLogger {};
+/// # impl Logger for FakeLogger {
+/// #     fn log(&self, record: &Record) { unimplemented!() }
+/// # }
+/// # let seed = [42u8; 32];
+/// # let time = Duration::from_secs(123456);
+/// # let keys_manager = KeysManager::new(&seed, time.as_secs(), time.subsec_nanos());
+/// # let logger = Arc::new(FakeLogger {});
+/// # let node_secret = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
+/// # let secp_ctx = Secp256k1::new();
+/// # let hop_node_id1 = PublicKey::from_secret_key(&secp_ctx, &node_secret);
+/// # let (hop_node_id2, hop_node_id3, hop_node_id4) = (hop_node_id1, hop_node_id1,
+/// hop_node_id1);
+/// # let destination_node_id = hop_node_id1;
+/// #
+/// // Create the onion messenger. This must use the same `keys_manager` as is passed to your
+/// // ChannelManager.
+/// let onion_messenger = OnionMessenger::new(&keys_manager, logger);
+///
+/// // Send an empty onion message to a node id.
+/// let intermediate_hops = [hop_node_id1, hop_node_id2];
+/// let reply_path = None;
+/// onion_messenger.send_onion_message(&intermediate_hops, Destination::Node(destination_node_id), reply_path);
+///
+/// // 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::<InMemorySigner, _, _>(&hops, &keys_manager, &secp_ctx).unwrap();
+///
+/// // Send an empty onion message to a blinded route.
+/// # let intermediate_hops = [hop_node_id1, hop_node_id2];
+/// let reply_path = None;
+/// onion_messenger.send_onion_message(&intermediate_hops, Destination::BlindedRoute(blinded_route), reply_path);
+/// ```
 ///
 /// [offers]: <https://github.com/lightning/bolts/pull/798>
+/// [`OnionMessenger`]: crate::onion_message::OnionMessenger
 pub struct OnionMessenger<Signer: Sign, K: Deref, L: Deref>
        where K::Target: KeysInterface<Signer = Signer>,
              L::Target: Logger,
 {
        keys_manager: K,
        logger: L,
-       pending_messages: Mutex<HashMap<PublicKey, Vec<msgs::OnionMessage>>>,
+       pending_messages: Mutex<HashMap<PublicKey, VecDeque<msgs::OnionMessage>>>,
        secp_ctx: Secp256k1<secp256k1::All>,
        // Coming soon:
        // invoice_handler: InvoiceHandler,
@@ -58,6 +109,23 @@ impl Destination {
        }
 }
 
+/// Errors that may occur when [sending an onion message].
+///
+/// [sending an onion message]: OnionMessenger::send_onion_message
+#[derive(Debug, PartialEq)]
+pub enum SendError {
+       /// Errored computing onion message packet keys.
+       Secp256k1(secp256k1::Error),
+       /// 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 [`BlindedRoute`], due to having fewer than two
+       /// blinded hops.
+       TooFewBlindedHops,
+       /// Our next-hop peer was offline or does not support onion message forwarding.
+       InvalidFirstHop,
+}
+
 impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
        where K::Target: KeysInterface<Signer = Signer>,
              L::Target: Logger,
@@ -76,7 +144,13 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
        }
 
        /// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
-       pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], destination: Destination) -> Result<(), secp256k1::Error> {
+       /// See [`OnionMessenger`] for example usage.
+       pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], destination: Destination, reply_path: Option<BlindedRoute>) -> Result<(), SendError> {
+               if let Destination::BlindedRoute(BlindedRoute { ref blinded_hops, .. }) = destination {
+                       if blinded_hops.len() < 2 {
+                               return Err(SendError::TooFewBlindedHops);
+                       }
+               }
                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 {
@@ -89,20 +163,169 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
                        }
                };
                let (packet_payloads, packet_keys) = packet_payloads_and_keys(
-                       &self.secp_ctx, intermediate_nodes, destination, &blinding_secret)?;
+                       &self.secp_ctx, intermediate_nodes, destination, reply_path, &blinding_secret)
+                       .map_err(|e| SendError::Secp256k1(e))?;
 
                let prng_seed = self.keys_manager.get_secure_random_bytes();
-               let onion_packet = construct_onion_message_packet(packet_payloads, packet_keys, prng_seed);
+               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();
-               let pending_msgs = pending_per_peer_msgs.entry(introduction_node_id).or_insert(Vec::new());
-               pending_msgs.push(
-                       msgs::OnionMessage {
-                               blinding_point,
-                               onion_routing_packet: onion_packet,
+               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(())
+                       }
+               }
+       }
+
+       #[cfg(test)]
+       pub(super) fn release_pending_msgs(&self) -> HashMap<PublicKey, VecDeque<msgs::OnionMessage>> {
+               let mut pending_msgs = self.pending_messages.lock().unwrap();
+               let mut msgs = HashMap::new();
+               // We don't want to disconnect the peers by removing them entirely from the original map, so we
+               // swap the pending message buffers individually.
+               for (peer_node_id, pending_messages) in &mut *pending_msgs {
+                       msgs.insert(*peer_node_id, core::mem::take(pending_messages));
+               }
+               msgs
+       }
+}
+
+impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Signer, K, L>
+       where K::Target: KeysInterface<Signer = Signer>,
+             L::Target: Logger,
+{
+       /// 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: &msgs::OnionMessage) {
+               let control_tlvs_ss = match self.keys_manager.ecdh(Recipient::Node, &msg.blinding_point, None) {
+                       Ok(ss) => ss,
+                       Err(e) =>  {
+                               log_error!(self.logger, "Failed to retrieve node secret: {:?}", e);
+                               return
                        }
-               );
-               Ok(())
+               };
+               let onion_decode_ss = {
+                       let blinding_factor = {
+                               let mut hmac = HmacEngine::<Sha256>::new(b"blinded_node_id");
+                               hmac.input(control_tlvs_ss.as_ref());
+                               Hmac::from_engine(hmac).into_inner()
+                       };
+                       match self.keys_manager.ecdh(Recipient::Node, &msg.onion_routing_packet.public_key,
+                               Some(&Scalar::from_be_bytes(blinding_factor).unwrap()))
+                       {
+                               Ok(ss) => ss.secret_bytes(),
+                               Err(()) => {
+                                       log_trace!(self.logger, "Failed to compute onion packet shared secret");
+                                       return
+                               }
+                       }
+               };
+               match onion_utils::decode_next_hop(onion_decode_ss, &msg.onion_routing_packet.hop_data[..],
+                       msg.onion_routing_packet.hmac, control_tlvs_ss)
+               {
+                       Ok((Payload::Receive {
+                               control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path,
+                       }, None)) => {
+                               log_info!(self.logger,
+                                       "Received an onion message with path_id: {:02x?} and {}reply_path",
+                                               path_id, if reply_path.is_some() { "" } else { "no " });
+                       },
+                       Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
+                               next_node_id, next_blinding_override
+                       })), Some((next_hop_hmac, new_packet_bytes)))) => {
+                               // TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy
+                               // blinded hop and this onion message is destined for us. In this situation, we should keep
+                               // unwrapping the onion layers to get to the final payload. Since we don't have the option
+                               // of creating blinded routes with dummy hops currently, we should be ok to not handle this
+                               // for now.
+                               let new_pubkey = match onion_utils::next_hop_packet_pubkey(&self.secp_ctx, msg.onion_routing_packet.public_key, &onion_decode_ss) {
+                                       Ok(pk) => pk,
+                                       Err(e) => {
+                                               log_trace!(self.logger, "Failed to compute next hop packet pubkey: {}", e);
+                                               return
+                                       }
+                               };
+                               let outgoing_packet = Packet {
+                                       version: 0,
+                                       public_key: new_pubkey,
+                                       hop_data: new_packet_bytes,
+                                       hmac: next_hop_hmac,
+                               };
+                               let onion_message = 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,
+                               };
+
+                               let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
+
+                               #[cfg(fuzzing)]
+                               pending_per_peer_msgs.entry(next_node_id).or_insert_with(VecDeque::new);
+
+                               match pending_per_peer_msgs.entry(next_node_id) {
+                                       hash_map::Entry::Vacant(_) => {
+                                               log_trace!(self.logger, "Dropping forwarded onion message to disconnected peer {:?}", next_node_id);
+                                               return
+                                       },
+                                       hash_map::Entry::Occupied(mut e) => {
+                                               e.get_mut().push_back(onion_message);
+                                               log_trace!(self.logger, "Forwarding an onion message to peer {}", next_node_id);
+                                       }
+                               };
+                       },
+                       Err(e) => {
+                               log_trace!(self.logger, "Errored decoding onion message packet: {:?}", e);
+                       },
+                       _ => {
+                               log_trace!(self.logger, "Received bogus onion message packet, either the sender encoded a final hop as a forwarding hop or vice versa");
+                       },
+               };
+       }
+
+       fn peer_connected(&self, their_node_id: &PublicKey, init: &msgs::Init) {
+               if init.features.supports_onion_messages() {
+                       let mut peers = self.pending_messages.lock().unwrap();
+                       peers.insert(their_node_id.clone(), VecDeque::new());
+               }
+       }
+
+       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);
+       }
+}
+
+impl<Signer: Sign, K: Deref, L: Deref> OnionMessageProvider for OnionMessenger<Signer, K, L>
+       where K::Target: KeysInterface<Signer = Signer>,
+             L::Target: Logger,
+{
+       fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<msgs::OnionMessage> {
+               let mut pending_msgs = self.pending_messages.lock().unwrap();
+               if let Some(msgs) = pending_msgs.get_mut(&peer_node_id) {
+                       return msgs.pop_front()
+               }
+               None
        }
 }
 
@@ -124,7 +347,8 @@ pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger<InMemorySigner, &'a
 /// 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<T: secp256k1::Signing + secp256k1::Verification>(
-       secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], destination: Destination, session_priv: &SecretKey
+       secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], destination: Destination, mut reply_path:
+       Option<BlindedRoute>, session_priv: &SecretKey
 ) -> Result<(Vec<(Payload, [u8; 32])>, Vec<onion_utils::OnionKeys>), secp256k1::Error> {
        let num_hops = unblinded_path.len() + destination.num_hops();
        let mut payloads = Vec::with_capacity(num_hops);
@@ -169,6 +393,7 @@ fn packet_payloads_and_keys<T: secp256k1::Signing + secp256k1::Verification>(
                } else if let Some(encrypted_payload) = enc_payload_opt {
                        payloads.push((Payload::Receive {
                                control_tlvs: ReceiveControlTlvs::Blinded(encrypted_payload),
+                               reply_path: reply_path.take(),
                        }, control_tlvs_ss));
                }
 
@@ -186,14 +411,16 @@ fn packet_payloads_and_keys<T: secp256k1::Signing + secp256k1::Verification>(
 
        if let Some(control_tlvs_ss) = prev_control_tlvs_ss {
                payloads.push((Payload::Receive {
-                       control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, })
+                       control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, }),
+                       reply_path: reply_path.take(),
                }, control_tlvs_ss));
        }
 
        Ok((payloads, onion_packet_keys))
 }
 
-fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec<onion_utils::OnionKeys>, prng_seed: [u8; 32]) -> Packet {
+/// Errors if the serialized payload size exceeds onion_message::BIG_PACKET_HOP_DATA_LEN
+fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec<onion_utils::OnionKeys>, prng_seed: [u8; 32]) -> Result<Packet, ()> {
        // 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
@@ -203,7 +430,8 @@ fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys
                SMALL_PACKET_HOP_DATA_LEN
        } else if payloads_ser_len <= BIG_PACKET_HOP_DATA_LEN {
                BIG_PACKET_HOP_DATA_LEN
-       } else { payloads_ser_len };
+       } else { return Err(()) };
 
-       onion_utils::construct_onion_message_packet::<_, _>(payloads, onion_keys, prng_seed, hop_data_len)
+       Ok(onion_utils::construct_onion_message_packet::<_, _>(
+               payloads, onion_keys, prng_seed, hop_data_len))
 }