+ let test_msg = TestCustomMessage::Response;
+
+ let secp_ctx = Secp256k1::new();
+ let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], &*nodes[3].entropy_source, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ first_node_addresses: None,
+ };
+
+ nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap();
+ nodes[3].custom_message_handler.expect_message(TestCustomMessage::Response);
+ pass_along_path(&nodes);
+}
+
+#[test]
+fn too_big_packet_error() {
+ // Make sure we error as expected if a packet is too big to send.
+ let nodes = create_nodes(2);
+ let test_msg = TestCustomMessage::Response;
+
+ let hop_node_id = nodes[1].node_id;
+ let hops = vec![hop_node_id; 400];
+ let path = OnionMessagePath {
+ intermediate_nodes: hops,
+ destination: Destination::Node(hop_node_id),
+ first_node_addresses: None,
+ };
+ let err = nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap_err();
+ assert_eq!(err, SendError::TooBigPacket);
+}
+
+#[test]
+fn we_are_intro_node() {
+ // If we are sending straight to a blinded path and we are the introduction node, we need to
+ // advance the blinded path by 1 hop so the second hop is the new introduction node.
+ let mut nodes = create_nodes(3);
+ let test_msg = TestCustomMessage::Response;
+
+ let secp_ctx = Secp256k1::new();
+ let blinded_path = BlindedPath::new_for_message(&[nodes[0].node_id, nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ first_node_addresses: None,
+ };
+
+ nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), None).unwrap();
+ nodes[2].custom_message_handler.expect_message(TestCustomMessage::Response);
+ 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].node_id, nodes[1].node_id], &*nodes[1].entropy_source, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ first_node_addresses: None,
+ };
+ nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap();
+ nodes[1].custom_message_handler.expect_message(TestCustomMessage::Response);
+ nodes.remove(2);
+ pass_along_path(&nodes);
+}
+
+#[test]
+fn invalid_blinded_path_error() {
+ // Make sure we error as expected if a provided blinded path has 0 or 1 hops.
+ let nodes = create_nodes(3);
+ let test_msg = TestCustomMessage::Response;
+
+ // 0 hops
+ let secp_ctx = Secp256k1::new();
+ let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx).unwrap();
+ blinded_path.blinded_hops.clear();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ first_node_addresses: None,
+ };
+ let err = nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), None).unwrap_err();
+ assert_eq!(err, SendError::TooFewBlindedHops);
+}
+
+#[test]
+fn reply_path() {
+ let mut nodes = create_nodes(4);
+ let test_msg = TestCustomMessage::Request;
+ let secp_ctx = Secp256k1::new();
+
+ // Destination::Node
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id],
+ destination: Destination::Node(nodes[3].node_id),
+ first_node_addresses: None,
+ };
+ let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], &*nodes[0].entropy_source, &secp_ctx).unwrap();
+ nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)).unwrap();
+ nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request);
+ pass_along_path(&nodes);
+ // Make sure the last node successfully decoded the reply path.
+ nodes[0].custom_message_handler.expect_message(TestCustomMessage::Response);
+ nodes.reverse();
+ pass_along_path(&nodes);
+
+ // Destination::BlindedPath
+ let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], &*nodes[3].entropy_source, &secp_ctx).unwrap();
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::BlindedPath(blinded_path),
+ first_node_addresses: None,
+ };
+ let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], &*nodes[0].entropy_source, &secp_ctx).unwrap();
+
+ nodes[0].messenger.send_onion_message_using_path(path, test_msg, Some(reply_path)).unwrap();
+ nodes[3].custom_message_handler.expect_message(TestCustomMessage::Request);
+ pass_along_path(&nodes);
+
+ // Make sure the last node successfully decoded the reply path.
+ nodes[0].custom_message_handler.expect_message(TestCustomMessage::Response);
+ nodes.reverse();
+ pass_along_path(&nodes);
+}
+
+#[test]
+fn invalid_custom_message_type() {
+ let nodes = create_nodes(2);
+
+ #[derive(Debug)]
+ struct InvalidCustomMessage{}
+ impl OnionMessageContents for InvalidCustomMessage {
+ fn tlv_type(&self) -> u64 {
+ // Onion message contents must have a TLV >= 64.
+ 63
+ }
+ }
+
+ impl Writeable for InvalidCustomMessage {
+ fn write<W: Writer>(&self, _w: &mut W) -> Result<(), io::Error> { unreachable!() }
+ }
+
+ let test_msg = InvalidCustomMessage {};
+ let path = OnionMessagePath {
+ intermediate_nodes: vec![],
+ destination: Destination::Node(nodes[1].node_id),
+ first_node_addresses: None,
+ };
+ let err = nodes[0].messenger.send_onion_message_using_path(path, test_msg, None).unwrap_err();
+ assert_eq!(err, SendError::InvalidMessage);
+}