X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fblinded_path%2Fmessage.rs;h=3a5541fa1468272f3859972bca2cdfb4f8053ee8;hb=ab4b87209886569ba94df10ee27dccf9c0562d05;hp=024fb451d00a78d1fe42a0524b042cfe3f42b9ec;hpb=381cc646c66538f69599ae4ee1224783eb5abe6a;p=rust-lightning diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index 024fb451..3a5541fa 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -1,9 +1,18 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; -use crate::blinded_path::BlindedHop; + +use crate::blinded_path::{BlindedHop, BlindedPath}; use crate::blinded_path::utils; use crate::io; +use crate::io::Cursor; +use crate::ln::onion_utils; +use crate::onion_message::packet::ControlTlvs; use crate::prelude::*; -use crate::util::ser::{Writeable, Writer}; +use crate::sign::{NodeSigner, Recipient}; +use crate::crypto::streams::ChaChaPolyReadAdapter; +use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer}; + +use core::mem; +use core::ops::Deref; /// TLVs to encode in an intermediate onion message packet's hop data. When provided in a blinded /// route, they are encoded into [`BlindedHop::encrypted_payload`]. @@ -48,32 +57,41 @@ impl Writeable for ReceiveTlvs { pub(super) fn blinded_hops( secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], session_priv: &SecretKey ) -> Result, secp256k1::Error> { - let mut blinded_hops = Vec::with_capacity(unblinded_path.len()); - - let mut prev_ss_and_blinded_node_id = None; - utils::construct_keys_callback(secp_ctx, unblinded_path, None, session_priv, |blinded_node_id, _, _, encrypted_payload_ss, unblinded_pk, _| { - if let Some((prev_ss, prev_blinded_node_id)) = prev_ss_and_blinded_node_id { - if let Some(pk) = unblinded_pk { - let payload = ForwardTlvs { - next_node_id: pk, - next_blinding_override: None, - }; - blinded_hops.push(BlindedHop { - blinded_node_id: prev_blinded_node_id, - encrypted_payload: utils::encrypt_payload(payload, prev_ss), - }); - } else { debug_assert!(false); } - } - prev_ss_and_blinded_node_id = Some((encrypted_payload_ss, blinded_node_id)); - })?; + let blinded_tlvs = unblinded_path.iter() + .skip(1) // The first node's TLVs contains the next node's pubkey + .map(|pk| { + ControlTlvs::Forward(ForwardTlvs { next_node_id: *pk, next_blinding_override: None }) + }) + .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None }))); - if let Some((final_ss, final_blinded_node_id)) = prev_ss_and_blinded_node_id { - let final_payload = ReceiveTlvs { path_id: None }; - blinded_hops.push(BlindedHop { - blinded_node_id: final_blinded_node_id, - encrypted_payload: utils::encrypt_payload(final_payload, final_ss), - }); - } else { debug_assert!(false) } + utils::construct_blinded_hops(secp_ctx, unblinded_path.iter(), blinded_tlvs, session_priv) +} - Ok(blinded_hops) +// Advance the blinded onion message path by one hop, so make the second hop into the new +// introduction node. +pub(crate) fn advance_path_by_one( + path: &mut BlindedPath, node_signer: &NS, secp_ctx: &Secp256k1 +) -> Result<(), ()> where NS::Target: NodeSigner { + let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?; + let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes()); + let encrypted_control_tlvs = path.blinded_hops.remove(0).encrypted_payload; + let mut s = Cursor::new(&encrypted_control_tlvs); + let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64); + match ChaChaPolyReadAdapter::read(&mut reader, rho) { + Ok(ChaChaPolyReadAdapter { readable: ControlTlvs::Forward(ForwardTlvs { + mut next_node_id, next_blinding_override, + })}) => { + let mut new_blinding_point = match next_blinding_override { + Some(blinding_point) => blinding_point, + None => { + onion_utils::next_hop_pubkey(secp_ctx, path.blinding_point, + control_tlvs_ss.as_ref()).map_err(|_| ())? + } + }; + mem::swap(&mut path.blinding_point, &mut new_blinding_point); + mem::swap(&mut path.introduction_node_id, &mut next_node_id); + Ok(()) + }, + _ => Err(()) + } }