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