X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fonion_message%2Fmessenger.rs;h=044248961973099560fae9853e8a86cca3037a98;hb=04d8f5e3f11c156a862940856002971dcb7ac358;hp=930d90ebac37c2936f0be0de0bf1eb0556a64362;hpb=eaff561e244943f6383ec9fb26e3f71dc628a104;p=rust-lightning diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 930d90eb..04424896 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -13,7 +13,7 @@ use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::hmac::{Hmac, HmacEngine}; use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; +use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey}; use chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager, Recipient, Sign}; use ln::msgs; @@ -108,6 +108,21 @@ 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, +} + impl OnionMessenger where K::Target: KeysInterface, L::Target: Logger, @@ -127,7 +142,12 @@ impl OnionMessenger /// Send an empty onion message to `destination`, routing it through `intermediate_nodes`. /// See [`OnionMessenger`] for example usage. - pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], destination: Destination) -> Result<(), secp256k1::Error> { + pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], destination: Destination) -> 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 { @@ -140,10 +160,12 @@ impl OnionMessenger } }; let (packet_payloads, packet_keys) = packet_payloads_and_keys( - &self.secp_ctx, intermediate_nodes, destination, &blinding_secret)?; + &self.secp_ctx, intermediate_nodes, destination, &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_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()); @@ -174,7 +196,7 @@ impl OnionMessenger Hmac::from_engine(hmac).into_inner() }; match self.keys_manager.ecdh(Recipient::Node, &msg.onion_routing_packet.public_key, - Some(&blinding_factor)) + Some(&Scalar::from_be_bytes(blinding_factor).unwrap())) { Ok(ss) => ss.secret_bytes(), Err(()) => { @@ -227,11 +249,13 @@ impl OnionMessenger Sha256::from_engine(sha).into_inner() }; let mut next_blinding_point = msg.blinding_point; - if let Err(e) = next_blinding_point.mul_assign(&self.secp_ctx, &blinding_factor[..]) { - log_trace!(self.logger, "Failed to compute next blinding point: {}", e); - return + 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 + } } - next_blinding_point }, }, onion_routing_packet: outgoing_packet, @@ -343,7 +367,8 @@ fn packet_payloads_and_keys( Ok((payloads, onion_packet_keys)) } -fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec, 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, 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 @@ -353,7 +378,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)) }