X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fblinded_path%2Fmessage.rs;h=bdbb4be4541d2ce8f3aa34840263de963b23ec57;hb=07d991c82fadf10f59ae01b2b5aef6bc8797fd9a;hp=9a282a5f87d42658599870dd7446d5eef2e1ea5c;hpb=74c9f9b1832fdb2f6e85af12d27cfaab9fe14154;p=rust-lightning diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index 9a282a5f..bdbb4be4 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -1,3 +1,16 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Data structures and methods for constructing [`BlindedPath`]s to send a message over. +//! +//! [`BlindedPath`]: crate::blinded_path::BlindedPath + use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; #[allow(unused_imports)] @@ -16,6 +29,17 @@ use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer} use core::mem; use core::ops::Deref; +/// An intermediate node, and possibly a short channel id leading to the next node. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +pub struct ForwardNode { + /// This node's pubkey. + pub node_id: PublicKey, + /// The channel between `node_id` and the next hop. If set, the constructed [`BlindedHop`]'s + /// `encrypted_payload` will use this instead of the next [`ForwardNode::node_id`] for a more + /// compact representation. + pub short_channel_id: Option, +} + /// 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`]. pub(crate) struct ForwardTlvs { @@ -60,21 +84,30 @@ impl Writeable for ReceiveTlvs { } } -/// Construct blinded onion message hops for the given `unblinded_path`. +/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`. pub(super) fn blinded_hops( - secp_ctx: &Secp256k1, unblinded_path: &[PublicKey], session_priv: &SecretKey + secp_ctx: &Secp256k1, intermediate_nodes: &[ForwardNode], recipient_node_id: PublicKey, + session_priv: &SecretKey ) -> Result, secp256k1::Error> { - let blinded_tlvs = unblinded_path.iter() + let pks = intermediate_nodes.iter().map(|node| &node.node_id) + .chain(core::iter::once(&recipient_node_id)); + let tlvs = pks.clone() .skip(1) // The first node's TLVs contains the next node's pubkey - .map(|pk| ForwardTlvs { next_hop: NextMessageHop::NodeId(*pk), next_blinding_override: None }) - .map(|tlvs| ControlTlvs::Forward(tlvs)) + .zip(intermediate_nodes.iter().map(|node| node.short_channel_id)) + .map(|(pubkey, scid)| match scid { + Some(scid) => NextMessageHop::ShortChannelId(scid), + None => NextMessageHop::NodeId(*pubkey), + }) + .map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None })) .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None }))); - utils::construct_blinded_hops(secp_ctx, unblinded_path.iter(), blinded_tlvs, session_priv) + utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv) } // Advance the blinded onion message path by one hop, so make the second hop into the new // introduction node. +// +// Will only modify `path` when returning `Ok`. pub(crate) fn advance_path_by_one( path: &mut BlindedPath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1 ) -> Result<(), ()> @@ -85,8 +118,8 @@ where { 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 encrypted_control_tlvs = &path.blinded_hops.get(0).ok_or(())?.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 { @@ -108,6 +141,7 @@ where }; mem::swap(&mut path.blinding_point, &mut new_blinding_point); path.introduction_node = IntroductionNode::NodeId(next_node_id); + path.blinded_hops.remove(0); Ok(()) }, _ => Err(())