Support sending onion messages
[rust-lightning] / lightning / src / onion_message / utils.rs
index 785a373caa4c80d7783dc062208af9da28e087b3..9b95183e74bb8bc549ca0a6f252522ae80e050f7 100644 (file)
@@ -16,14 +16,16 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
 use bitcoin::secp256k1::ecdh::SharedSecret;
 
 use ln::onion_utils;
+use super::blinded_route::BlindedRoute;
+use super::messenger::Destination;
 
 use prelude::*;
 
 // TODO: DRY with onion_utils::construct_onion_keys_callback
 #[inline]
 pub(super) fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verification,
-       FType: FnMut(PublicKey, SharedSecret, PublicKey, [u8; 32], Option<PublicKey>)>(
-       secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey],
+       FType: FnMut(PublicKey, SharedSecret, PublicKey, [u8; 32], Option<PublicKey>, Option<Vec<u8>>)>(
+       secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], destination: Option<Destination>,
        session_priv: &SecretKey, mut callback: FType
 ) -> Result<(), secp256k1::Error> {
        let mut msg_blinding_point_priv = session_priv.clone();
@@ -32,7 +34,7 @@ pub(super) fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verific
        let mut onion_packet_pubkey = msg_blinding_point.clone();
 
        macro_rules! build_keys {
-               ($pk: expr, $blinded: expr) => {
+               ($pk: expr, $blinded: expr, $encrypted_payload: expr) => {{
                        let encrypted_data_ss = SharedSecret::new(&$pk, &msg_blinding_point_priv);
 
                        let blinded_hop_pk = if $blinded { $pk } else {
@@ -49,7 +51,14 @@ pub(super) fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verific
 
                        let rho = onion_utils::gen_rho_from_shared_secret(encrypted_data_ss.as_ref());
                        let unblinded_pk_opt = if $blinded { None } else { Some($pk) };
-                       callback(blinded_hop_pk, onion_packet_ss, onion_packet_pubkey, rho, unblinded_pk_opt);
+                       callback(blinded_hop_pk, onion_packet_ss, onion_packet_pubkey, rho, unblinded_pk_opt, $encrypted_payload);
+                       (encrypted_data_ss, onion_packet_ss)
+               }}
+       }
+
+       macro_rules! build_keys_in_loop {
+               ($pk: expr, $blinded: expr, $encrypted_payload: expr) => {
+                       let (encrypted_data_ss, onion_packet_ss) = build_keys!($pk, $blinded, $encrypted_payload);
 
                        let msg_blinding_point_blinding_factor = {
                                let mut sha = Sha256::engine();
@@ -73,7 +82,19 @@ pub(super) fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verific
        }
 
        for pk in unblinded_path {
-               build_keys!(*pk, false);
+               build_keys_in_loop!(*pk, false, None);
+       }
+       if let Some(dest) = destination {
+               match dest {
+                       Destination::Node(pk) => {
+                               build_keys!(pk, false, None);
+                       },
+                       Destination::BlindedRoute(BlindedRoute { blinded_hops, .. }) => {
+                               for hop in blinded_hops {
+                                       build_keys_in_loop!(hop.blinded_node_id, true, Some(hop.encrypted_payload));
+                               }
+                       },
+               }
        }
        Ok(())
 }