Skip to content

Commit 059e39c

Browse files
Add SendError enum for onion messages and error on too-big packets
1 parent 0078878 commit 059e39c

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
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

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

lightning/src/onion_message/messenger.rs

Lines changed: 23 additions & 8 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,
@@ -126,7 +138,7 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
126138
}
127139

128140
/// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
129-
pub fn send_onion_message(&self, intermediate_nodes: Vec<PublicKey>, destination: Destination) -> Result<(), secp256k1::Error> {
141+
pub fn send_onion_message(&self, intermediate_nodes: Vec<PublicKey>, destination: Destination) -> Result<(), SendError> {
130142
let blinding_secret_bytes = self.keys_manager.get_secure_random_bytes();
131143
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
132144
let (introduction_node_id, blinding_point) = if intermediate_nodes.len() != 0 {
@@ -139,11 +151,13 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
139151
}
140152
};
141153
let (control_tlvs_keys, onion_packet_keys) = construct_sending_keys(
142-
&self.secp_ctx, &intermediate_nodes, &destination, &blinding_secret)?;
154+
&self.secp_ctx, &intermediate_nodes, &destination, &blinding_secret)
155+
.map_err(|e| SendError::Secp256k1(e))?;
143156
let payloads = build_payloads(intermediate_nodes, destination, control_tlvs_keys);
144157

145158
let prng_seed = self.keys_manager.get_secure_random_bytes();
146-
let onion_packet = construct_onion_message_packet(payloads, onion_packet_keys, prng_seed);
159+
let onion_packet = construct_onion_message_packet(
160+
payloads, onion_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());
@@ -359,19 +373,20 @@ fn build_payloads(intermediate_nodes: Vec<PublicKey>, destination: Destination,
359373
payloads
360374
}
361375

362-
fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec<onion_utils::OnionKeys>, prng_seed: [u8; 32]) -> Packet {
363-
let payloads_serialized_len = payloads.iter().map(|p| p.serialized_length() + 32 /* HMAC */).sum();
376+
/// Errors if the serialized payload size exceeds onion_message::BIG_PACKET_HOP_DATA_LEN
377+
fn construct_onion_message_packet(payloads: Vec<(Payload, [u8; 32])>, onion_keys: Vec<onion_utils::OnionKeys>, prng_seed: [u8; 32]) -> Result<Packet, ()> {
378+
let payloads_serialized_len: usize = payloads.iter().map(|p| p.serialized_length() + 32 /* HMAC */).sum();
364379
let hop_data_len = if payloads_serialized_len <= SMALL_PACKET_HOP_DATA_LEN {
365380
SMALL_PACKET_HOP_DATA_LEN
366381
} else if payloads_serialized_len <= BIG_PACKET_HOP_DATA_LEN {
367382
BIG_PACKET_HOP_DATA_LEN
368-
} else { payloads_serialized_len };
383+
} else { return Err(()) };
369384

370385
let mut packet_data = vec![0; hop_data_len];
371386

372387
let mut chacha = ChaCha20::new(&prng_seed, &[0; 8]);
373388
chacha.process_in_place(&mut packet_data);
374389

375-
onion_utils::construct_onion_packet_with_init_noise::<_, _>(
376-
payloads, onion_keys, packet_data, None)
390+
Ok(onion_utils::construct_onion_packet_with_init_noise::<_, _>(
391+
payloads, onion_keys, packet_data, None))
377392
}

lightning/src/onion_message/mod.rs

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

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

0 commit comments

Comments
 (0)