Move some blinded path message code into message submodule.
[rust-lightning] / lightning / src / blinded_path / message.rs
1 use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
2 use crate::blinded_path::BlindedHop;
3 use crate::blinded_path::utils;
4 use crate::io;
5 use crate::prelude::*;
6 use crate::util::ser::{Writeable, Writer};
7
8 /// TLVs to encode in an intermediate onion message packet's hop data. When provided in a blinded
9 /// route, they are encoded into [`BlindedHop::encrypted_payload`].
10 pub(crate) struct ForwardTlvs {
11         /// The node id of the next hop in the onion message's path.
12         pub(crate) next_node_id: PublicKey,
13         /// Senders to a blinded path use this value to concatenate the route they find to the
14         /// introduction node with the blinded path.
15         pub(crate) next_blinding_override: Option<PublicKey>,
16 }
17
18 /// Similar to [`ForwardTlvs`], but these TLVs are for the final node.
19 pub(crate) struct ReceiveTlvs {
20         /// If `path_id` is `Some`, it is used to identify the blinded path that this onion message is
21         /// sending to. This is useful for receivers to check that said blinded path is being used in
22         /// the right context.
23         pub(crate) path_id: Option<[u8; 32]>,
24 }
25
26 impl Writeable for ForwardTlvs {
27         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
28                 // TODO: write padding
29                 encode_tlv_stream!(writer, {
30                         (4, self.next_node_id, required),
31                         (8, self.next_blinding_override, option)
32                 });
33                 Ok(())
34         }
35 }
36
37 impl Writeable for ReceiveTlvs {
38         fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
39                 // TODO: write padding
40                 encode_tlv_stream!(writer, {
41                         (6, self.path_id, option),
42                 });
43                 Ok(())
44         }
45 }
46
47 /// Construct blinded onion message hops for the given `unblinded_path`.
48 pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
49         secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], session_priv: &SecretKey
50 ) -> Result<Vec<BlindedHop>, secp256k1::Error> {
51         let mut blinded_hops = Vec::with_capacity(unblinded_path.len());
52
53         let mut prev_ss_and_blinded_node_id = None;
54         utils::construct_keys_callback(secp_ctx, unblinded_path, None, session_priv, |blinded_node_id, _, _, encrypted_payload_ss, unblinded_pk, _| {
55                 if let Some((prev_ss, prev_blinded_node_id)) = prev_ss_and_blinded_node_id {
56                         if let Some(pk) = unblinded_pk {
57                                 let payload = ForwardTlvs {
58                                         next_node_id: pk,
59                                         next_blinding_override: None,
60                                 };
61                                 blinded_hops.push(BlindedHop {
62                                         blinded_node_id: prev_blinded_node_id,
63                                         encrypted_payload: utils::encrypt_payload(payload, prev_ss),
64                                 });
65                         } else { debug_assert!(false); }
66                 }
67                 prev_ss_and_blinded_node_id = Some((encrypted_payload_ss, blinded_node_id));
68         })?;
69
70         if let Some((final_ss, final_blinded_node_id)) = prev_ss_and_blinded_node_id {
71                 let final_payload = ReceiveTlvs { path_id: None };
72                 blinded_hops.push(BlindedHop {
73                         blinded_node_id: final_blinded_node_id,
74                         encrypted_payload: utils::encrypt_payload(final_payload, final_ss),
75                 });
76         } else { debug_assert!(false) }
77
78         Ok(blinded_hops)
79 }