99
1010//! Creating blinded paths and related utilities live here. 
1111
12+ pub  mod  payment; 
13+ pub ( crate )  mod  message; 
1214pub ( crate )  mod  utils; 
1315
1416use  bitcoin:: secp256k1:: { self ,  PublicKey ,  Secp256k1 ,  SecretKey } ; 
1517
16- use  crate :: sign:: { EntropySource ,  NodeSigner ,  Recipient } ; 
17- use  crate :: onion_message:: ControlTlvs ; 
18+ use  crate :: sign:: EntropySource ; 
1819use  crate :: ln:: msgs:: DecodeError ; 
19- use  crate :: ln:: onion_utils; 
20- use  crate :: util:: chacha20poly1305rfc:: { ChaChaPolyReadAdapter ,  ChaChaPolyWriteAdapter } ; 
21- use  crate :: util:: ser:: { FixedLengthReader ,  LengthReadableArgs ,  Readable ,  VecWriter ,  Writeable ,  Writer } ; 
20+ use  crate :: util:: ser:: { Readable ,  Writeable ,  Writer } ; 
2221
23- use  core:: mem; 
24- use  core:: ops:: Deref ; 
25- use  crate :: io:: { self ,  Cursor } ; 
22+ use  crate :: io; 
2623use  crate :: prelude:: * ; 
2724
2825/// Onion messages and payments can be sent and received to blinded paths, which serve to hide the 
@@ -44,13 +41,14 @@ pub struct BlindedPath {
4441pub  blinded_hops :  Vec < BlindedHop > , 
4542} 
4643
47- /// Used to construct the blinded hops portion of a blinded path. These hops cannot be identified 
48- /// by outside observers and thus can be used to hide the identity of the recipient. 
44+ /// An encrypted payload and node id corresponding to a hop in a payment or onion message path, to 
45+ /// be encoded in the sender's onion packet. These hops cannot be identified by outside observers 
46+ /// and thus can be used to hide the identity of the recipient. 
4947#[ derive( Clone ,  Debug ,  Hash ,  PartialEq ,  Eq ) ]  
5048pub  struct  BlindedHop  { 
51- 	/// The blinded node id of this hop in a blinded path . 
49+ 	/// The blinded node id of this hop in a [`BlindedPath`] . 
5250pub  blinded_node_id :  PublicKey , 
53- 	/// The encrypted payload intended for this hop in a blinded path . 
51+ 	/// The encrypted payload intended for this hop in a [`BlindedPath`] . 
5452// The node sending to this blinded path will later encode this payload into the onion packet for 
5553	// this hop. 
5654	pub  encrypted_payload :  Vec < u8 > , 
@@ -73,81 +71,30 @@ impl BlindedPath {
7371		Ok ( BlindedPath  { 
7472			introduction_node_id, 
7573			blinding_point :  PublicKey :: from_secret_key ( secp_ctx,  & blinding_secret) , 
76- 			blinded_hops :  blinded_message_hops ( secp_ctx,  node_pks,  & blinding_secret) . map_err ( |_| ( ) ) ?, 
74+ 			blinded_hops :  message :: blinded_hops ( secp_ctx,  node_pks,  & blinding_secret) . map_err ( |_| ( ) ) ?, 
7775		} ) 
7876	} 
7977
80- 	// Advance the blinded onion message path by one hop, so make the second hop into the new 
81- 	// introduction node. 
82- 	pub ( super )  fn  advance_message_path_by_one < NS :  Deref ,  T :  secp256k1:: Signing  + secp256k1:: Verification > 
83- 		( & mut  self ,  node_signer :  & NS ,  secp_ctx :  & Secp256k1 < T > )  -> Result < ( ) ,  ( ) > 
84- 		where  NS :: Target :  NodeSigner 
85- 	{ 
86- 		let  control_tlvs_ss = node_signer. ecdh ( Recipient :: Node ,  & self . blinding_point ,  None ) ?; 
87- 		let  rho = onion_utils:: gen_rho_from_shared_secret ( & control_tlvs_ss. secret_bytes ( ) ) ; 
88- 		let  encrypted_control_tlvs = self . blinded_hops . remove ( 0 ) . encrypted_payload ; 
89- 		let  mut  s = Cursor :: new ( & encrypted_control_tlvs) ; 
90- 		let  mut  reader = FixedLengthReader :: new ( & mut  s,  encrypted_control_tlvs. len ( )  as  u64 ) ; 
91- 		match  ChaChaPolyReadAdapter :: read ( & mut  reader,  rho)  { 
92- 			Ok ( ChaChaPolyReadAdapter  {  readable :  ControlTlvs :: Forward ( ForwardTlvs  { 
93- 				mut  next_node_id,  next_blinding_override, 
94- 			} ) } )  => { 
95- 				let  mut  new_blinding_point = match  next_blinding_override { 
96- 					Some ( blinding_point)  => blinding_point, 
97- 					None  => { 
98- 						onion_utils:: next_hop_pubkey ( secp_ctx,  self . blinding_point , 
99- 							control_tlvs_ss. as_ref ( ) ) . map_err ( |_| ( ) ) ?
100- 					} 
101- 				} ; 
102- 				mem:: swap ( & mut  self . blinding_point ,  & mut  new_blinding_point) ; 
103- 				mem:: swap ( & mut  self . introduction_node_id ,  & mut  next_node_id) ; 
104- 				Ok ( ( ) ) 
105- 			} , 
106- 			_ => Err ( ( ) ) 
107- 		} 
108- 	} 
109- } 
110- 
111- /// Construct blinded onion message hops for the given `unblinded_path`. 
112- fn  blinded_message_hops < T :  secp256k1:: Signing  + secp256k1:: Verification > ( 
113- 	secp_ctx :  & Secp256k1 < T > ,  unblinded_path :  & [ PublicKey ] ,  session_priv :  & SecretKey 
114- )  -> Result < Vec < BlindedHop > ,  secp256k1:: Error >  { 
115- 	let  mut  blinded_hops = Vec :: with_capacity ( unblinded_path. len ( ) ) ; 
116- 
117- 	let  mut  prev_ss_and_blinded_node_id = None ; 
118- 	utils:: construct_keys_callback ( secp_ctx,  unblinded_path,  None ,  session_priv,  |blinded_node_id,  _,  _,  encrypted_payload_ss,  unblinded_pk,  _| { 
119- 		if  let  Some ( ( prev_ss,  prev_blinded_node_id) )  = prev_ss_and_blinded_node_id { 
120- 			if  let  Some ( pk)  = unblinded_pk { 
121- 				let  payload = ForwardTlvs  { 
122- 					next_node_id :  pk, 
123- 					next_blinding_override :  None , 
124- 				} ; 
125- 				blinded_hops. push ( BlindedHop  { 
126- 					blinded_node_id :  prev_blinded_node_id, 
127- 					encrypted_payload :  encrypt_payload ( payload,  prev_ss) , 
128- 				} ) ; 
129- 			}  else  {  debug_assert ! ( false ) ;  } 
130- 		} 
131- 		prev_ss_and_blinded_node_id = Some ( ( encrypted_payload_ss,  blinded_node_id) ) ; 
132- 	} ) ?; 
133- 
134- 	if  let  Some ( ( final_ss,  final_blinded_node_id) )  = prev_ss_and_blinded_node_id { 
135- 		let  final_payload = ReceiveTlvs  {  path_id :  None  } ; 
136- 		blinded_hops. push ( BlindedHop  { 
137- 			blinded_node_id :  final_blinded_node_id, 
138- 			encrypted_payload :  encrypt_payload ( final_payload,  final_ss) , 
139- 		} ) ; 
140- 	}  else  {  debug_assert ! ( false )  } 
141- 
142- 	Ok ( blinded_hops) 
143- } 
78+ 	/// Create a blinded path for a payment, to be forwarded along `path`. The last node 
79+ /// in `path` will be the destination node. 
80+ /// 
81+ /// Errors if `path` is empty or a node id in `path` is invalid. 
82+ //  TODO: make all payloads the same size with padding + add dummy hops 
83+ 	pub  fn  new_for_payment < ES :  EntropySource ,  T :  secp256k1:: Signing  + secp256k1:: Verification > ( 
84+ 		intermediate_nodes :  & [ ( PublicKey ,  payment:: ForwardTlvs ) ] ,  payee_node_id :  PublicKey , 
85+ 		payee_tlvs :  payment:: ReceiveTlvs ,  entropy_source :  & ES ,  secp_ctx :  & Secp256k1 < T > 
86+ 	)  -> Result < Self ,  ( ) >  { 
87+ 		let  blinding_secret_bytes = entropy_source. get_secure_random_bytes ( ) ; 
88+ 		let  blinding_secret = SecretKey :: from_slice ( & blinding_secret_bytes[ ..] ) . expect ( "RNG is busted" ) ; 
14489
145- /// Encrypt TLV payload to be used as a [`BlindedHop::encrypted_payload`]. 
146- fn  encrypt_payload < P :  Writeable > ( payload :  P ,  encrypted_tlvs_ss :  [ u8 ;  32 ] )  -> Vec < u8 >  { 
147- 	let  mut  writer = VecWriter ( Vec :: new ( ) ) ; 
148- 	let  write_adapter = ChaChaPolyWriteAdapter :: new ( encrypted_tlvs_ss,  & payload) ; 
149- 	write_adapter. write ( & mut  writer) . expect ( "In-memory writes cannot fail" ) ; 
150- 	writer. 0 
90+ 		Ok ( BlindedPath  { 
91+ 			introduction_node_id :  intermediate_nodes. first ( ) . map_or ( payee_node_id,  |n| n. 0 ) , 
92+ 			blinding_point :  PublicKey :: from_secret_key ( secp_ctx,  & blinding_secret) , 
93+ 			blinded_hops :  payment:: blinded_hops ( 
94+ 				secp_ctx,  intermediate_nodes,  payee_node_id,  payee_tlvs,  & blinding_secret
95+ 			) . map_err ( |_| ( ) ) ?, 
96+ 		} ) 
97+ 	} 
15198} 
15299
153100impl  Writeable  for  BlindedPath  { 
@@ -185,41 +132,3 @@ impl_writeable!(BlindedHop, {
185132	encrypted_payload
186133} ) ; 
187134
188- /// TLVs to encode in an intermediate onion message packet's hop data. When provided in a blinded 
189- /// route, they are encoded into [`BlindedHop::encrypted_payload`]. 
190- pub ( crate )  struct  ForwardTlvs  { 
191- 	/// The node id of the next hop in the onion message's path. 
192- pub ( super )  next_node_id :  PublicKey , 
193- 	/// Senders to a blinded path use this value to concatenate the route they find to the 
194- /// introduction node with the blinded path. 
195- pub ( super )  next_blinding_override :  Option < PublicKey > , 
196- } 
197- 
198- /// Similar to [`ForwardTlvs`], but these TLVs are for the final node. 
199- pub ( crate )  struct  ReceiveTlvs  { 
200- 	/// If `path_id` is `Some`, it is used to identify the blinded path that this onion message is 
201- /// sending to. This is useful for receivers to check that said blinded path is being used in 
202- /// the right context. 
203- pub ( super )  path_id :  Option < [ u8 ;  32 ] > , 
204- } 
205- 
206- impl  Writeable  for  ForwardTlvs  { 
207- 	fn  write < W :  Writer > ( & self ,  writer :  & mut  W )  -> Result < ( ) ,  io:: Error >  { 
208- 		// TODO: write padding 
209- 		encode_tlv_stream ! ( writer,  { 
210- 			( 4 ,  self . next_node_id,  required) , 
211- 			( 8 ,  self . next_blinding_override,  option) 
212- 		} ) ; 
213- 		Ok ( ( ) ) 
214- 	} 
215- } 
216- 
217- impl  Writeable  for  ReceiveTlvs  { 
218- 	fn  write < W :  Writer > ( & self ,  writer :  & mut  W )  -> Result < ( ) ,  io:: Error >  { 
219- 		// TODO: write padding 
220- 		encode_tlv_stream ! ( writer,  { 
221- 			( 6 ,  self . path_id,  option) , 
222- 		} ) ; 
223- 		Ok ( ( ) ) 
224- 	} 
225- } 
0 commit comments