@@ -398,6 +398,22 @@ pub struct InvoiceRequest {
398398	signature :  Signature , 
399399} 
400400
401+ /// An [`InvoiceRequest`] that has been verified by [`InvoiceRequest::verify`] and exposes different 
402+ /// ways to respond depending on whether the signing keys were derived. 
403+ #[ derive( Clone ,  Debug ) ]  
404+ pub  struct  VerifiedInvoiceRequest  { 
405+ 	/// The verified request. 
406+  	pub  inner :  InvoiceRequest , 
407+ 
408+ 	/// Keys used for signing a [`Bolt12Invoice`] if they can be derived. 
409+  	/// 
410+  	/// If `Some`, then must respond with methods that use derived keys. Otherwise, should respond 
411+  	/// with an invoice signed explicitly. 
412+  	/// 
413+  	/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice 
414+  	pub  keys :  Option < KeyPair > , 
415+ } 
416+ 
401417/// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`]. 
402418/// 
403419/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice 
@@ -521,6 +537,60 @@ impl InvoiceRequest {
521537		InvoiceBuilder :: for_offer ( self ,  payment_paths,  created_at,  payment_hash) 
522538	} 
523539
540+ 	/// Verifies that the request was for an offer created using the given key. Returns the verified 
541+  	/// request along with the derived keys needed to sign a [`Bolt12Invoice`] for the request if 
542+  	/// they could be extracted from the metadata. 
543+  	/// 
544+  	/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice 
545+  	pub  fn  verify < T :  secp256k1:: Signing > ( 
546+ 		self ,  key :  & ExpandedKey ,  secp_ctx :  & Secp256k1 < T > 
547+ 	)  -> Result < VerifiedInvoiceRequest ,  ( ) >  { 
548+ 		let  keys = self . contents . inner . offer . verify ( & self . bytes ,  key,  secp_ctx) ?; 
549+ 		Ok ( VerifiedInvoiceRequest  { 
550+ 			inner :  self , 
551+ 			keys, 
552+ 		} ) 
553+ 	} 
554+ 
555+ 	#[ cfg( test) ]  
556+ 	fn  as_tlv_stream ( & self )  -> FullInvoiceRequestTlvStreamRef  { 
557+ 		let  ( payer_tlv_stream,  offer_tlv_stream,  invoice_request_tlv_stream)  =
558+ 			self . contents . as_tlv_stream ( ) ; 
559+ 		let  signature_tlv_stream = SignatureTlvStreamRef  { 
560+ 			signature :  Some ( & self . signature ) , 
561+ 		} ; 
562+ 		( payer_tlv_stream,  offer_tlv_stream,  invoice_request_tlv_stream,  signature_tlv_stream) 
563+ 	} 
564+ } 
565+ 
566+ impl  VerifiedInvoiceRequest  { 
567+ 	/// Creates an [`InvoiceBuilder`] for the request with the given required fields and using the 
568+  	/// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time. 
569+  	/// 
570+  	/// See [`InvoiceRequest::respond_with_no_std`] for further details. 
571+  	/// 
572+  	/// This is not exported to bindings users as builder patterns don't map outside of move semantics. 
573+  	/// 
574+  	/// [`Duration`]: core::time::Duration 
575+  	#[ cfg( feature = "std" ) ]  
576+ 	pub  fn  respond_with ( 
577+ 		& self ,  payment_paths :  Vec < ( BlindedPayInfo ,  BlindedPath ) > ,  payment_hash :  PaymentHash 
578+ 	)  -> Result < InvoiceBuilder < ExplicitSigningPubkey > ,  Bolt12SemanticError >  { 
579+ 		self . inner . respond_with ( payment_paths,  payment_hash) 
580+ 	} 
581+ 
582+ 	/// Creates an [`InvoiceBuilder`] for the request with the given required fields. 
583+  	/// 
584+  	/// See [`InvoiceRequest::respond_with_no_std`] for further details. 
585+  	/// 
586+  	/// This is not exported to bindings users as builder patterns don't map outside of move semantics. 
587+  	pub  fn  respond_with_no_std ( 
588+ 		& self ,  payment_paths :  Vec < ( BlindedPayInfo ,  BlindedPath ) > ,  payment_hash :  PaymentHash , 
589+ 		created_at :  core:: time:: Duration 
590+ 	)  -> Result < InvoiceBuilder < ExplicitSigningPubkey > ,  Bolt12SemanticError >  { 
591+ 		self . inner . respond_with_no_std ( payment_paths,  payment_hash,  created_at) 
592+ 	} 
593+ 
524594	/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses 
525595 	/// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use 
526596 	/// the same [`ExpandedKey`] as the one used to create the offer. 
@@ -531,17 +601,14 @@ impl InvoiceRequest {
531601 	/// 
532602 	/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice 
533603 	#[ cfg( feature = "std" ) ]  
534- 	pub  fn  verify_and_respond_using_derived_keys < T :  secp256k1:: Signing > ( 
535- 		& self ,  payment_paths :  Vec < ( BlindedPayInfo ,  BlindedPath ) > ,  payment_hash :  PaymentHash , 
536- 		expanded_key :  & ExpandedKey ,  secp_ctx :  & Secp256k1 < T > 
604+ 	pub  fn  respond_using_derived_keys ( 
605+ 		& self ,  payment_paths :  Vec < ( BlindedPayInfo ,  BlindedPath ) > ,  payment_hash :  PaymentHash 
537606	)  -> Result < InvoiceBuilder < DerivedSigningPubkey > ,  Bolt12SemanticError >  { 
538607		let  created_at = std:: time:: SystemTime :: now ( ) 
539608			. duration_since ( std:: time:: SystemTime :: UNIX_EPOCH ) 
540609			. expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ; 
541610
542- 		self . verify_and_respond_using_derived_keys_no_std ( 
543- 			payment_paths,  payment_hash,  created_at,  expanded_key,  secp_ctx
544- 		) 
611+ 		self . respond_using_derived_keys_no_std ( payment_paths,  payment_hash,  created_at) 
545612	} 
546613
547614	/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses 
@@ -553,42 +620,22 @@ impl InvoiceRequest {
553620 	/// This is not exported to bindings users as builder patterns don't map outside of move semantics. 
554621 	/// 
555622 	/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice 
556-  	pub  fn  verify_and_respond_using_derived_keys_no_std < T :  secp256k1 :: Signing > ( 
623+  	pub  fn  respond_using_derived_keys_no_std ( 
557624		& self ,  payment_paths :  Vec < ( BlindedPayInfo ,  BlindedPath ) > ,  payment_hash :  PaymentHash , 
558- 		created_at :  core:: time:: Duration ,   expanded_key :   & ExpandedKey ,   secp_ctx :   & Secp256k1 < T > 
625+ 		created_at :  core:: time:: Duration 
559626	)  -> Result < InvoiceBuilder < DerivedSigningPubkey > ,  Bolt12SemanticError >  { 
560- 		if  self . features ( ) . requires_unknown_bits ( )  { 
627+ 		if  self . inner . features ( ) . requires_unknown_bits ( )  { 
561628			return  Err ( Bolt12SemanticError :: UnknownRequiredFeatures ) ; 
562629		} 
563630
564- 		let  keys = match  self . verify ( expanded_key,  secp_ctx)  { 
565- 			Err ( ( ) )  => return  Err ( Bolt12SemanticError :: InvalidMetadata ) , 
566- 			Ok ( None )  => return  Err ( Bolt12SemanticError :: InvalidMetadata ) , 
567- 			Ok ( Some ( keys) )  => keys, 
631+ 		let  keys = match  self . keys  { 
632+ 			None  => return  Err ( Bolt12SemanticError :: InvalidMetadata ) , 
633+ 			Some ( keys)  => keys, 
568634		} ; 
569635
570- 		InvoiceBuilder :: for_offer_using_keys ( self ,  payment_paths,  created_at,  payment_hash,  keys) 
571- 	} 
572- 
573- 	/// Verifies that the request was for an offer created using the given key. Returns the derived 
574-  	/// keys need to sign an [`Bolt12Invoice`] for the request if they could be extracted from the 
575-  	/// metadata. 
576-  	/// 
577-  	/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice 
578-  	pub  fn  verify < T :  secp256k1:: Signing > ( 
579- 		& self ,  key :  & ExpandedKey ,  secp_ctx :  & Secp256k1 < T > 
580- 	)  -> Result < Option < KeyPair > ,  ( ) >  { 
581- 		self . contents . inner . offer . verify ( & self . bytes ,  key,  secp_ctx) 
582- 	} 
583- 
584- 	#[ cfg( test) ]  
585- 	fn  as_tlv_stream ( & self )  -> FullInvoiceRequestTlvStreamRef  { 
586- 		let  ( payer_tlv_stream,  offer_tlv_stream,  invoice_request_tlv_stream)  =
587- 			self . contents . as_tlv_stream ( ) ; 
588- 		let  signature_tlv_stream = SignatureTlvStreamRef  { 
589- 			signature :  Some ( & self . signature ) , 
590- 		} ; 
591- 		( payer_tlv_stream,  offer_tlv_stream,  invoice_request_tlv_stream,  signature_tlv_stream) 
636+ 		InvoiceBuilder :: for_offer_using_keys ( 
637+ 			& self . inner ,  payment_paths,  created_at,  payment_hash,  keys
638+ 		) 
592639	} 
593640} 
594641
0 commit comments