Skip to content

Commit 9708dfa

Browse files
Add SendError enum for onion messages and error on too-big packets
1 parent fc53d80 commit 9708dfa

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

lightning/src/onion_message/functional_tests.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
//! Onion message testing and test utilities live here.
1111
1212
use chain::keysinterface::{KeysInterface, Recipient};
13-
use super::{BlindedRoute, Destination, OnionMessenger};
13+
use super::{BlindedRoute, Destination, OnionMessenger, SendError};
1414
use util::enforcing_trait_impls::EnforcingSigner;
1515
use util::test_utils;
1616

1717
use bitcoin::network::constants::Network;
18-
use bitcoin::secp256k1::{PublicKey, Secp256k1};
18+
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
1919

2020
use sync::Arc;
2121

@@ -105,3 +105,17 @@ fn three_blinded_hops() {
105105
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route)).unwrap();
106106
pass_along_path(nodes, None);
107107
}
108+
109+
#[test]
110+
fn too_big_packet_error() {
111+
// Make sure we error as expected if a packet is too big to send.
112+
let nodes = create_nodes(1);
113+
114+
let hop_secret = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
115+
let secp_ctx = Secp256k1::new();
116+
let hop_node_id = PublicKey::from_secret_key(&secp_ctx, &hop_secret);
117+
118+
let hops = [hop_node_id; 400];
119+
let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id)).unwrap_err();
120+
assert_eq!(err, SendError::TooBigPacket);
121+
}

lightning/src/onion_message/messenger.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ impl Destination {
108108
}
109109
}
110110

111+
/// Errors that may occur when [sending an onion message].
112+
///
113+
/// [sending an onion message]: OnionMessenger::send_onion_message
114+
#[derive(Debug, PartialEq)]
115+
pub enum SendError {
116+
/// Errored computing onion message packet keys.
117+
Secp256k1(secp256k1::Error),
118+
/// Because implementations such as Eclair will drop onion messages where the message packet
119+
/// exceeds 32834 bytes, we refuse to send messages where the packet exceeds this size.
120+
TooBigPacket,
121+
}
122+
111123
impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
112124
where K::Target: KeysInterface<Signer = Signer>,
113125
L::Target: Logger,
@@ -127,7 +139,7 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
127139

128140
/// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
129141
/// See [`OnionMessenger`] for example usage.
130-
pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], destination: Destination) -> Result<(), secp256k1::Error> {
142+
pub fn send_onion_message(&self, intermediate_nodes: &[PublicKey], destination: Destination) -> Result<(), SendError> {
131143
let blinding_secret_bytes = self.keys_manager.get_secure_random_bytes();
132144
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
133145
let (introduction_node_id, blinding_point) = if intermediate_nodes.len() != 0 {
@@ -140,10 +152,12 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
140152
}
141153
};
142154
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
143-
&self.secp_ctx, intermediate_nodes, destination, &blinding_secret)?;
155+
&self.secp_ctx, intermediate_nodes, destination, &blinding_secret)
156+
.map_err(|e| SendError::Secp256k1(e))?;
144157

145158
let prng_seed = self.keys_manager.get_secure_random_bytes();
146-
let onion_packet = construct_onion_message_packet(packet_payloads, packet_keys, prng_seed);
159+
let onion_packet = construct_onion_message_packet(
160+
packet_payloads, packet_keys, prng_seed).map_err(|()| SendError::TooBigPacket)?;
147161

148162
let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
149163
let pending_msgs = pending_per_peer_msgs.entry(introduction_node_id).or_insert(Vec::new());
@@ -343,7 +357,8 @@ fn packet_payloads_and_keys<T: secp256k1::Signing + secp256k1::Verification>(
343357
Ok((payloads, onion_packet_keys))
344358
}
345359

346-
fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec<onion_utils::OnionKeys>, prng_seed: [u8; 32]) -> Packet {
360+
/// Errors if the serialized payload size exceeds onion_message::BIG_PACKET_HOP_DATA_LEN
361+
fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec<onion_utils::OnionKeys>, prng_seed: [u8; 32]) -> Result<Packet, ()> {
347362
// Spec rationale:
348363
// "`len` allows larger messages to be sent than the standard 1300 bytes allowed for an HTLC
349364
// onion, but this should be used sparingly as it is reduces anonymity set, hence the
@@ -353,7 +368,8 @@ fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys
353368
SMALL_PACKET_HOP_DATA_LEN
354369
} else if payloads_ser_len <= BIG_PACKET_HOP_DATA_LEN {
355370
BIG_PACKET_HOP_DATA_LEN
356-
} else { payloads_ser_len };
371+
} else { return Err(()) };
357372

358-
onion_utils::construct_onion_message_packet::<_, _>(payloads, onion_keys, prng_seed, hop_data_len)
373+
Ok(onion_utils::construct_onion_message_packet::<_, _>(
374+
payloads, onion_keys, prng_seed, hop_data_len))
359375
}

lightning/src/onion_message/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ mod functional_tests;
2929

3030
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
3131
pub use self::blinded_route::{BlindedRoute, BlindedHop};
32-
pub use self::messenger::{Destination, OnionMessenger, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
32+
pub use self::messenger::{Destination, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3333
pub(crate) use self::packet::Packet;

0 commit comments

Comments
 (0)