@@ -151,19 +151,26 @@ impl OfferBuilder {
151
151
152
152
/// Sets the [`Offer::metadata`] to the given bytes.
153
153
///
154
- /// Successive calls to this method will override the previous setting and any previous calls to
155
- /// [`OfferBuilder::metadata_derived`].
156
- pub fn metadata ( mut self , metadata : Vec < u8 > ) -> Self {
154
+ /// Successive calls to this method will override the previous setting. Errors if the builder
155
+ /// was constructed with [`SigningPubkey::Derived`].
156
+ pub fn metadata ( mut self , metadata : Vec < u8 > ) -> Result < Self , SemanticError > {
157
+ if self . offer . signing_pubkey . is_none ( ) {
158
+ return Err ( SemanticError :: UnexpectedMetadata ) ;
159
+ }
160
+
157
161
self . offer . metadata = Some ( metadata) ;
158
162
self . hmac = None ;
159
- self
163
+ Ok ( self )
160
164
}
161
165
162
166
/// Sets the [`Offer::metadata`] derived from the given `key` and any fields set prior to
163
- /// calling [`OfferBuilder::build`].
167
+ /// calling [`OfferBuilder::build`]. Allows for stateless verification of an [`InvoiceRequest`].
164
168
///
165
169
/// Successive calls to this method will override the previous setting and any previous calls to
166
- /// [`OfferBuilder::metadata`].
170
+ /// [`OfferBuilder::metadata`]. Must be called if the builder was constructed with
171
+ /// [`SigningPubkey::Derived`] in order to derive [`Offer::signing_pubkey`].
172
+ ///
173
+ /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
167
174
pub fn metadata_derived ( mut self , key : & ExpandedKey ) -> Self {
168
175
self . offer . metadata = None ;
169
176
self . hmac = Some ( key. hmac_for_offer ( ) ) ;
@@ -239,8 +246,13 @@ impl OfferBuilder {
239
246
}
240
247
}
241
248
249
+ // Created the metadata for stateless verification and derive the signing_pubkey, if needed.
242
250
if let Some ( mut hmac) = self . hmac {
243
- self . offer . write ( & mut hmac) . unwrap ( ) ;
251
+ debug_assert ! ( self . offer. metadata. is_none( ) ) ;
252
+ let mut tlv_stream = self . offer . as_tlv_stream ( ) ;
253
+ tlv_stream. node_id = None ;
254
+ tlv_stream. write ( & mut hmac) . unwrap ( ) ;
255
+
244
256
self . offer . metadata = Some ( Hmac :: from_engine ( hmac) . into_inner ( ) . to_vec ( ) ) ;
245
257
}
246
258
@@ -533,10 +545,11 @@ impl OfferContents {
533
545
let mut hmac = key. hmac_for_offer ( ) ;
534
546
535
547
for record in tlv_stream. range ( OFFER_TYPES ) {
536
- if record. r#type != OFFER_METADATA_TYPE {
537
- hmac. input ( record. record_bytes ) ;
538
- } else {
548
+ match record. r#type {
539
549
// TODO: Assert value bytes == metadata?
550
+ OFFER_METADATA_TYPE => { } ,
551
+ OFFER_NODE_ID_TYPE => { } ,
552
+ _ => hmac. input ( record. record_bytes ) ,
540
553
}
541
554
}
542
555
@@ -638,6 +651,9 @@ const OFFER_TYPES: core::ops::Range<u64> = 1..80;
638
651
/// TLV record type for [`Offer::metadata`].
639
652
const OFFER_METADATA_TYPE : u64 = 4 ;
640
653
654
+ /// TLV record type for [`Offer::signing_pubkey`].
655
+ const OFFER_NODE_ID_TYPE : u64 = 22 ;
656
+
641
657
tlv_stream ! ( OfferTlvStream , OfferTlvStreamRef , OFFER_TYPES , {
642
658
( 2 , chains: ( Vec <ChainHash >, WithoutLength ) ) ,
643
659
( OFFER_METADATA_TYPE , metadata: ( Vec <u8 >, WithoutLength ) ) ,
@@ -649,7 +665,7 @@ tlv_stream!(OfferTlvStream, OfferTlvStreamRef, OFFER_TYPES, {
649
665
( 16 , paths: ( Vec <BlindedPath >, WithoutLength ) ) ,
650
666
( 18 , issuer: ( String , WithoutLength ) ) ,
651
667
( 20 , quantity_max: ( u64 , HighZeroBytesDroppedBigSize ) ) ,
652
- ( 22 , node_id: PublicKey ) ,
668
+ ( OFFER_NODE_ID_TYPE , node_id: PublicKey ) ,
653
669
} ) ;
654
670
655
671
impl Bech32Encode for Offer {
@@ -865,15 +881,15 @@ mod tests {
865
881
#[ test]
866
882
fn builds_offer_with_metadata ( ) {
867
883
let offer = OfferBuilder :: new ( "foo" . into ( ) , pubkey ( 42 ) . into ( ) )
868
- . metadata ( vec ! [ 42 ; 32 ] )
884
+ . metadata ( vec ! [ 42 ; 32 ] ) . unwrap ( )
869
885
. build ( )
870
886
. unwrap ( ) ;
871
887
assert_eq ! ( offer. metadata( ) , Some ( & vec![ 42 ; 32 ] ) ) ;
872
888
assert_eq ! ( offer. as_tlv_stream( ) . metadata, Some ( & vec![ 42 ; 32 ] ) ) ;
873
889
874
890
let offer = OfferBuilder :: new ( "foo" . into ( ) , pubkey ( 42 ) . into ( ) )
875
- . metadata ( vec ! [ 42 ; 32 ] )
876
- . metadata ( vec ! [ 43 ; 32 ] )
891
+ . metadata ( vec ! [ 42 ; 32 ] ) . unwrap ( )
892
+ . metadata ( vec ! [ 43 ; 32 ] ) . unwrap ( )
877
893
. build ( )
878
894
. unwrap ( ) ;
879
895
assert_eq ! ( offer. metadata( ) , Some ( & vec![ 43 ; 32 ] ) ) ;
0 commit comments