@@ -399,6 +399,22 @@ pub struct InvoiceRequest {
399
399
signature : Signature ,
400
400
}
401
401
402
+ /// An [`InvoiceRequest`] that has been verified by [`InvoiceRequest::verify`] and exposes different
403
+ /// ways to respond depending on whether the signing keys were derived.
404
+ #[ derive( Clone , Debug ) ]
405
+ pub struct VerifiedInvoiceRequest {
406
+ /// The verified request.
407
+ pub inner : InvoiceRequest ,
408
+
409
+ /// Keys used for signing an [`Invoice`] if they can be derived.
410
+ ///
411
+ /// If `Some`, then must respond with methods that use derived keys. Otherwise, should respond
412
+ /// with an invoice signed explicitly.
413
+ ///
414
+ /// [`Invoice`]: crate::offers::invoice::Invoice
415
+ pub keys : Option < KeyPair > ,
416
+ }
417
+
402
418
/// The contents of an [`InvoiceRequest`], which may be shared with an [`Invoice`].
403
419
///
404
420
/// [`Invoice`]: crate::offers::invoice::Invoice
@@ -522,6 +538,60 @@ impl InvoiceRequest {
522
538
InvoiceBuilder :: for_offer ( self , payment_paths, created_at, payment_hash)
523
539
}
524
540
541
+ /// Verifies that the request was for an offer created using the given key. Returns the verified
542
+ /// request along with the derived keys needed to sign an [`Invoice`] for the request if they
543
+ /// could be extracted from the metadata.
544
+ ///
545
+ /// [`Invoice`]: crate::offers::invoice::Invoice
546
+ pub fn verify < T : secp256k1:: Signing > (
547
+ self , key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
548
+ ) -> Result < VerifiedInvoiceRequest , ( ) > {
549
+ let keys = self . contents . inner . offer . verify ( & self . bytes , key, secp_ctx) ?;
550
+ Ok ( VerifiedInvoiceRequest {
551
+ inner : self ,
552
+ keys,
553
+ } )
554
+ }
555
+
556
+ #[ cfg( test) ]
557
+ fn as_tlv_stream ( & self ) -> FullInvoiceRequestTlvStreamRef {
558
+ let ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
559
+ self . contents . as_tlv_stream ( ) ;
560
+ let signature_tlv_stream = SignatureTlvStreamRef {
561
+ signature : Some ( & self . signature ) ,
562
+ } ;
563
+ ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, signature_tlv_stream)
564
+ }
565
+ }
566
+
567
+ impl VerifiedInvoiceRequest {
568
+ /// Creates an [`InvoiceBuilder`] for the request with the given required fields and using the
569
+ /// [`Duration`] since [`std::time::SystemTime::UNIX_EPOCH`] as the creation time.
570
+ ///
571
+ /// See [`InvoiceRequest::respond_with_no_std`] for further details.
572
+ ///
573
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
574
+ ///
575
+ /// [`Duration`]: core::time::Duration
576
+ #[ cfg( feature = "std" ) ]
577
+ pub fn respond_with (
578
+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash
579
+ ) -> Result < InvoiceBuilder < ExplicitSigningPubkey > , SemanticError > {
580
+ self . inner . respond_with ( payment_paths, payment_hash)
581
+ }
582
+
583
+ /// Creates an [`InvoiceBuilder`] for the request with the given required fields.
584
+ ///
585
+ /// See [`InvoiceRequest::respond_with_no_std`] for further details.
586
+ ///
587
+ /// This is not exported to bindings users as builder patterns don't map outside of move semantics.
588
+ pub fn respond_with_no_std (
589
+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
590
+ created_at : core:: time:: Duration
591
+ ) -> Result < InvoiceBuilder < ExplicitSigningPubkey > , SemanticError > {
592
+ self . inner . respond_with_no_std ( payment_paths, payment_hash, created_at)
593
+ }
594
+
525
595
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
526
596
/// derived signing keys from the originating [`Offer`] to sign the [`Invoice`]. Must use the
527
597
/// same [`ExpandedKey`] as the one used to create the offer.
@@ -532,17 +602,14 @@ impl InvoiceRequest {
532
602
///
533
603
/// [`Invoice`]: crate::offers::invoice::Invoice
534
604
#[ cfg( feature = "std" ) ]
535
- pub fn verify_and_respond_using_derived_keys < T : secp256k1:: Signing > (
536
- & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
537
- expanded_key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
605
+ pub fn respond_using_derived_keys (
606
+ & self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash
538
607
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , SemanticError > {
539
608
let created_at = std:: time:: SystemTime :: now ( )
540
609
. duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
541
610
. expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ;
542
611
543
- self . verify_and_respond_using_derived_keys_no_std (
544
- payment_paths, payment_hash, created_at, expanded_key, secp_ctx
545
- )
612
+ self . respond_using_derived_keys_no_std ( payment_paths, payment_hash, created_at)
546
613
}
547
614
548
615
/// Creates an [`InvoiceBuilder`] for the request using the given required fields and that uses
@@ -554,42 +621,22 @@ impl InvoiceRequest {
554
621
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
555
622
///
556
623
/// [`Invoice`]: crate::offers::invoice::Invoice
557
- pub fn verify_and_respond_using_derived_keys_no_std < T : secp256k1 :: Signing > (
624
+ pub fn respond_using_derived_keys_no_std (
558
625
& self , payment_paths : Vec < ( BlindedPayInfo , BlindedPath ) > , payment_hash : PaymentHash ,
559
- created_at : core:: time:: Duration , expanded_key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
626
+ created_at : core:: time:: Duration
560
627
) -> Result < InvoiceBuilder < DerivedSigningPubkey > , SemanticError > {
561
- if self . features ( ) . requires_unknown_bits ( ) {
628
+ if self . inner . features ( ) . requires_unknown_bits ( ) {
562
629
return Err ( SemanticError :: UnknownRequiredFeatures ) ;
563
630
}
564
631
565
- let keys = match self . verify ( expanded_key, secp_ctx) {
566
- Err ( ( ) ) => return Err ( SemanticError :: InvalidMetadata ) ,
567
- Ok ( None ) => return Err ( SemanticError :: InvalidMetadata ) ,
568
- Ok ( Some ( keys) ) => keys,
632
+ let keys = match self . keys {
633
+ None => return Err ( SemanticError :: InvalidMetadata ) ,
634
+ Some ( keys) => keys,
569
635
} ;
570
636
571
- InvoiceBuilder :: for_offer_using_keys ( self , payment_paths, created_at, payment_hash, keys)
572
- }
573
-
574
- /// Verifies that the request was for an offer created using the given key. Returns the derived
575
- /// keys need to sign an [`Invoice`] for the request if they could be extracted from the
576
- /// metadata.
577
- ///
578
- /// [`Invoice`]: crate::offers::invoice::Invoice
579
- pub fn verify < T : secp256k1:: Signing > (
580
- & self , key : & ExpandedKey , secp_ctx : & Secp256k1 < T >
581
- ) -> Result < Option < KeyPair > , ( ) > {
582
- self . contents . inner . offer . verify ( & self . bytes , key, secp_ctx)
583
- }
584
-
585
- #[ cfg( test) ]
586
- fn as_tlv_stream ( & self ) -> FullInvoiceRequestTlvStreamRef {
587
- let ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream) =
588
- self . contents . as_tlv_stream ( ) ;
589
- let signature_tlv_stream = SignatureTlvStreamRef {
590
- signature : Some ( & self . signature ) ,
591
- } ;
592
- ( payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, signature_tlv_stream)
637
+ InvoiceBuilder :: for_offer_using_keys (
638
+ & self . inner , payment_paths, created_at, payment_hash, keys
639
+ )
593
640
}
594
641
}
595
642
0 commit comments