@@ -71,6 +71,7 @@ use crate::io;
71
71
use crate :: ln:: channelmanager:: PaymentId ;
72
72
use crate :: ln:: inbound_payment:: { ExpandedKey , IV_LEN } ;
73
73
use crate :: ln:: msgs:: DecodeError ;
74
+ use crate :: offers:: invoice:: { DerivedSigningPubkey , ExplicitSigningPubkey , SigningPubkeyStrategy } ;
74
75
use crate :: offers:: merkle:: {
75
76
self , SignError , SignFn , SignatureTlvStream , SignatureTlvStreamRef , TaggedHash , TlvStream ,
76
77
} ;
@@ -96,7 +97,7 @@ use bitcoin::secp256k1::schnorr::Signature;
96
97
use bitcoin:: secp256k1:: { self , Keypair , PublicKey , Secp256k1 } ;
97
98
98
99
#[ cfg( not( c_bindings) ) ]
99
- use crate :: offers:: invoice:: { DerivedSigningPubkey , ExplicitSigningPubkey , InvoiceBuilder } ;
100
+ use crate :: offers:: invoice:: InvoiceBuilder ;
100
101
#[ cfg( c_bindings) ]
101
102
use crate :: offers:: invoice:: {
102
103
InvoiceWithDerivedSigningPubkeyBuilder , InvoiceWithExplicitSigningPubkeyBuilder ,
@@ -615,6 +616,63 @@ pub struct VerifiedInvoiceRequestLegacy {
615
616
pub keys : Option < Keypair > ,
616
617
}
617
618
619
+ /// An [`InvoiceRequest`] that has been verified by [`InvoiceRequest::verify_using_metadata`] or
620
+ /// [`InvoiceRequest::verify_using_recipient_data`] and exposes different ways to respond depending
621
+ /// on whether the signing keys were derived.
622
+ #[ derive( Clone , Debug ) ]
623
+ pub struct VerifiedInvoiceRequest < S : SigningPubkeyStrategy > {
624
+ /// The identifier of the [`Offer`] for which the [`InvoiceRequest`] was made.
625
+ pub offer_id : OfferId ,
626
+
627
+ /// The verified request.
628
+ pub ( crate ) inner : InvoiceRequest ,
629
+
630
+ /// Keys for signing a [`Bolt12Invoice`] for the request.
631
+ ///
632
+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
633
+ pub keys : S ,
634
+ }
635
+
636
+ /// Represents a [`VerifiedInvoiceRequest`], along with information about how the resulting
637
+ /// [`Bolt12Invoice`] should be signed.
638
+ ///
639
+ /// The signing strategy determines whether the signing keys are:
640
+ /// - Derived either from the originating [`Offer`]’s metadata or recipient_data, or
641
+ /// - Explicitly provided.
642
+ ///
643
+ /// This distinction is required to produce a valid, signed [`Bolt12Invoice`] from a verified request.
644
+ ///
645
+ /// For more on key derivation strategies, see:
646
+ /// [`InvoiceRequest::verify_using_metadata`] and [`InvoiceRequest::verify_using_recipient_data`].
647
+ ///
648
+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
649
+ pub enum InvoiceRequestVerifiedFromOffer {
650
+ /// A verified invoice request that uses signing keys derived from the originating [`Offer`]’s metadata or recipient_data.
651
+ DerivedKeys ( VerifiedInvoiceRequest < DerivedSigningPubkey > ) ,
652
+ /// A verified invoice request that requires explicitly provided signing keys to sign the resulting [`Bolt12Invoice`].
653
+ ///
654
+ /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
655
+ ExplicitKeys ( VerifiedInvoiceRequest < ExplicitSigningPubkey > ) ,
656
+ }
657
+
658
+ impl InvoiceRequestVerifiedFromOffer {
659
+ /// Returns a reference to the underlying `InvoiceRequest`.
660
+ fn inner ( & self ) -> & InvoiceRequest {
661
+ match self {
662
+ InvoiceRequestVerifiedFromOffer :: DerivedKeys ( req) => & req. inner ,
663
+ InvoiceRequestVerifiedFromOffer :: ExplicitKeys ( req) => & req. inner ,
664
+ }
665
+ }
666
+
667
+ /// Returns the `OfferId` of the offer this invoice request is for.
668
+ pub fn offer_id ( & self ) -> OfferId {
669
+ match self {
670
+ InvoiceRequestVerifiedFromOffer :: DerivedKeys ( req) => req. offer_id ,
671
+ InvoiceRequestVerifiedFromOffer :: ExplicitKeys ( req) => req. offer_id ,
672
+ }
673
+ }
674
+ }
675
+
618
676
/// The contents of an [`InvoiceRequest`], which may be shared with an [`Bolt12Invoice`].
619
677
///
620
678
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
@@ -1024,6 +1082,24 @@ impl VerifiedInvoiceRequestLegacy {
1024
1082
) ;
1025
1083
}
1026
1084
1085
+ impl VerifiedInvoiceRequest < DerivedSigningPubkey > {
1086
+ offer_accessors ! ( self , self . inner. contents. inner. offer) ;
1087
+ invoice_request_accessors ! ( self , self . inner. contents) ;
1088
+ fields_accessor ! ( self , self . inner. contents) ;
1089
+ }
1090
+
1091
+ impl VerifiedInvoiceRequest < ExplicitSigningPubkey > {
1092
+ offer_accessors ! ( self , self . inner. contents. inner. offer) ;
1093
+ invoice_request_accessors ! ( self , self . inner. contents) ;
1094
+ fields_accessor ! ( self , self . inner. contents) ;
1095
+ }
1096
+
1097
+ impl InvoiceRequestVerifiedFromOffer {
1098
+ offer_accessors ! ( self , self . inner( ) . contents. inner. offer) ;
1099
+ invoice_request_accessors ! ( self , self . inner( ) . contents) ;
1100
+ fields_accessor ! ( self , self . inner( ) . contents) ;
1101
+ }
1102
+
1027
1103
/// `String::truncate(new_len)` panics if you split inside a UTF-8 code point,
1028
1104
/// which would leave the `String` containing invalid UTF-8. This function will
1029
1105
/// instead truncate the string to the next smaller code point boundary so the
0 commit comments