@@ -424,6 +424,24 @@ 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
+ 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
+
427
445
/// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`].
428
446
///
429
447
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
@@ -542,9 +560,15 @@ impl InvoiceRequest {
542
560
///
543
561
/// Errors if the request contains unknown required features.
544
562
///
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
+ ///
545
568
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
546
569
///
547
570
/// [`Bolt12Invoice::created_at`]: crate::offers::invoice::Bolt12Invoice::created_at
571
+ /// [`OfferBuilder::deriving_signing_pubkey`]: crate::offers::offer::OfferBuilder::deriving_signing_pubkey
548
572
pub fn respond_with_no_std (
549
573
& self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
550
574
created_at : core:: time:: Duration
@@ -556,6 +580,63 @@ impl InvoiceRequest {
556
580
InvoiceBuilder :: for_offer ( self , payment_paths, created_at, payment_hash)
557
581
}
558
582
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
+
559
640
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
560
641
/// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use
561
642
/// the same [`ExpandedKey`] as the one used to create the offer.
@@ -566,17 +647,14 @@ impl InvoiceRequest {
566
647
///
567
648
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
568
649
#[ 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
572
652
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
573
653
let created_at = std:: time:: SystemTime :: now ( )
574
654
. duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
575
655
. expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ;
576
656
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)
580
658
}
581
659
582
660
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
@@ -588,42 +666,22 @@ impl InvoiceRequest {
588
666
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
589
667
///
590
668
/// [`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 (
592
670
& 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
594
672
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
595
- if self . invoice_request_features ( ) . requires_unknown_bits ( ) {
673
+ if self . inner . invoice_request_features ( ) . requires_unknown_bits ( ) {
596
674
return Err ( Bolt12SemanticError :: UnknownRequiredFeatures ) ;
597
675
}
598
676
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,
603
680
} ;
604
681
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
+ )
627
685
}
628
686
}
629
687
0 commit comments