77// You may not use this file except in accordance with one or both of these
88// licenses.
99
10- //! Data structures and methods for constructing [`BlindedPath`]s to send a payment over.
11- //!
12- //! [`BlindedPath`]: crate::blinded_path::BlindedPath
10+ //! Data structures and methods for constructing [`BlindedPaymentPath`]s to send a payment over.
1311
1412use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 , SecretKey } ;
1513
@@ -26,7 +24,7 @@ use crate::ln::onion_utils;
2624use crate :: offers:: invoice:: BlindedPayInfo ;
2725use crate :: offers:: invoice_request:: InvoiceRequestFields ;
2826use crate :: offers:: offer:: OfferId ;
29- use crate :: sign:: { NodeSigner , Recipient } ;
27+ use crate :: sign:: { EntropySource , NodeSigner , Recipient } ;
3028use crate :: util:: ser:: { FixedLengthReader , LengthReadableArgs , HighZeroBytesDroppedBigSize , Readable , Writeable , Writer } ;
3129
3230use core:: mem;
@@ -35,6 +33,55 @@ use core::ops::Deref;
3533#[ allow( unused_imports) ]
3634use crate :: prelude:: * ;
3735
36+ /// A [`BlindedPath`] to be used for sending or receiving a payment, hiding the identity of the
37+ /// recipient.
38+ #[ derive( Clone , Debug , Hash , PartialEq , Eq ) ]
39+ pub struct BlindedPaymentPath ( pub BlindedPath ) ;
40+
41+ impl Writeable for BlindedPaymentPath {
42+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
43+ self . 0 . write ( w)
44+ }
45+ }
46+
47+ impl Readable for BlindedPaymentPath {
48+ fn read < R : io:: Read > ( r : & mut R ) -> Result < Self , DecodeError > {
49+ Ok ( Self ( BlindedPath :: read ( r) ?) )
50+ }
51+ }
52+
53+ impl BlindedPaymentPath {
54+ /// Create a blinded path for a payment, to be forwarded along `intermediate_nodes`.
55+ ///
56+ /// Errors if:
57+ /// * a provided node id is invalid
58+ /// * [`BlindedPayInfo`] calculation results in an integer overflow
59+ /// * any unknown features are required in the provided [`ForwardTlvs`]
60+ // TODO: make all payloads the same size with padding + add dummy hops
61+ pub fn new < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
62+ intermediate_nodes : & [ ForwardNode ] , payee_node_id : PublicKey , payee_tlvs : ReceiveTlvs ,
63+ htlc_maximum_msat : u64 , min_final_cltv_expiry_delta : u16 , entropy_source : ES ,
64+ secp_ctx : & Secp256k1 < T >
65+ ) -> Result < ( BlindedPayInfo , Self ) , ( ) > where ES :: Target : EntropySource {
66+ let introduction_node = IntroductionNode :: NodeId (
67+ intermediate_nodes. first ( ) . map_or ( payee_node_id, |n| n. node_id )
68+ ) ;
69+ let blinding_secret_bytes = entropy_source. get_secure_random_bytes ( ) ;
70+ let blinding_secret = SecretKey :: from_slice ( & blinding_secret_bytes[ ..] ) . expect ( "RNG is busted" ) ;
71+
72+ let blinded_payinfo = compute_payinfo (
73+ intermediate_nodes, & payee_tlvs, htlc_maximum_msat, min_final_cltv_expiry_delta
74+ ) ?;
75+ Ok ( ( blinded_payinfo, Self ( BlindedPath {
76+ introduction_node,
77+ blinding_point : PublicKey :: from_secret_key ( secp_ctx, & blinding_secret) ,
78+ blinded_hops : blinded_hops (
79+ secp_ctx, intermediate_nodes, payee_node_id, payee_tlvs, & blinding_secret
80+ ) . map_err ( |_| ( ) ) ?,
81+ } ) ) )
82+ }
83+ }
84+
3885/// An intermediate node, its outbound channel, and relay parameters.
3986#[ derive( Clone , Debug ) ]
4087pub struct ForwardNode {
@@ -117,10 +164,9 @@ pub struct PaymentConstraints {
117164 pub htlc_minimum_msat : u64 ,
118165}
119166
120- /// The context of an inbound payment, which is included in a [`BlindedPath `] via [`ReceiveTlvs`]
121- /// and surfaced in [`PaymentPurpose`].
167+ /// The context of an inbound payment, which is included in a [`BlindedPaymentPath `] via
168+ /// [`ReceiveTlvs`] and surfaced in [`PaymentPurpose`].
122169///
123- /// [`BlindedPath`]: crate::blinded_path::BlindedPath
124170/// [`PaymentPurpose`]: crate::events::PaymentPurpose
125171#[ derive( Clone , Debug , Eq , PartialEq ) ]
126172pub enum PaymentContext {
@@ -286,16 +332,16 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
286332//
287333// Will only modify `path` when returning `Ok`.
288334pub ( 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 >
335+ path : & mut BlindedPaymentPath , node_signer : & NS , node_id_lookup : & NL , secp_ctx : & Secp256k1 < T >
290336) -> Result < ( ) , ( ) >
291337where
292338 NS :: Target : NodeSigner ,
293339 NL :: Target : NodeIdLookUp ,
294340 T : secp256k1:: Signing + secp256k1:: Verification ,
295341{
296- let control_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & path. blinding_point , None ) ?;
342+ let control_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & path. 0 . blinding_point , None ) ?;
297343 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 ;
344+ let encrypted_control_tlvs = & path. 0 . blinded_hops . get ( 0 ) . ok_or ( ( ) ) ?. encrypted_payload ;
299345 let mut s = Cursor :: new ( encrypted_control_tlvs) ;
300346 let mut reader = FixedLengthReader :: new ( & mut s, encrypted_control_tlvs. len ( ) as u64 ) ;
301347 match ChaChaPolyReadAdapter :: read ( & mut reader, rho) {
@@ -307,11 +353,11 @@ where
307353 None => return Err ( ( ) ) ,
308354 } ;
309355 let mut new_blinding_point = onion_utils:: next_hop_pubkey (
310- secp_ctx, path. blinding_point , control_tlvs_ss. as_ref ( )
356+ secp_ctx, path. 0 . blinding_point , control_tlvs_ss. as_ref ( )
311357 ) . 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 ) ;
358+ mem:: swap ( & mut path. 0 . blinding_point , & mut new_blinding_point) ;
359+ path. 0 . introduction_node = IntroductionNode :: NodeId ( next_node_id) ;
360+ path. 0 . blinded_hops . remove ( 0 ) ;
315361 Ok ( ( ) )
316362 } ,
317363 _ => Err ( ( ) )
0 commit comments