@@ -424,6 +424,22 @@ pub struct InvoiceRequest {
424
424
signature : Signature ,
425
425
}
426
426
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
+
427
443
/// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`].
428
444
///
429
445
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
@@ -556,6 +572,60 @@ impl InvoiceRequest {
556
572
InvoiceBuilder :: for_offer ( self , payment_paths, created_at, payment_hash)
557
573
}
558
574
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
+
559
629
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
560
630
/// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use
561
631
/// the same [`ExpandedKey`] as the one used to create the offer.
@@ -566,17 +636,14 @@ impl InvoiceRequest {
566
636
///
567
637
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
568
638
#[ 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
572
641
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
573
642
let created_at = std:: time:: SystemTime :: now ( )
574
643
. duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
575
644
. expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ;
576
645
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)
580
647
}
581
648
582
649
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
@@ -588,42 +655,22 @@ impl InvoiceRequest {
588
655
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
589
656
///
590
657
/// [`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 (
592
659
& 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
594
661
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
595
- if self . invoice_request_features ( ) . requires_unknown_bits ( ) {
662
+ if self . inner . invoice_request_features ( ) . requires_unknown_bits ( ) {
596
663
return Err ( Bolt12SemanticError :: UnknownRequiredFeatures ) ;
597
664
}
598
665
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,
603
669
} ;
604
670
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
+ )
627
674
}
628
675
}
629
676
0 commit comments