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 message over.
11- //!
12- //! [`BlindedPath`]: crate::blinded_path::BlindedPath
10+ //! Data structures and methods for constructing [`BlindedMessagePath`]s to send a message over.
1311
1412use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 , SecretKey } ;
1513
@@ -21,16 +19,61 @@ use crate::blinded_path::utils;
2119use crate :: io;
2220use crate :: io:: Cursor ;
2321use crate :: ln:: channelmanager:: PaymentId ;
22+ use crate :: ln:: msgs:: DecodeError ;
2423use crate :: ln:: { PaymentHash , onion_utils} ;
2524use crate :: offers:: nonce:: Nonce ;
2625use crate :: onion_message:: packet:: ControlTlvs ;
27- use crate :: sign:: { NodeSigner , Recipient } ;
26+ use crate :: sign:: { EntropySource , NodeSigner , Recipient } ;
2827use crate :: crypto:: streams:: ChaChaPolyReadAdapter ;
29- use crate :: util:: ser:: { FixedLengthReader , LengthReadableArgs , Writeable , Writer } ;
28+ use crate :: util:: ser:: { FixedLengthReader , LengthReadableArgs , Readable , Writeable , Writer } ;
3029
3130use core:: mem;
3231use core:: ops:: Deref ;
3332
33+ /// A [`BlindedPath`] to be used for sending or receiving a message, hiding the identity of the
34+ /// recipient.
35+ #[ derive( Clone , Debug , Hash , PartialEq , Eq ) ]
36+ pub struct BlindedMessagePath ( pub BlindedPath ) ;
37+
38+ impl Writeable for BlindedMessagePath {
39+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
40+ self . 0 . write ( w)
41+ }
42+ }
43+
44+ impl Readable for BlindedMessagePath {
45+ fn read < R : io:: Read > ( r : & mut R ) -> Result < Self , DecodeError > {
46+ Ok ( Self ( BlindedPath :: read ( r) ?) )
47+ }
48+ }
49+
50+ impl BlindedMessagePath {
51+ /// Create a path for an onion message, to be forwarded along `node_pks`. The last node
52+ /// pubkey in `node_pks` will be the destination node.
53+ ///
54+ /// Errors if no hops are provided or if `node_pk`(s) are invalid.
55+ // TODO: make all payloads the same size with padding + add dummy hops
56+ pub fn new < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
57+ intermediate_nodes : & [ ForwardNode ] , recipient_node_id : PublicKey , context : MessageContext ,
58+ entropy_source : ES , secp_ctx : & Secp256k1 < T >
59+ ) -> Result < Self , ( ) > where ES :: Target : EntropySource {
60+ let introduction_node = IntroductionNode :: NodeId (
61+ intermediate_nodes. first ( ) . map_or ( recipient_node_id, |n| n. node_id )
62+ ) ;
63+ let blinding_secret_bytes = entropy_source. get_secure_random_bytes ( ) ;
64+ let blinding_secret = SecretKey :: from_slice ( & blinding_secret_bytes[ ..] ) . expect ( "RNG is busted" ) ;
65+
66+ Ok ( BlindedMessagePath ( BlindedPath {
67+ introduction_node,
68+ blinding_point : PublicKey :: from_secret_key ( secp_ctx, & blinding_secret) ,
69+ blinded_hops : blinded_hops (
70+ secp_ctx, intermediate_nodes, recipient_node_id,
71+ context, & blinding_secret,
72+ ) . map_err ( |_| ( ) ) ?,
73+ } ) )
74+ }
75+ }
76+
3477/// An intermediate node, and possibly a short channel id leading to the next node.
3578#[ derive( Clone , Copy , Debug , Hash , PartialEq , Eq ) ]
3679pub struct ForwardNode {
@@ -86,10 +129,10 @@ impl Writeable for ReceiveTlvs {
86129 }
87130}
88131
89- /// Additional data included by the recipient in a [`BlindedPath `].
132+ /// Additional data included by the recipient in a [`BlindedMessagePath `].
90133///
91134/// This data is encrypted by the recipient and will be given to the corresponding message handler
92- /// when handling a message sent over the [`BlindedPath `]. The recipient can use this data to
135+ /// when handling a message sent over the [`BlindedMessagePath `]. The recipient can use this data to
93136/// authenticate the message or for further processing if needed.
94137#[ derive( Clone , Debug ) ]
95138pub enum MessageContext {
@@ -108,7 +151,7 @@ pub enum MessageContext {
108151/// [`OffersMessage`]: crate::onion_message::offers::OffersMessage
109152#[ derive( Clone , Debug , Eq , PartialEq ) ]
110153pub enum OffersContext {
111- /// Context used by a [`BlindedPath `] within an [`Offer`].
154+ /// Context used by a [`BlindedMessagePath `] within an [`Offer`].
112155 ///
113156 /// This variant is intended to be received when handling an [`InvoiceRequest`].
114157 ///
@@ -122,7 +165,7 @@ pub enum OffersContext {
122165 /// [`Offer`]: crate::offers::offer::Offer
123166 nonce : Nonce ,
124167 } ,
125- /// Context used by a [`BlindedPath `] within a [`Refund`] or as a reply path for an
168+ /// Context used by a [`BlindedMessagePath `] within a [`Refund`] or as a reply path for an
126169 /// [`InvoiceRequest`].
127170 ///
128171 /// This variant is intended to be received when handling a [`Bolt12Invoice`] or an
@@ -147,7 +190,7 @@ pub enum OffersContext {
147190 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
148191 nonce : Nonce ,
149192 } ,
150- /// Context used by a [`BlindedPath `] as a reply path for a [`Bolt12Invoice`].
193+ /// Context used by a [`BlindedMessagePath `] as a reply path for a [`Bolt12Invoice`].
151194 ///
152195 /// This variant is intended to be received when handling an [`InvoiceError`].
153196 ///
@@ -204,16 +247,16 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
204247//
205248// Will only modify `path` when returning `Ok`.
206249pub ( crate ) fn advance_path_by_one < NS : Deref , NL : Deref , T > (
207- path : & mut BlindedPath , node_signer : & NS , node_id_lookup : & NL , secp_ctx : & Secp256k1 < T >
250+ path : & mut BlindedMessagePath , node_signer : & NS , node_id_lookup : & NL , secp_ctx : & Secp256k1 < T >
208251) -> Result < ( ) , ( ) >
209252where
210253 NS :: Target : NodeSigner ,
211254 NL :: Target : NodeIdLookUp ,
212255 T : secp256k1:: Signing + secp256k1:: Verification ,
213256{
214- let control_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & path. blinding_point , None ) ?;
257+ let control_tlvs_ss = node_signer. ecdh ( Recipient :: Node , & path. 0 . blinding_point , None ) ?;
215258 let rho = onion_utils:: gen_rho_from_shared_secret ( & control_tlvs_ss. secret_bytes ( ) ) ;
216- let encrypted_control_tlvs = & path. blinded_hops . get ( 0 ) . ok_or ( ( ) ) ?. encrypted_payload ;
259+ let encrypted_control_tlvs = & path. 0 . blinded_hops . get ( 0 ) . ok_or ( ( ) ) ?. encrypted_payload ;
217260 let mut s = Cursor :: new ( encrypted_control_tlvs) ;
218261 let mut reader = FixedLengthReader :: new ( & mut s, encrypted_control_tlvs. len ( ) as u64 ) ;
219262 match ChaChaPolyReadAdapter :: read ( & mut reader, rho) {
@@ -230,13 +273,13 @@ where
230273 let mut new_blinding_point = match next_blinding_override {
231274 Some ( blinding_point) => blinding_point,
232275 None => {
233- onion_utils:: next_hop_pubkey ( secp_ctx, path. blinding_point ,
276+ onion_utils:: next_hop_pubkey ( secp_ctx, path. 0 . blinding_point ,
234277 control_tlvs_ss. as_ref ( ) ) . map_err ( |_| ( ) ) ?
235278 }
236279 } ;
237- mem:: swap ( & mut path. blinding_point , & mut new_blinding_point) ;
238- path. introduction_node = IntroductionNode :: NodeId ( next_node_id) ;
239- path. blinded_hops . remove ( 0 ) ;
280+ mem:: swap ( & mut path. 0 . blinding_point , & mut new_blinding_point) ;
281+ path. 0 . introduction_node = IntroductionNode :: NodeId ( next_node_id) ;
282+ path. 0 . blinded_hops . remove ( 0 ) ;
240283 Ok ( ( ) )
241284 } ,
242285 _ => Err ( ( ) )
0 commit comments