Skip to content

Pub make onion #2583

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lightning/src/ln/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,8 @@ pub struct UpdateAddHTLC {
pub struct OnionMessage {
/// Used in decrypting the onion packet's payload.
pub blinding_point: PublicKey,
pub(crate) onion_routing_packet: onion_message::Packet,
/// The full onion packet including hop data, pubkey, and hmac
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, docs should end in periods (particularly public docs)

pub onion_routing_packet: onion_message::Packet,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't (actually) public because Packet isn't pub (its only pub from a private module). You'll need to make the packet module pub.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packet was already exported from the mod.rs as pub(crate), so I just made it pub and added doc comments

}

/// An [`update_fulfill_htlc`] message to be sent to or received from a peer.
Expand Down
57 changes: 41 additions & 16 deletions lightning/src/onion_message/messenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,36 @@ where
&self, path: OnionMessagePath, message: OnionMessageContents<T>,
reply_path: Option<BlindedPath>
) -> Result<(), SendError> {
let (introduction_node_id, onion_msg) = Self::create_onion_message(
&self.entropy_source,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You have whitespace hanging off the end of line here and a few other places. This should be highlighted by a local git show depending on your terminal settings.

&self.node_signer,
&self.secp_ctx,
path,
message,
reply_path
)?;

let mut pending_per_peer_msgs = self.pending_messages.lock().unwrap();
if outbound_buffer_full(&introduction_node_id, &pending_per_peer_msgs) { return Err(SendError::BufferFull) }
match pending_per_peer_msgs.entry(introduction_node_id) {
hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
hash_map::Entry::Occupied(mut e) => {
e.get_mut().push_back(onion_msg);
Ok(())
}
}
}

/// Create an onion message with contents `message` to the destination of `path`.
/// Returns (introduction_node_id, onion_msg)
pub fn create_onion_message<T: CustomOnionMessageContents>(
entropy_source: &ES,
node_signer: &NS,
secp_ctx: &Secp256k1<secp256k1::All>,
path: OnionMessagePath,
message: OnionMessageContents<T>,
reply_path: Option<BlindedPath>,
) -> Result<(PublicKey, msgs::OnionMessage), SendError> {
let OnionMessagePath { intermediate_nodes, mut destination } = path;
if let Destination::BlindedPath(BlindedPath { ref blinded_hops, .. }) = destination {
if blinded_hops.len() < 2 {
Expand All @@ -296,43 +326,38 @@ where
// advance the blinded path by 1 hop so the second hop is the new introduction node.
if intermediate_nodes.len() == 0 {
if let Destination::BlindedPath(ref mut blinded_path) = destination {
let our_node_id = self.node_signer.get_node_id(Recipient::Node)
let our_node_id = node_signer.get_node_id(Recipient::Node)
.map_err(|()| SendError::GetNodeIdFailed)?;
if blinded_path.introduction_node_id == our_node_id {
advance_path_by_one(blinded_path, &self.node_signer, &self.secp_ctx)
advance_path_by_one(blinded_path, node_signer, &secp_ctx)
.map_err(|()| SendError::BlindedPathAdvanceFailed)?;
}
}
}

let blinding_secret_bytes = self.entropy_source.get_secure_random_bytes();
let blinding_secret_bytes = entropy_source.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 {
(intermediate_nodes[0], PublicKey::from_secret_key(&self.secp_ctx, &blinding_secret))
(intermediate_nodes[0], PublicKey::from_secret_key(&secp_ctx, &blinding_secret))
} else {
match destination {
Destination::Node(pk) => (pk, PublicKey::from_secret_key(&self.secp_ctx, &blinding_secret)),
Destination::Node(pk) => (pk, PublicKey::from_secret_key(&secp_ctx, &blinding_secret)),
Destination::BlindedPath(BlindedPath { introduction_node_id, blinding_point, .. }) =>
(introduction_node_id, blinding_point),
}
};
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
&self.secp_ctx, &intermediate_nodes, destination, message, reply_path, &blinding_secret)
&secp_ctx, &intermediate_nodes, destination, message, reply_path, &blinding_secret)
.map_err(|e| SendError::Secp256k1(e))?;

let prng_seed = self.entropy_source.get_secure_random_bytes();
let prng_seed = entropy_source.get_secure_random_bytes();
let onion_routing_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();
if outbound_buffer_full(&introduction_node_id, &pending_per_peer_msgs) { return Err(SendError::BufferFull) }
match pending_per_peer_msgs.entry(introduction_node_id) {
hash_map::Entry::Vacant(_) => Err(SendError::InvalidFirstHop),
hash_map::Entry::Occupied(mut e) => {
e.get_mut().push_back(msgs::OnionMessage { blinding_point, onion_routing_packet });
Ok(())
}
}
Ok((introduction_node_id, msgs::OnionMessage {
blinding_point,
onion_routing_packet
}))
}

fn respond_with_onion_message<T: CustomOnionMessageContents>(
Expand Down
3 changes: 2 additions & 1 deletion lightning/src/onion_message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ mod functional_tests;
// Re-export structs so they can be imported with just the `onion_message::` module prefix.
pub use self::messenger::{CustomOnionMessageContents, CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError, SimpleArcOnionMessenger, SimpleRefOnionMessenger};
pub use self::offers::{OffersMessage, OffersMessageHandler};
pub(crate) use self::packet::{ControlTlvs, Packet};
pub use self::packet::Packet;
pub(crate) use self::packet::ControlTlvs;
16 changes: 11 additions & 5 deletions lightning/src/onion_message/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,22 @@ use crate::prelude::*;
pub(super) const SMALL_PACKET_HOP_DATA_LEN: usize = 1300;
pub(super) const BIG_PACKET_HOP_DATA_LEN: usize = 32768;

/// Packet of hop data for next peer
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct Packet {
pub(super) version: u8,
pub(super) public_key: PublicKey,
pub struct Packet {
/// Bolt 04 version number
pub version: u8,
/// A random sepc256k1 point, used to build the ECDH shared secret to decrypt hop_data
pub public_key: PublicKey,
/// Encrypted payload for the next hop
//
// Unlike the onion packets used for payments, onion message packets can have payloads greater
// than 1300 bytes.
// TODO: if 1300 ends up being the most common size, optimize this to be:
// enum { ThirteenHundred([u8; 1300]), VarLen(Vec<u8>) }
pub(super) hop_data: Vec<u8>,
pub(super) hmac: [u8; 32],
pub hop_data: Vec<u8>,
/// HMAC to verify the integrity of hop_data
pub hmac: [u8; 32],
}

impl onion_utils::Packet for Packet {
Expand Down