1f3f5a1fa38e70bdac2c7d01923fa06e04513f2e
[rust-lightning] / lightning / src / blinded_path / message.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! Data structures and methods for constructing [`BlindedPath`]s to send a message over.
11 //!
12 //! [`BlindedPath`]: crate::blinded_path::BlindedPath
13
14 use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
15
16 #[allow(unused_imports)]
17 use crate::prelude::*;
18
19 use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp};
20 use crate::blinded_path::utils;
21 use crate::io;
22 use crate::io::Cursor;
23 use crate::ln::onion_utils;
24 use crate::onion_message::packet::ControlTlvs;
25 use crate::sign::{NodeSigner, Recipient};
26 use crate::crypto::streams::ChaChaPolyReadAdapter;
27 use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
28
29 use core::mem;
30 use core::ops::Deref;
31
32 /// An intermediate node, and possibly a short channel id leading to the next node.
33 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
34 pub struct ForwardNode {
35         /// This node's pubkey.
36         pub node_id: PublicKey,
37         /// The channel between `node_id` and the next hop. If set, the constructed [`BlindedHop`]'s
38         /// `encrypted_payload` will use this instead of the next [`ForwardNode::node_id`] for a more
39         /// compact representation.
40         pub short_channel_id: Option<u64>,
41 }
42
43 /// TLVs to encode in an intermediate onion message packet's hop data. When provided in a blinded
44 /// route, they are encoded into [`BlindedHop::encrypted_payload`].
45 pub(crate) struct ForwardTlvs {
46         /// The next hop in the onion message's path.
47         pub(crate) next_hop: NextMessageHop,
48         /// Senders to a blinded path use this value to concatenate the route they find to the
49         /// introduction node with the blinded path.
50         pub(crate) next_blinding_override: Option<PublicKey>,
51 }
52
53 /// Similar to [`ForwardTlvs`], but these TLVs are for the final node.
54 pub(crate) struct ReceiveTlvs {
55         /// If `path_id` is `Some`, it is used to identify the blinded path that this onion message is
56         /// sending to. This is useful for receivers to check that said blinded path is being used in
57         /// the right context.
58         pub(crate) path_id: Option<[u8; 32]>,
59 }
60
61 impl Writeable for ForwardTlvs {
62         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
63                 let (next_node_id, short_channel_id) = match self.next_hop {
64                         NextMessageHop::NodeId(pubkey) => (Some(pubkey), None),
65                         NextMessageHop::ShortChannelId(scid) => (None, Some(scid)),
66                 };
67                 // TODO: write padding
68                 encode_tlv_stream!(writer, {
69                         (2, short_channel_id, option),
70                         (4, next_node_id, option),
71                         (8, self.next_blinding_override, option)
72                 });
73                 Ok(())
74         }
75 }
76
77 impl Writeable for ReceiveTlvs {
78         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
79                 // TODO: write padding
80                 encode_tlv_stream!(writer, {
81                         (6, self.path_id, option),
82                 });
83                 Ok(())
84         }
85 }
86
87 /// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
88 pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
89         secp_ctx: &Secp256k1<T>, intermediate_nodes: &[ForwardNode], recipient_node_id: PublicKey,
90         session_priv: &SecretKey
91 ) -> Result<Vec<BlindedHop>, secp256k1::Error> {
92         let pks = intermediate_nodes.iter().map(|node| &node.node_id)
93                 .chain(core::iter::once(&recipient_node_id));
94         let tlvs = pks.clone()
95                 .skip(1) // The first node's TLVs contains the next node's pubkey
96                 .zip(intermediate_nodes.iter().map(|node| node.short_channel_id))
97                 .map(|(pubkey, scid)| match scid {
98                         Some(scid) => NextMessageHop::ShortChannelId(scid),
99                         None => NextMessageHop::NodeId(*pubkey),
100                 })
101                 .map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None }))
102                 .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None })));
103
104         utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv)
105 }
106
107 // Advance the blinded onion message path by one hop, so make the second hop into the new
108 // introduction node.
109 pub(crate) fn advance_path_by_one<NS: Deref, NL: Deref, T>(
110         path: &mut BlindedPath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>
111 ) -> Result<(), ()>
112 where
113         NS::Target: NodeSigner,
114         NL::Target: NodeIdLookUp,
115         T: secp256k1::Signing + secp256k1::Verification,
116 {
117         let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?;
118         let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
119         let encrypted_control_tlvs = path.blinded_hops.remove(0).encrypted_payload;
120         let mut s = Cursor::new(&encrypted_control_tlvs);
121         let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64);
122         match ChaChaPolyReadAdapter::read(&mut reader, rho) {
123                 Ok(ChaChaPolyReadAdapter {
124                         readable: ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override })
125                 }) => {
126                         let next_node_id = match next_hop {
127                                 NextMessageHop::NodeId(pubkey) => pubkey,
128                                 NextMessageHop::ShortChannelId(scid) => match node_id_lookup.next_node_id(scid) {
129                                         Some(pubkey) => pubkey,
130                                         None => return Err(()),
131                                 },
132                         };
133                         let mut new_blinding_point = match next_blinding_override {
134                                 Some(blinding_point) => blinding_point,
135                                 None => {
136                                         onion_utils::next_hop_pubkey(secp_ctx, path.blinding_point,
137                                                 control_tlvs_ss.as_ref()).map_err(|_| ())?
138                                 }
139                         };
140                         mem::swap(&mut path.blinding_point, &mut new_blinding_point);
141                         path.introduction_node = IntroductionNode::NodeId(next_node_id);
142                         Ok(())
143                 },
144                 _ => Err(())
145         }
146 }