|
9 | 9 |
|
10 | 10 | //! Creating blinded routes and related utilities live here.
|
11 | 11 |
|
12 |
| -use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; |
| 12 | +use bitcoin::hashes::{Hash, HashEngine}; |
| 13 | +use bitcoin::hashes::sha256::Hash as Sha256; |
| 14 | +use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey}; |
13 | 15 |
|
14 |
| -use crate::chain::keysinterface::KeysInterface; |
| 16 | +use crate::chain::keysinterface::{KeysInterface, Recipient}; |
| 17 | +use super::packet::ControlTlvs; |
15 | 18 | use super::utils;
|
16 | 19 | use crate::ln::msgs::DecodeError;
|
17 |
| -use crate::util::chacha20poly1305rfc::ChaChaPolyWriteAdapter; |
18 |
| -use crate::util::ser::{Readable, VecWriter, Writeable, Writer}; |
| 20 | +use crate::ln::onion_utils; |
| 21 | +use crate::util::chacha20poly1305rfc::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter}; |
| 22 | +use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Readable, VecWriter, Writeable, Writer}; |
19 | 23 |
|
20 |
| -use crate::io; |
| 24 | +use core::mem; |
| 25 | +use core::ops::Deref; |
| 26 | +use crate::io::{self, Cursor}; |
21 | 27 | use crate::prelude::*;
|
22 | 28 |
|
23 | 29 | /// Onion messages can be sent and received to blinded routes, which serve to hide the identity of
|
@@ -69,6 +75,41 @@ impl BlindedRoute {
|
69 | 75 | blinded_hops: blinded_hops(secp_ctx, node_pks, &blinding_secret).map_err(|_| ())?,
|
70 | 76 | })
|
71 | 77 | }
|
| 78 | + |
| 79 | + // Advance the blinded route by one hop, so make the second hop into the new introduction node. |
| 80 | + pub(super) fn advance_by_one<K: Deref, T: secp256k1::Signing + secp256k1::Verification> |
| 81 | + (&mut self, keys_manager: &K, secp_ctx: &Secp256k1<T>) -> Result<(), ()> |
| 82 | + where K::Target: KeysInterface |
| 83 | + { |
| 84 | + let control_tlvs_ss = keys_manager.ecdh(Recipient::Node, &self.blinding_point, None)?; |
| 85 | + let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes()); |
| 86 | + let encrypted_control_tlvs = self.blinded_hops.remove(0).encrypted_payload; |
| 87 | + let mut s = Cursor::new(&encrypted_control_tlvs); |
| 88 | + let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64); |
| 89 | + match ChaChaPolyReadAdapter::read(&mut reader, rho) { |
| 90 | + Ok(ChaChaPolyReadAdapter { readable: ControlTlvs::Forward(ForwardTlvs { |
| 91 | + mut next_node_id, next_blinding_override, |
| 92 | + })}) => { |
| 93 | + let mut new_blinding_point = match next_blinding_override { |
| 94 | + Some(blinding_point) => blinding_point, |
| 95 | + None => { |
| 96 | + let blinding_factor = { |
| 97 | + let mut sha = Sha256::engine(); |
| 98 | + sha.input(&self.blinding_point.serialize()[..]); |
| 99 | + sha.input(control_tlvs_ss.as_ref()); |
| 100 | + Sha256::from_engine(sha).into_inner() |
| 101 | + }; |
| 102 | + self.blinding_point.mul_tweak(secp_ctx, &Scalar::from_be_bytes(blinding_factor).unwrap()) |
| 103 | + .map_err(|_| ())? |
| 104 | + } |
| 105 | + }; |
| 106 | + mem::swap(&mut self.blinding_point, &mut new_blinding_point); |
| 107 | + mem::swap(&mut self.introduction_node_id, &mut next_node_id); |
| 108 | + Ok(()) |
| 109 | + }, |
| 110 | + _ => Err(()) |
| 111 | + } |
| 112 | + } |
72 | 113 | }
|
73 | 114 |
|
74 | 115 | /// Construct blinded hops for the given `unblinded_path`.
|
|
0 commit comments