Look up node id from scid in OnionMessenger
[rust-lightning] / lightning / src / blinded_path / message.rs
1 use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
2
3 #[allow(unused_imports)]
4 use crate::prelude::*;
5
6 use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NodeIdLookUp};
7 use crate::blinded_path::utils;
8 use crate::io;
9 use crate::io::Cursor;
10 use crate::ln::onion_utils;
11 use crate::onion_message::packet::ControlTlvs;
12 use crate::sign::{NodeSigner, Recipient};
13 use crate::crypto::streams::ChaChaPolyReadAdapter;
14 use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
15
16 use core::mem;
17 use core::ops::Deref;
18
19 /// TLVs to encode in an intermediate onion message packet's hop data. When provided in a blinded
20 /// route, they are encoded into [`BlindedHop::encrypted_payload`].
21 pub(crate) struct ForwardTlvs {
22         /// The next hop in the onion message's path.
23         pub(crate) next_hop: NextHop,
24         /// Senders to a blinded path use this value to concatenate the route they find to the
25         /// introduction node with the blinded path.
26         pub(crate) next_blinding_override: Option<PublicKey>,
27 }
28
29 /// Similar to [`ForwardTlvs`], but these TLVs are for the final node.
30 pub(crate) struct ReceiveTlvs {
31         /// If `path_id` is `Some`, it is used to identify the blinded path that this onion message is
32         /// sending to. This is useful for receivers to check that said blinded path is being used in
33         /// the right context.
34         pub(crate) path_id: Option<[u8; 32]>,
35 }
36
37 /// The next hop to forward the onion message along its path.
38 #[derive(Debug)]
39 pub enum NextHop {
40         /// The node id of the next hop.
41         NodeId(PublicKey),
42         /// The short channel id leading to the next hop.
43         ShortChannelId(u64),
44 }
45
46 impl Writeable for ForwardTlvs {
47         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
48                 let (next_node_id, short_channel_id) = match self.next_hop {
49                         NextHop::NodeId(pubkey) => (Some(pubkey), None),
50                         NextHop::ShortChannelId(scid) => (None, Some(scid)),
51                 };
52                 // TODO: write padding
53                 encode_tlv_stream!(writer, {
54                         (2, short_channel_id, option),
55                         (4, next_node_id, option),
56                         (8, self.next_blinding_override, option)
57                 });
58                 Ok(())
59         }
60 }
61
62 impl Writeable for ReceiveTlvs {
63         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
64                 // TODO: write padding
65                 encode_tlv_stream!(writer, {
66                         (6, self.path_id, option),
67                 });
68                 Ok(())
69         }
70 }
71
72 /// Construct blinded onion message hops for the given `unblinded_path`.
73 pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
74         secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], session_priv: &SecretKey
75 ) -> Result<Vec<BlindedHop>, secp256k1::Error> {
76         let blinded_tlvs = unblinded_path.iter()
77                 .skip(1) // The first node's TLVs contains the next node's pubkey
78                 .map(|pk| ForwardTlvs { next_hop: NextHop::NodeId(*pk), next_blinding_override: None })
79                 .map(|tlvs| ControlTlvs::Forward(tlvs))
80                 .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None })));
81
82         utils::construct_blinded_hops(secp_ctx, unblinded_path.iter(), blinded_tlvs, session_priv)
83 }
84
85 // Advance the blinded onion message path by one hop, so make the second hop into the new
86 // introduction node.
87 pub(crate) fn advance_path_by_one<NS: Deref, NL: Deref, T>(
88         path: &mut BlindedPath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T>
89 ) -> Result<(), ()>
90 where
91         NS::Target: NodeSigner,
92         NL::Target: NodeIdLookUp,
93         T: secp256k1::Signing + secp256k1::Verification,
94 {
95         let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?;
96         let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes());
97         let encrypted_control_tlvs = path.blinded_hops.remove(0).encrypted_payload;
98         let mut s = Cursor::new(&encrypted_control_tlvs);
99         let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64);
100         match ChaChaPolyReadAdapter::read(&mut reader, rho) {
101                 Ok(ChaChaPolyReadAdapter {
102                         readable: ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override })
103                 }) => {
104                         let next_node_id = match next_hop {
105                                 NextHop::NodeId(pubkey) => pubkey,
106                                 NextHop::ShortChannelId(scid) => match node_id_lookup.next_node_id(scid) {
107                                         Some(pubkey) => pubkey,
108                                         None => return Err(()),
109                                 },
110                         };
111                         let mut new_blinding_point = match next_blinding_override {
112                                 Some(blinding_point) => blinding_point,
113                                 None => {
114                                         onion_utils::next_hop_pubkey(secp_ctx, path.blinding_point,
115                                                 control_tlvs_ss.as_ref()).map_err(|_| ())?
116                                 }
117                         };
118                         mem::swap(&mut path.blinding_point, &mut new_blinding_point);
119                         path.introduction_node = IntroductionNode::NodeId(next_node_id);
120                         Ok(())
121                 },
122                 _ => Err(())
123         }
124 }