use crate::sign::{NodeSigner, Recipient};
use crate::ln::features::InitFeatures;
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
-use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessenger, SendError};
+use super::{CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger, SendError};
use crate::util::ser::{Writeable, Writer};
use crate::util::test_utils;
let nodes = create_nodes(2);
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
- nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), test_msg, None).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::Node(nodes[1].get_node_pk()),
+ };
+ nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
pass_along_path(&nodes);
}
let nodes = create_nodes(3);
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
- nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk()], Destination::Node(nodes[2].get_node_pk()), test_msg, None).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![nodes[1].get_node_pk()],
+ destination: Destination::Node(nodes[2].get_node_pk()),
+ };
+ nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
pass_along_path(&nodes);
}
let secp_ctx = Secp256k1::new();
let blinded_path = BlindedPath::new_for_message(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![nodes[1].get_node_pk(), nodes[2].get_node_pk()],
+ destination: Destination::BlindedPath(blinded_path),
+ };
- nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedPath(blinded_path), test_msg, None).unwrap();
+ nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
pass_along_path(&nodes);
}
let secp_ctx = Secp256k1::new();
let blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ };
- nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), test_msg, None).unwrap();
+ nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
pass_along_path(&nodes);
}
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
let hop_node_id = nodes[1].get_node_pk();
- let hops = [hop_node_id; 400];
- let err = nodes[0].messenger.send_onion_message(&hops, Destination::Node(hop_node_id), test_msg, None).unwrap_err();
+ let hops = vec![hop_node_id; 400];
+ let path = OnionMessagePath {
+ intermediate_nodes: hops,
+ destination: Destination::Node(hop_node_id),
+ };
+ let err = nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap_err();
assert_eq!(err, SendError::TooBigPacket);
}
let secp_ctx = Secp256k1::new();
let blinded_path = BlindedPath::new_for_message(&[nodes[0].get_node_pk(), nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ };
- nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
+ nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
pass_along_path(&nodes);
// Try with a two-hop blinded path where we are the introduction node.
let blinded_path = BlindedPath::new_for_message(&[nodes[0].get_node_pk(), nodes[1].get_node_pk()], &*nodes[1].keys_manager, &secp_ctx).unwrap();
- nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg), None).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ };
+ nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), None).unwrap();
nodes.remove(2);
pass_along_path(&nodes);
}
let secp_ctx = Secp256k1::new();
let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
blinded_path.blinded_hops.clear();
- let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg.clone()), None).unwrap_err();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ };
+ let err = nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg.clone()), None).unwrap_err();
assert_eq!(err, SendError::TooFewBlindedHops);
// 1 hop
let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
blinded_path.blinded_hops.remove(0);
assert_eq!(blinded_path.blinded_hops.len(), 1);
- let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg), None).unwrap_err();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ };
+ let err = nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), None).unwrap_err();
assert_eq!(err, SendError::TooFewBlindedHops);
}
let secp_ctx = Secp256k1::new();
// Destination::Node
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![nodes[1].get_node_pk(), nodes[2].get_node_pk()],
+ destination: Destination::Node(nodes[3].get_node_pk()),
+ };
let reply_path = BlindedPath::new_for_message(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
- nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::Node(nodes[3].get_node_pk()), OnionMessageContents::Custom(test_msg.clone()), Some(reply_path)).unwrap();
+ nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg.clone()), Some(reply_path)).unwrap();
pass_along_path(&nodes);
// Make sure the last node successfully decoded the reply path.
nodes[3].logger.assert_log_contains(
// Destination::BlindedPath
let blinded_path = BlindedPath::new_for_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ };
let reply_path = BlindedPath::new_for_message(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
- nodes[0].messenger.send_onion_message(&[], Destination::BlindedPath(blinded_path), OnionMessageContents::Custom(test_msg), Some(reply_path)).unwrap();
+ nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), Some(reply_path)).unwrap();
pass_along_path(&nodes);
nodes[3].logger.assert_log_contains(
"lightning::onion_message::messenger",
}
let test_msg = OnionMessageContents::Custom(InvalidCustomMessage {});
- let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), test_msg, None).unwrap_err();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::Node(nodes[1].get_node_pk()),
+ };
+ let err = nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap_err();
assert_eq!(err, SendError::InvalidMessage);
}
fn peer_buffer_full() {
let nodes = create_nodes(2);
let test_msg = TestCustomMessage {};
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::Node(nodes[1].get_node_pk()),
+ };
for _ in 0..188 { // Based on MAX_PER_PEER_BUFFER_SIZE in OnionMessenger
- nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
+ nodes[0].messenger.send_onion_message(path.clone(), OnionMessageContents::Custom(test_msg.clone()), None).unwrap();
}
- let err = nodes[0].messenger.send_onion_message(&[], Destination::Node(nodes[1].get_node_pk()), OnionMessageContents::Custom(test_msg), None).unwrap_err();
+ let err = nodes[0].messenger.send_onion_message(path, OnionMessageContents::Custom(test_msg), None).unwrap_err();
assert_eq!(err, SendError::BufferFull);
}
let nodes = create_nodes(num_nodes as u8);
let test_msg = OnionMessageContents::Custom(TestCustomMessage {});
- let mut intermediates = vec![];
+ let mut intermediate_nodes = vec![];
for i in 1..(num_nodes-1) {
- intermediates.push(nodes[i].get_node_pk());
+ intermediate_nodes.push(nodes[i].get_node_pk());
}
- nodes[0].messenger.send_onion_message(&intermediates, Destination::Node(nodes[num_nodes-1].get_node_pk()), test_msg, None).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes,
+ destination: Destination::Node(nodes[num_nodes-1].get_node_pk()),
+ };
+ nodes[0].messenger.send_onion_message(path, test_msg, None).unwrap();
pass_along_path(&nodes);
}
/// # use lightning::blinded_path::BlindedPath;
/// # use lightning::sign::KeysManager;
/// # use lightning::ln::peer_handler::IgnoringMessageHandler;
-/// # use lightning::onion_message::{CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessenger};
+/// # use lightning::onion_message::{CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessagePath, OnionMessenger};
/// # use lightning::util::logger::{Logger, Record};
/// # use lightning::util::ser::{Writeable, Writer};
/// # use lightning::io;
/// }
/// }
/// // Send a custom onion message to a node id.
-/// let intermediate_hops = [hop_node_id1, hop_node_id2];
+/// let path = OnionMessagePath {
+/// intermediate_nodes: vec![hop_node_id1, hop_node_id2],
+/// destination: Destination::Node(destination_node_id),
+/// };
/// let reply_path = None;
/// # let your_custom_message = YourCustomMessage {};
/// let message = OnionMessageContents::Custom(your_custom_message);
-/// onion_messenger.send_onion_message(&intermediate_hops, Destination::Node(destination_node_id), message, reply_path);
+/// onion_messenger.send_onion_message(path, message, reply_path);
///
/// // Create a blinded path to yourself, for someone to send an onion message to.
/// # let your_node_id = hop_node_id1;
/// let blinded_path = BlindedPath::new_for_message(&hops, &keys_manager, &secp_ctx).unwrap();
///
/// // Send a custom onion message to a blinded path.
-/// # let intermediate_hops = [hop_node_id1, hop_node_id2];
+/// let path = OnionMessagePath {
+/// intermediate_nodes: vec![hop_node_id1, hop_node_id2],
+/// destination: Destination::BlindedPath(blinded_path),
+/// };
/// let reply_path = None;
/// # let your_custom_message = YourCustomMessage {};
/// let message = OnionMessageContents::Custom(your_custom_message);
-/// onion_messenger.send_onion_message(&intermediate_hops, Destination::BlindedPath(blinded_path), message, reply_path);
+/// onion_messenger.send_onion_message(path, message, reply_path);
/// ```
///
/// [offers]: <https://github.com/lightning/bolts/pull/798>
custom_handler: CMH,
}
+/// A path for sending an [`msgs::OnionMessage`].
+#[derive(Clone)]
+pub struct OnionMessagePath {
+ /// Nodes on the path between the sender and the destination.
+ pub intermediate_nodes: Vec<PublicKey>,
+
+ /// The recipient of the message.
+ pub destination: Destination,
+}
+
/// The destination of an onion message.
+#[derive(Clone)]
pub enum Destination {
/// We're sending this onion message to a node.
Node(PublicKey),
}
}
- /// Send an onion message with contents `message` to `destination`, routing it through `intermediate_nodes`.
+ /// Send an onion message with contents `message` to the destination of `path`.
+ ///
/// See [`OnionMessenger`] for example usage.
- pub fn send_onion_message<T: CustomOnionMessageContents>(&self, intermediate_nodes: &[PublicKey], mut destination: Destination, message: OnionMessageContents<T>, reply_path: Option<BlindedPath>) -> Result<(), SendError> {
+ pub fn send_onion_message<T: CustomOnionMessageContents>(
+ &self, path: OnionMessagePath, message: OnionMessageContents<T>,
+ reply_path: Option<BlindedPath>
+ ) -> Result<(), SendError> {
+ let OnionMessagePath { intermediate_nodes, mut destination } = path;
if let Destination::BlindedPath(BlindedPath { ref blinded_hops, .. }) = destination {
if blinded_hops.len() < 2 {
return Err(SendError::TooFewBlindedHops);
}
};
let (packet_payloads, packet_keys) = packet_payloads_and_keys(
- &self.secp_ctx, intermediate_nodes, destination, message, reply_path, &blinding_secret)
+ &self.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();