@@ -424,6 +424,22 @@ 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+ pub inner : InvoiceRequest ,
433+
434+ /// Keys used for signing a [`Bolt12Invoice`] if they can be derived.
435+ ///
436+ /// If `Some`, then must respond with methods that use derived keys. Otherwise, should respond
437+ /// with an invoice signed explicitly.
438+ ///
439+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
440+ pub keys : Option < KeyPair > ,
441+ }
442+
427443/// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`].
428444///
429445/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
@@ -556,6 +572,60 @@ impl InvoiceRequest {
556572 InvoiceBuilder :: for_offer ( self , payment_paths, created_at, payment_hash)
557573 }
558574
575+ /// Verifies that the request was for an offer created using the given key. Returns the verified
576+ /// request along with the derived keys needed to sign a [`Bolt12Invoice`] for the request if
577+ /// they could be extracted from the metadata.
578+ ///
579+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
580+ pub fn verify < T : secp256k1:: Signing > (
581+ self , key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
582+ ) -> Result < VerifiedInvoiceRequest , ( ) > {
583+ let keys = self . contents . inner . offer . verify ( & self . bytes , key, secp_ctx) ?;
584+ Ok ( VerifiedInvoiceRequest {
585+ inner : self ,
586+ keys,
587+ } )
588+ }
589+
590+ #[ cfg( test) ]
591+ fn as_tlv_stream ( & self ) -> FullInvoiceRequestTlvStreamRef {
592+ let ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
593+ self . contents . as_tlv_stream ( ) ;
594+ let signature_tlv_stream = SignatureTlvStreamRef {
595+ signature : Some ( & self . signature ) ,
596+ } ;
597+ ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, signature_tlv_stream)
598+ }
599+ }
600+
601+ impl VerifiedInvoiceRequest {
602+ /// Creates an [`InvoiceBuilder`] for the request with the given required fields and using the
603+ /// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
604+ ///
605+ /// See [`InvoiceRequest::respond_with_no_std`] for further details.
606+ ///
607+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
608+ ///
609+ /// [`Duration`]: core::time::Duration
610+ #[ cfg( feature = "std" ) ]
611+ pub fn respond_with (
612+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash
613+ ) -> Result < InvoiceBuilder < ExplicitSigningPubkey > , Bolt12SemanticError > {
614+ self . inner . respond_with ( payment_paths, payment_hash)
615+ }
616+
617+ /// Creates an [`InvoiceBuilder`] for the request with the given required fields.
618+ ///
619+ /// See [`InvoiceRequest::respond_with_no_std`] for further details.
620+ ///
621+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
622+ pub fn respond_with_no_std (
623+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
624+ created_at : core:: time:: Duration
625+ ) -> Result < InvoiceBuilder < ExplicitSigningPubkey > , Bolt12SemanticError > {
626+ self . inner . respond_with_no_std ( payment_paths, payment_hash, created_at)
627+ }
628+
559629 /// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
560630 /// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use
561631 /// the same [`ExpandedKey`] as the one used to create the offer.
@@ -566,17 +636,14 @@ impl InvoiceRequest {
566636 ///
567637 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
568638 #[ 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 >
639+ pub fn respond_using_derived_keys (
640+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash
572641 ) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
573642 let created_at = std:: time:: SystemTime :: now ( )
574643 . duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
575644 . expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ;
576645
577- self . verify_and_respond_using_derived_keys_no_std (
578- payment_paths, payment_hash, created_at, expanded_key, secp_ctx
579- )
646+ self . respond_using_derived_keys_no_std ( payment_paths, payment_hash, created_at)
580647 }
581648
582649 /// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
@@ -588,42 +655,22 @@ impl InvoiceRequest {
588655 /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
589656 ///
590657 /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
591- pub fn verify_and_respond_using_derived_keys_no_std < T : secp256k1 :: Signing > (
658+ pub fn respond_using_derived_keys_no_std (
592659 & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
593- created_at : core:: time:: Duration , expanded_key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
660+ created_at : core:: time:: Duration
594661 ) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
595- if self . invoice_request_features ( ) . requires_unknown_bits ( ) {
662+ if self . inner . invoice_request_features ( ) . requires_unknown_bits ( ) {
596663 return Err ( Bolt12SemanticError :: UnknownRequiredFeatures ) ;
597664 }
598665
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,
666+ let keys = match self . keys {
667+ None => return Err ( Bolt12SemanticError :: InvalidMetadata ) ,
668+ Some ( keys) => keys,
603669 } ;
604670
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)
671+ InvoiceBuilder :: for_offer_using_keys (
672+ & self . inner , payment_paths, created_at, payment_hash, keys
673+ )
627674 }
628675}
629676
0 commit comments