@@ -424,6 +424,24 @@ pub struct InvoiceRequest {
424424 signature : Signature ,
425425}
426426
427+ /// An [`InvoiceRequest`] that has been verified by [`InvoiceRequest::verify`] and exposes different
428+ /// ways to respond depending on whether the signing keys were derived.
429+ #[ derive( Clone , Debug ) ]
430+ pub struct VerifiedInvoiceRequest {
431+ /// The verified request.
432+ inner : InvoiceRequest ,
433+
434+ /// Keys used for signing a [`Bolt12Invoice`] if they can be derived.
435+ ///
436+ /// If `Some`, must call [`respond_using_derived_keys`] when responding. Otherwise, call
437+ /// [`respond_with`].
438+ ///
439+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
440+ /// [`respond_using_derived_keys`]: Self::respond_using_derived_keys
441+ /// [`respond_with`]: Self::respond_with
442+ pub keys : Option < KeyPair > ,
443+ }
444+
427445/// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`].
428446///
429447/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
@@ -542,9 +560,15 @@ impl InvoiceRequest {
542560 ///
543561 /// Errors if the request contains unknown required features.
544562 ///
563+ /// # Note
564+ ///
565+ /// If the originating [`Offer`] was created using [`OfferBuilder::deriving_signing_pubkey`],
566+ /// then use [`InvoiceRequest::verify`] and [`VerifiedInvoiceRequest`] methods instead.
567+ ///
545568 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
546569 ///
547570 /// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
571+ /// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
548572 pub fn respond_with_no_std (
549573 & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
550574 created_at : core:: time:: Duration
@@ -556,6 +580,63 @@ impl InvoiceRequest {
556580 InvoiceBuilder :: for_offer ( self , payment_paths, created_at, payment_hash)
557581 }
558582
583+ /// Verifies that the request was for an offer created using the given key. Returns the verified
584+ /// request which contains the derived keys needed to sign a [`Bolt12Invoice`] for the request
585+ /// if they could be extracted from the metadata.
586+ ///
587+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
588+ pub fn verify < T : secp256k1:: Signing > (
589+ self , key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
590+ ) -> Result < VerifiedInvoiceRequest , ( ) > {
591+ let keys = self . contents . inner . offer . verify ( & self . bytes , key, secp_ctx) ?;
592+ Ok ( VerifiedInvoiceRequest {
593+ inner : self ,
594+ keys,
595+ } )
596+ }
597+
598+ #[ cfg( test) ]
599+ fn as_tlv_stream ( & self ) -> FullInvoiceRequestTlvStreamRef {
600+ let ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
601+ self . contents . as_tlv_stream ( ) ;
602+ let signature_tlv_stream = SignatureTlvStreamRef {
603+ signature : Some ( & self . signature ) ,
604+ } ;
605+ ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, signature_tlv_stream)
606+ }
607+ }
608+
609+ impl VerifiedInvoiceRequest {
610+ offer_accessors ! ( self , self . inner. contents. inner. offer) ;
611+ invoice_request_accessors ! ( self , self . inner. contents) ;
612+
613+ /// Creates an [`InvoiceBuilder`] for the request with the given required fields and using the
614+ /// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
615+ ///
616+ /// See [`InvoiceRequest::respond_with_no_std`] for further details.
617+ ///
618+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
619+ ///
620+ /// [`Duration`]: core::time::Duration
621+ #[ cfg( feature = "std" ) ]
622+ pub fn respond_with (
623+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash
624+ ) -> Result < InvoiceBuilder < ExplicitSigningPubkey > , Bolt12SemanticError > {
625+ self . inner . respond_with ( payment_paths, payment_hash)
626+ }
627+
628+ /// Creates an [`InvoiceBuilder`] for the request with the given required fields.
629+ ///
630+ /// See [`InvoiceRequest::respond_with_no_std`] for further details.
631+ ///
632+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
633+ pub fn respond_with_no_std (
634+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
635+ created_at : core:: time:: Duration
636+ ) -> Result < InvoiceBuilder < ExplicitSigningPubkey > , Bolt12SemanticError > {
637+ self . inner . respond_with_no_std ( payment_paths, payment_hash, created_at)
638+ }
639+
559640 /// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
560641 /// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use
561642 /// the same [`ExpandedKey`] as the one used to create the offer.
@@ -566,17 +647,14 @@ impl InvoiceRequest {
566647 ///
567648 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
568649 #[ cfg( feature = "std" ) ]
569- pub fn verify_and_respond_using_derived_keys < T : secp256k1:: Signing > (
570- & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
571- expanded_key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
650+ pub fn respond_using_derived_keys (
651+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash
572652 ) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
573653 let created_at = std:: time:: SystemTime :: now ( )
574654 . duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
575655 . expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ;
576656
577- self . verify_and_respond_using_derived_keys_no_std (
578- payment_paths, payment_hash, created_at, expanded_key, secp_ctx
579- )
657+ self . respond_using_derived_keys_no_std ( payment_paths, payment_hash, created_at)
580658 }
581659
582660 /// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
@@ -588,42 +666,22 @@ impl InvoiceRequest {
588666 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
589667 ///
590668 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
591- pub fn verify_and_respond_using_derived_keys_no_std < T : secp256k1 :: Signing > (
669+ pub fn respond_using_derived_keys_no_std (
592670 & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
593- created_at : core:: time:: Duration , expanded_key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
671+ created_at : core:: time:: Duration
594672 ) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
595- if self . invoice_request_features ( ) . requires_unknown_bits ( ) {
673+ if self . inner . invoice_request_features ( ) . requires_unknown_bits ( ) {
596674 return Err ( Bolt12SemanticError :: UnknownRequiredFeatures ) ;
597675 }
598676
599- let keys = match self . verify ( expanded_key, secp_ctx) {
600- Err ( ( ) ) => return Err ( Bolt12SemanticError :: InvalidMetadata ) ,
601- Ok ( None ) => return Err ( Bolt12SemanticError :: InvalidMetadata ) ,
602- Ok ( Some ( keys) ) => keys,
677+ let keys = match self . keys {
678+ None => return Err ( Bolt12SemanticError :: InvalidMetadata ) ,
679+ Some ( keys) => keys,
603680 } ;
604681
605- InvoiceBuilder :: for_offer_using_keys ( self , payment_paths, created_at, payment_hash, keys)
606- }
607-
608- /// Verifies that the request was for an offer created using the given key. Returns the derived
609- /// keys need to sign an [`Bolt12Invoice`] for the request if they could be extracted from the
610- /// metadata.
611- ///
612- /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
613- pub fn verify < T : secp256k1:: Signing > (
614- & self , key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
615- ) -> Result < Option < KeyPair > , ( ) > {
616- self . contents . inner . offer . verify ( & self . bytes , key, secp_ctx)
617- }
618-
619- #[ cfg( test) ]
620- fn as_tlv_stream ( & self ) -> FullInvoiceRequestTlvStreamRef {
621- let ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
622- self . contents . as_tlv_stream ( ) ;
623- let signature_tlv_stream = SignatureTlvStreamRef {
624- signature : Some ( & self . signature ) ,
625- } ;
626- ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, signature_tlv_stream)
682+ InvoiceBuilder :: for_offer_using_keys (
683+ & self . inner , payment_paths, created_at, payment_hash, keys
684+ )
627685 }
628686}
629687
0 commit comments