//! Onion message testing and test utilities live here.
use chain::keysinterface::{KeysInterface, Recipient};
-use super::{BlindedRoute, Destination, OnionMessenger};
+use super::{BlindedRoute, Destination, OnionMessenger, SendError};
use util::enforcing_trait_impls::EnforcingSigner;
use util::test_utils;
use bitcoin::network::constants::Network;
-use bitcoin::secp256k1::{PublicKey, Secp256k1};
+use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use sync::Arc;
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route)).unwrap();
pass_along_path(nodes, None);
}
+
+#[test]
+fn too_big_packet_error() {
+ // Make sure we error as expected if a packet is too big to send.
+ let nodes = create_nodes(1);
+
+ let hop_secret = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
+ let secp_ctx = Secp256k1::new();
+ let hop_node_id = PublicKey::from_secret_key(&secp_ctx, &hop_secret);
+
+ let hops = [hop_node_id; 400];
+ let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id)).unwrap_err();
+ assert_eq!(err, SendError::TooBigPacket);
+}
}
}
+/// 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,
+}
+
impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
where K::Target: KeysInterface<Signer = Signer>,
L::Target: Logger,
/// 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> {
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 {
}
};
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());
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
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))
}