@@ -398,6 +398,22 @@ pub struct InvoiceRequest {
398
398
signature : Signature ,
399
399
}
400
400
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
+
401
417
/// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`].
402
418
///
403
419
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
@@ -521,6 +537,60 @@ impl InvoiceRequest {
521
537
InvoiceBuilder :: for_offer ( self , payment_paths, created_at, payment_hash)
522
538
}
523
539
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
+
524
594
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
525
595
/// derived signing keys from the originating [`Offer`] to sign the [`Bolt12Invoice`]. Must use
526
596
/// the same [`ExpandedKey`] as the one used to create the offer.
@@ -531,17 +601,14 @@ impl InvoiceRequest {
531
601
///
532
602
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
533
603
#[ 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
537
606
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
538
607
let created_at = std:: time:: SystemTime :: now ( )
539
608
. duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
540
609
. expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ;
541
610
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)
545
612
}
546
613
547
614
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
@@ -553,42 +620,22 @@ impl InvoiceRequest {
553
620
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
554
621
///
555
622
/// [`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 (
557
624
& 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
559
626
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , Bolt12SemanticError > {
560
- if self . features ( ) . requires_unknown_bits ( ) {
627
+ if self . inner . features ( ) . requires_unknown_bits ( ) {
561
628
return Err ( Bolt12SemanticError :: UnknownRequiredFeatures ) ;
562
629
}
563
630
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,
568
634
} ;
569
635
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
+ )
592
639
}
593
640
}
594
641
0 commit comments