Skip to content

Commit ce74634

Browse files
authored
Merge pull request #2583 from Evanfeenstra/pub-make-onion
Pub make onion
2 parents 0e83e91 + 30b74a6 commit ce74634

File tree

4 files changed

+56
-23
lines changed

4 files changed

+56
-23
lines changed

lightning/src/ln/msgs.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,8 @@ pub struct UpdateAddHTLC {
631631
pub struct OnionMessage {
632632
/// Used in decrypting the onion packet's payload.
633633
pub blinding_point: PublicKey,
634-
pub(crate) onion_routing_packet: onion_message::Packet,
634+
/// The full onion packet including hop data, pubkey, and hmac
635+
pub onion_routing_packet: onion_message::Packet,
635636
}
636637

637638
/// An [`update_fulfill_htlc`] message to be sent to or received from a peer.

lightning/src/onion_message/messenger.rs

+41-16
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,36 @@ where
283283
&self, path: OnionMessagePath, message: OnionMessageContents<T>,
284284
reply_path: Option<BlindedPath>
285285
) -> Result<(), SendError> {
286+
let (introduction_node_id, onion_msg) = Self::create_onion_message(
287+
&self.entropy_source,
288+
&self.node_signer,
289+
&self.secp_ctx,
290+
path,
291+
message,
292+
reply_path
293+
)?;
294+
295+
let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
296+
if outbound_buffer_full(&introduction_node_id, &pending_per_peer_msgs) { return Err(SendError::BufferFull) }
297+
match pending_per_peer_msgs.entry(introduction_node_id) {
298+
hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
299+
hash_map::Entry::Occupied(mut e) => {
300+
e.get_mut().push_back(onion_msg);
301+
Ok(())
302+
}
303+
}
304+
}
305+
306+
/// Create an onion message with contents `message` to the destination of `path`.
307+
/// Returns (introduction_node_id, onion_msg)
308+
pub fn create_onion_message<T: CustomOnionMessageContents>(
309+
entropy_source: &ES,
310+
node_signer: &NS,
311+
secp_ctx: &Secp256k1<secp256k1::All>,
312+
path: OnionMessagePath,
313+
message: OnionMessageContents<T>,
314+
reply_path: Option<BlindedPath>,
315+
) -> Result<(PublicKey, msgs::OnionMessage), SendError> {
286316
let OnionMessagePath { intermediate_nodes, mut destination } = path;
287317
if let Destination::BlindedPath(BlindedPath { ref blinded_hops, .. }) = destination {
288318
if blinded_hops.len() < 2 {
@@ -296,43 +326,38 @@ where
296326
// advance the blinded path by 1 hop so the second hop is the new introduction node.
297327
if intermediate_nodes.len() == 0 {
298328
if let Destination::BlindedPath(ref mut blinded_path) = destination {
299-
let our_node_id = self.node_signer.get_node_id(Recipient::Node)
329+
let our_node_id = node_signer.get_node_id(Recipient::Node)
300330
.map_err(|()| SendError::GetNodeIdFailed)?;
301331
if blinded_path.introduction_node_id == our_node_id {
302-
advance_path_by_one(blinded_path, &self.node_signer, &self.secp_ctx)
332+
advance_path_by_one(blinded_path, node_signer, &secp_ctx)
303333
.map_err(|()| SendError::BlindedPathAdvanceFailed)?;
304334
}
305335
}
306336
}
307337

308-
let blinding_secret_bytes = self.entropy_source.get_secure_random_bytes();
338+
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
309339
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
310340
let (introduction_node_id, blinding_point) = if intermediate_nodes.len() != 0 {
311-
(intermediate_nodes[0], PublicKey::from_secret_key(&self.secp_ctx, &blinding_secret))
341+
(intermediate_nodes[0], PublicKey::from_secret_key(&secp_ctx, &blinding_secret))
312342
} else {
313343
match destination {
314-
Destination::Node(pk) => (pk, PublicKey::from_secret_key(&self.secp_ctx, &blinding_secret)),
344+
Destination::Node(pk) => (pk, PublicKey::from_secret_key(&secp_ctx, &blinding_secret)),
315345
Destination::BlindedPath(BlindedPath { introduction_node_id, blinding_point, .. }) =>
316346
(introduction_node_id, blinding_point),
317347
}
318348
};
319349
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
320-
&self.secp_ctx, &intermediate_nodes, destination, message, reply_path, &blinding_secret)
350+
&secp_ctx, &intermediate_nodes, destination, message, reply_path, &blinding_secret)
321351
.map_err(|e| SendError::Secp256k1(e))?;
322352

323-
let prng_seed = self.entropy_source.get_secure_random_bytes();
353+
let prng_seed = entropy_source.get_secure_random_bytes();
324354
let onion_routing_packet = construct_onion_message_packet(
325355
packet_payloads, packet_keys, prng_seed).map_err(|()| SendError::TooBigPacket)?;
326356

327-
let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
328-
if outbound_buffer_full(&introduction_node_id, &pending_per_peer_msgs) { return Err(SendError::BufferFull) }
329-
match pending_per_peer_msgs.entry(introduction_node_id) {
330-
hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
331-
hash_map::Entry::Occupied(mut e) => {
332-
e.get_mut().push_back(msgs::OnionMessage { blinding_point, onion_routing_packet });
333-
Ok(())
334-
}
335-
}
357+
Ok((introduction_node_id, msgs::OnionMessage {
358+
blinding_point,
359+
onion_routing_packet
360+
}))
336361
}
337362

338363
fn respond_with_onion_message<T: CustomOnionMessageContents>(

lightning/src/onion_message/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ mod functional_tests;
2929
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
3030
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
3131
pub use self::offers::{OffersMessage, OffersMessageHandler};
32-
pub(crate) use self::packet::{ControlTlvs, Packet};
32+
pub use self::packet::Packet;
33+
pub(crate) use self::packet::ControlTlvs;

lightning/src/onion_message/packet.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,22 @@ use crate::prelude::*;
3232
pub(super) const SMALL_PACKET_HOP_DATA_LEN: usize = 1300;
3333
pub(super) const BIG_PACKET_HOP_DATA_LEN: usize = 32768;
3434

35+
/// Packet of hop data for next peer
3536
#[derive(Clone, Debug, PartialEq, Eq)]
36-
pub(crate) struct Packet {
37-
pub(super) version: u8,
38-
pub(super) public_key: PublicKey,
37+
pub struct Packet {
38+
/// Bolt 04 version number
39+
pub version: u8,
40+
/// A random sepc256k1 point, used to build the ECDH shared secret to decrypt hop_data
41+
pub public_key: PublicKey,
42+
/// Encrypted payload for the next hop
43+
//
3944
// Unlike the onion packets used for payments, onion message packets can have payloads greater
4045
// than 1300 bytes.
4146
// TODO: if 1300 ends up being the most common size, optimize this to be:
4247
// enum { ThirteenHundred([u8; 1300]), VarLen(Vec<u8>) }
43-
pub(super) hop_data: Vec<u8>,
44-
pub(super) hmac: [u8; 32],
48+
pub hop_data: Vec<u8>,
49+
/// HMAC to verify the integrity of hop_data
50+
pub hmac: [u8; 32],
4551
}
4652

4753
impl onion_utils::Packet for Packet {

0 commit comments

Comments
 (0)