diff --git a/lightning/src/onion_message.rs b/lightning/src/onion_message.rs index 777a16a4b69..64cdf23cd7e 100644 --- a/lightning/src/onion_message.rs +++ b/lightning/src/onion_message.rs @@ -365,6 +365,11 @@ impl Destination { pub enum SendError { /// Errored computing onion message packet keys. Secp256k1(secp256k1::Error), + /// The provided [destination] was an invalid [blinded route], due to having 0 blinded hops. + /// + /// [destination]: Destination + /// [blinded route]: BlindedRoute + MissingBlindedHops, /// 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, @@ -457,6 +462,11 @@ impl OnionMessenger /// Send an empty onion message to `destination`, routing it through `intermediate_nodes`. pub fn send_onion_message(&self, intermediate_nodes: Vec, destination: Destination) -> Result<(), SendError> { + if let Destination::BlindedRoute(BlindedRoute { ref blinded_hops, .. }) = destination { + if blinded_hops.len() == 0 { + return Err(SendError::MissingBlindedHops); + } + } 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 { @@ -806,6 +816,7 @@ mod tests { use bitcoin::network::constants::Network; use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; + use core::mem; use sync::Arc; struct MessengerNode { @@ -911,4 +922,19 @@ mod tests { let err = nodes[0].messenger.send_onion_message(hops, Destination::Node(hop_node_id)).unwrap_err(); assert_eq!(err, SendError::TooBigPacket); } + + #[test] + fn invalid_blinded_route_error() { + // Make sure we error as expected if a provided blinded route has 0 hops. + let mut nodes = create_nodes(3); + let (node1, node2, node3) = (nodes.remove(0), nodes.remove(0), nodes.remove(0)); + + let secp_ctx = Secp256k1::new(); + let mut blinded_route = BlindedRoute::new(vec![node2.get_node_pk(), node3.get_node_pk()], &node3.keys_manager, &secp_ctx).unwrap(); + let mut empty_hops = Vec::new(); + mem::swap(&mut empty_hops, &mut blinded_route.blinded_hops); + + let err = node1.messenger.send_onion_message(vec![], Destination::BlindedRoute(blinded_route)).unwrap_err(); + assert_eq!(err, SendError::MissingBlindedHops); + } }