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