@@ -246,6 +246,14 @@ pub trait CustomOnionMessageHandler {
246246fn  read_custom_message < R :  io:: Read > ( & self ,  message_type :  u64 ,  buffer :  & mut  R )  -> Result < Option < Self :: CustomMessage > ,  msgs:: DecodeError > ; 
247247} 
248248
249+ /// A processed incoming onion message, containing either a Forward (another onion message) 
250+ /// or a Receive payload with decrypted contents. 
251+ pub  enum  PeeledOnion < CM :  CustomOnionMessageContents >  { 
252+ 	/// Forwarded onion, with the next node id and a new onion 
253+ Forward ( PublicKey ,  msgs:: OnionMessage ) , 
254+ 	/// Received onion message, with decrypted contents, path_id, and reply path 
255+ Receive ( OnionMessageContents < CM > ,  Option < [ u8 ;  32 ] > ,  Option < BlindedPath > ) 
256+ } 
249257
250258/// Create an onion message with contents `message` to the destination of `path`. 
251259/// Returns (introduction_node_id, onion_msg) 
@@ -304,6 +312,101 @@ where
304312	} ) ) 
305313} 
306314
315+ /// Decode one layer of an incoming onion message 
316+ /// Returns either a Forward (another onion message), or Receive (decrypted content) 
317+ pub  fn  peel_onion < NS :  Deref ,  L :  Deref ,  CMH :  Deref > ( 
318+ 	node_signer :  NS ,  secp_ctx :  & Secp256k1 < secp256k1:: All > ,  logger :  L ,  custom_handler :  CMH , 
319+ 	msg :  & msgs:: OnionMessage , 
320+ )  -> Result < PeeledOnion < <<CMH >:: Target  as  CustomOnionMessageHandler >:: CustomMessage > ,  ( ) > 
321+ where 
322+ 	NS :: Target :  NodeSigner , 
323+ 	L :: Target :  Logger , 
324+ 	CMH :: Target :  CustomOnionMessageHandler , 
325+ { 
326+ 	let  control_tlvs_ss = match  node_signer. ecdh ( Recipient :: Node ,  & msg. blinding_point ,  None )  { 
327+ 		Ok ( ss)  => ss, 
328+ 		Err ( e)  =>  { 
329+ 			log_error ! ( logger,  "Failed to retrieve node secret: {:?}" ,  e) ; 
330+ 			return  Err ( ( ) ) ; 
331+ 		} 
332+ 	} ; 
333+ 	let  onion_decode_ss = { 
334+ 		let  blinding_factor = { 
335+ 			let  mut  hmac = HmacEngine :: < Sha256 > :: new ( b"blinded_node_id" ) ; 
336+ 			hmac. input ( control_tlvs_ss. as_ref ( ) ) ; 
337+ 			Hmac :: from_engine ( hmac) . into_inner ( ) 
338+ 		} ; 
339+ 		match  node_signer. ecdh ( Recipient :: Node ,  & msg. onion_routing_packet . public_key , 
340+ 			Some ( & Scalar :: from_be_bytes ( blinding_factor) . unwrap ( ) ) ) 
341+ 		{ 
342+ 			Ok ( ss)  => ss. secret_bytes ( ) , 
343+ 			Err ( ( ) )  => { 
344+ 				log_trace ! ( logger,  "Failed to compute onion packet shared secret" ) ; 
345+ 				return  Err ( ( ) ) ; 
346+ 			} 
347+ 		} 
348+ 	} ; 
349+ 	match  onion_utils:: decode_next_untagged_hop ( 
350+ 		onion_decode_ss,  & msg. onion_routing_packet . hop_data [ ..] ,  msg. onion_routing_packet . hmac , 
351+ 		( control_tlvs_ss,  custom_handler. deref ( ) ,  logger. deref ( ) ) 
352+ 	)  { 
353+ 		Ok ( ( Payload :: Receive :: < <<CMH  as  Deref >:: Target  as  CustomOnionMessageHandler >:: CustomMessage >  { 
354+ 			message,  control_tlvs :  ReceiveControlTlvs :: Unblinded ( ReceiveTlvs  {  path_id } ) ,  reply_path, 
355+ 		} ,  None ) )  => { 
356+ 			Ok ( PeeledOnion : : Receive ( message,  path_id,  reply_path) ) 
357+ 		} , 
358+ 		Ok ( ( Payload : : Forward ( ForwardControlTlvs :: Unblinded ( ForwardTlvs  { 
359+ 			next_node_id,  next_blinding_override
360+ 		} ) ) ,  Some ( ( next_hop_hmac,  new_packet_bytes) ) ) )  => { 
361+ 			// TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy 
362+ 			// blinded hop and this onion message is destined for us. In this situation, we should keep 
363+ 			// unwrapping the onion layers to get to the final payload. Since we don't have the option 
364+ 			// of creating blinded paths with dummy hops currently, we should be ok to not handle this 
365+ 			// for now. 
366+ 			let  new_pubkey = match  onion_utils : : next_hop_pubkey( & secp_ctx,  msg. onion_routing_packet. public_key,  & onion_decode_ss)  { 
367+ 				Ok ( pk)  => pk, 
368+ 				Err ( e)  => { 
369+ 					log_trace!( logger,  "Failed to compute next hop packet pubkey: {}" ,  e) ; 
370+ 					return  Err ( ( ) ) 
371+ 				} 
372+ 			} ; 
373+ 			let  outgoing_packet = Packet  { 
374+ 				version :  0 , 
375+ 				public_key :  new_pubkey, 
376+ 				hop_data :  new_packet_bytes, 
377+ 				hmac :  next_hop_hmac, 
378+ 			} ; 
379+ 			let  onion_message = msgs:: OnionMessage  { 
380+ 				blinding_point :  match  next_blinding_override { 
381+ 					Some ( blinding_point)  => blinding_point, 
382+ 					None  => { 
383+ 						match  onion_utils:: next_hop_pubkey ( 
384+ 							& secp_ctx,  msg. blinding_point ,  control_tlvs_ss. as_ref ( ) 
385+ 						)  { 
386+ 							Ok ( bp)  => bp, 
387+ 							Err ( e)  => { 
388+ 								log_trace ! ( logger,  "Failed to compute next blinding point: {}" ,  e) ; 
389+ 								return  Err ( ( ) ) 
390+ 							} 
391+ 						} 
392+ 					} 
393+ 				} , 
394+ 				onion_routing_packet :  outgoing_packet, 
395+ 			} ; 
396+ 
397+ 			Ok ( PeeledOnion :: Forward ( next_node_id,  onion_message) ) 
398+ 		} , 
399+ 		Err ( e)  => { 
400+ 			log_trace ! ( logger,  "Errored decoding onion message packet: {:?}" ,  e) ; 
401+ 			Err ( ( ) ) 
402+ 		} , 
403+ 		_ => { 
404+ 			log_trace ! ( logger,  "Received bogus onion message packet, either the sender encoded a final hop as a forwarding hop or vice versa" ) ; 
405+ 			Err ( ( ) ) 
406+ 		} , 
407+ 	} 
408+ } 
409+ 
307410impl < ES :  Deref ,  NS :  Deref ,  L :  Deref ,  MR :  Deref ,  OMH :  Deref ,  CMH :  Deref > 
308411OnionMessenger < ES ,  NS ,  L ,  MR ,  OMH ,  CMH > 
309412where 
@@ -457,40 +560,13 @@ where
457560/// soon we'll delegate the onion message to a handler that can generate invoices or send 
458561/// payments. 
459562fn  handle_onion_message ( & self ,  _peer_node_id :  & PublicKey ,  msg :  & msgs:: OnionMessage )  { 
460- 		let  control_tlvs_ss = match  self . node_signer . ecdh ( Recipient :: Node ,  & msg. blinding_point ,  None )  { 
461- 			Ok ( ss)  => ss, 
462- 			Err ( e)  =>  { 
463- 				log_error ! ( self . logger,  "Failed to retrieve node secret: {:?}" ,  e) ; 
464- 				return 
465- 			} 
466- 		} ; 
467- 		let  onion_decode_ss = { 
468- 			let  blinding_factor = { 
469- 				let  mut  hmac = HmacEngine :: < Sha256 > :: new ( b"blinded_node_id" ) ; 
470- 				hmac. input ( control_tlvs_ss. as_ref ( ) ) ; 
471- 				Hmac :: from_engine ( hmac) . into_inner ( ) 
472- 			} ; 
473- 			match  self . node_signer . ecdh ( Recipient :: Node ,  & msg. onion_routing_packet . public_key , 
474- 				Some ( & Scalar :: from_be_bytes ( blinding_factor) . unwrap ( ) ) ) 
475- 			{ 
476- 				Ok ( ss)  => ss. secret_bytes ( ) , 
477- 				Err ( ( ) )  => { 
478- 					log_trace ! ( self . logger,  "Failed to compute onion packet shared secret" ) ; 
479- 					return 
480- 				} 
481- 			} 
482- 		} ; 
483- 		match  onion_utils:: decode_next_untagged_hop ( 
484- 			onion_decode_ss,  & msg. onion_routing_packet . hop_data [ ..] ,  msg. onion_routing_packet . hmac , 
485- 			( control_tlvs_ss,  & * self . custom_handler ,  & * self . logger ) 
563+ 		match  peel_onion ( 
564+ 			& * self . node_signer ,  & self . secp_ctx ,  & * self . logger ,  & * self . custom_handler ,  msg
486565		)  { 
487- 			Ok ( ( Payload :: Receive :: < <<CMH  as  Deref >:: Target  as  CustomOnionMessageHandler >:: CustomMessage >  { 
488- 				message,  control_tlvs :  ReceiveControlTlvs :: Unblinded ( ReceiveTlvs  {  path_id } ) ,  reply_path, 
489- 			} ,  None ) )  => { 
566+ 			Ok ( PeeledOnion :: Receive ( message,  path_id,  reply_path) )  => { 
490567				log_trace ! ( self . logger, 
491568					"Received an onion message with path_id {:02x?} and {} reply_path" , 
492569						path_id,  if  reply_path. is_some( )  {  "a"  }  else {  "no"  } ) ; 
493- 
494570				let  response = match  message { 
495571					OnionMessageContents :: Offers ( msg)  => { 
496572						self . offers_handler . handle_message ( msg) 
@@ -501,50 +577,11 @@ where
501577							. map ( |msg| OnionMessageContents :: Custom ( msg) ) 
502578					} , 
503579				} ; 
504- 
505580				if  let  Some ( response)  = response { 
506581					self . respond_with_onion_message ( response,  path_id,  reply_path) ; 
507582				} 
508583			} , 
509- 			Ok ( ( Payload :: Forward ( ForwardControlTlvs :: Unblinded ( ForwardTlvs  { 
510- 				next_node_id,  next_blinding_override
511- 			} ) ) ,  Some ( ( next_hop_hmac,  new_packet_bytes) ) ) )  => { 
512- 				// TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy 
513- 				// blinded hop and this onion message is destined for us. In this situation, we should keep 
514- 				// unwrapping the onion layers to get to the final payload. Since we don't have the option 
515- 				// of creating blinded paths with dummy hops currently, we should be ok to not handle this 
516- 				// for now. 
517- 				let  new_pubkey = match  onion_utils:: next_hop_pubkey ( & self . secp_ctx ,  msg. onion_routing_packet . public_key ,  & onion_decode_ss)  { 
518- 					Ok ( pk)  => pk, 
519- 					Err ( e)  => { 
520- 						log_trace ! ( self . logger,  "Failed to compute next hop packet pubkey: {}" ,  e) ; 
521- 						return 
522- 					} 
523- 				} ; 
524- 				let  outgoing_packet = Packet  { 
525- 					version :  0 , 
526- 					public_key :  new_pubkey, 
527- 					hop_data :  new_packet_bytes, 
528- 					hmac :  next_hop_hmac, 
529- 				} ; 
530- 				let  onion_message = msgs:: OnionMessage  { 
531- 					blinding_point :  match  next_blinding_override { 
532- 						Some ( blinding_point)  => blinding_point, 
533- 						None  => { 
534- 							match  onion_utils:: next_hop_pubkey ( 
535- 								& self . secp_ctx ,  msg. blinding_point ,  control_tlvs_ss. as_ref ( ) 
536- 							)  { 
537- 								Ok ( bp)  => bp, 
538- 								Err ( e)  => { 
539- 									log_trace ! ( self . logger,  "Failed to compute next blinding point: {}" ,  e) ; 
540- 									return 
541- 								} 
542- 							} 
543- 						} 
544- 					} , 
545- 					onion_routing_packet :  outgoing_packet, 
546- 				} ; 
547- 
584+ 			Ok ( PeeledOnion :: Forward ( next_node_id,  onion_message) )  => { 
548585				let  mut  pending_per_peer_msgs = self . pending_messages . lock ( ) . unwrap ( ) ; 
549586				if  outbound_buffer_full ( & next_node_id,  & pending_per_peer_msgs)  { 
550587					log_trace ! ( self . logger,  "Dropping forwarded onion message to peer {:?}: outbound buffer full" ,  next_node_id) ; 
@@ -563,15 +600,12 @@ where
563600						e. get_mut ( ) . push_back ( onion_message) ; 
564601						log_trace ! ( self . logger,  "Forwarding an onion message to peer {}" ,  next_node_id) ; 
565602					} 
566- 				} ; 
603+ 				} 
567604			} , 
568605			Err ( e)  => { 
569- 				log_trace ! ( self . logger,  "Errored decoding onion message packet: {:?}" ,  e) ; 
570- 			} , 
571- 			_ => { 
572- 				log_trace ! ( self . logger,  "Received bogus onion message packet, either the sender encoded a final hop as a forwarding hop or vice versa" ) ; 
573- 			} , 
574- 		} ; 
606+ 				log_error ! ( self . logger,  "Failed to process onion message {:?}" ,  e) ; 
607+ 			} 
608+ 		} 
575609	} 
576610
577611	fn  peer_connected ( & self ,  their_node_id :  & PublicKey ,  init :  & msgs:: Init ,  _inbound :  bool )  -> Result < ( ) ,  ( ) >  { 
0 commit comments