|
13 | 13 |
|
14 | 14 | use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
|
15 | 15 |
|
16 |
| -use crate::blinded_path::BlindedHop; |
| 16 | +use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NodeIdLookUp}; |
17 | 17 | use crate::blinded_path::utils;
|
| 18 | +use crate::crypto::streams::ChaChaPolyReadAdapter; |
18 | 19 | use crate::io;
|
| 20 | +use crate::io::Cursor; |
19 | 21 | use crate::ln::types::PaymentSecret;
|
20 | 22 | use crate::ln::channel_state::CounterpartyForwardingInfo;
|
21 | 23 | use crate::ln::features::BlindedHopFeatures;
|
22 | 24 | use crate::ln::msgs::DecodeError;
|
| 25 | +use crate::ln::onion_utils; |
23 | 26 | use crate::offers::invoice::BlindedPayInfo;
|
24 | 27 | use crate::offers::invoice_request::InvoiceRequestFields;
|
25 | 28 | use crate::offers::offer::OfferId;
|
26 |
| -use crate::util::ser::{HighZeroBytesDroppedBigSize, Readable, Writeable, Writer}; |
| 29 | +use crate::sign::{NodeSigner, Recipient}; |
| 30 | +use crate::util::ser::{FixedLengthReader, LengthReadableArgs, HighZeroBytesDroppedBigSize, Readable, Writeable, Writer}; |
| 31 | + |
| 32 | +use core::mem; |
| 33 | +use core::ops::Deref; |
27 | 34 |
|
28 | 35 | #[allow(unused_imports)]
|
29 | 36 | use crate::prelude::*;
|
@@ -274,6 +281,43 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
|
274 | 281 | utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv)
|
275 | 282 | }
|
276 | 283 |
|
| 284 | +// Advance the blinded onion payment path by one hop, so make the second hop into the new |
| 285 | +// introduction node. |
| 286 | +// |
| 287 | +// Will only modify `path` when returning `Ok`. |
| 288 | +pub(crate) fn advance_path_by_one<NS: Deref, NL: Deref, T>( |
| 289 | + path: &mut BlindedPath, node_signer: &NS, node_id_lookup: &NL, secp_ctx: &Secp256k1<T> |
| 290 | +) -> Result<(), ()> |
| 291 | +where |
| 292 | + NS::Target: NodeSigner, |
| 293 | + NL::Target: NodeIdLookUp, |
| 294 | + T: secp256k1::Signing + secp256k1::Verification, |
| 295 | +{ |
| 296 | + let control_tlvs_ss = node_signer.ecdh(Recipient::Node, &path.blinding_point, None)?; |
| 297 | + let rho = onion_utils::gen_rho_from_shared_secret(&control_tlvs_ss.secret_bytes()); |
| 298 | + let encrypted_control_tlvs = &path.blinded_hops.get(0).ok_or(())?.encrypted_payload; |
| 299 | + let mut s = Cursor::new(encrypted_control_tlvs); |
| 300 | + let mut reader = FixedLengthReader::new(&mut s, encrypted_control_tlvs.len() as u64); |
| 301 | + match ChaChaPolyReadAdapter::read(&mut reader, rho) { |
| 302 | + Ok(ChaChaPolyReadAdapter { |
| 303 | + readable: BlindedPaymentTlvs::Forward(ForwardTlvs { short_channel_id, .. }) |
| 304 | + }) => { |
| 305 | + let next_node_id = match node_id_lookup.next_node_id(short_channel_id) { |
| 306 | + Some(node_id) => node_id, |
| 307 | + None => return Err(()), |
| 308 | + }; |
| 309 | + let mut new_blinding_point = onion_utils::next_hop_pubkey( |
| 310 | + secp_ctx, path.blinding_point, control_tlvs_ss.as_ref() |
| 311 | + ).map_err(|_| ())?; |
| 312 | + mem::swap(&mut path.blinding_point, &mut new_blinding_point); |
| 313 | + path.introduction_node = IntroductionNode::NodeId(next_node_id); |
| 314 | + path.blinded_hops.remove(0); |
| 315 | + Ok(()) |
| 316 | + }, |
| 317 | + _ => Err(()) |
| 318 | + } |
| 319 | +} |
| 320 | + |
277 | 321 | /// `None` if underflow occurs.
|
278 | 322 | pub(crate) fn amt_to_forward_msat(inbound_amt_msat: u64, payment_relay: &PaymentRelay) -> Option<u64> {
|
279 | 323 | let inbound_amt = inbound_amt_msat as u128;
|
|
0 commit comments