@@ -90,11 +90,11 @@ use crate::blinded_path::BlindedPath;
90
90
use crate :: ln:: channelmanager:: PaymentId ;
91
91
use crate :: ln:: features:: OfferFeatures ;
92
92
use crate :: ln:: inbound_payment:: { ExpandedKey , IV_LEN , Nonce } ;
93
- use crate :: ln:: msgs:: MAX_VALUE_MSAT ;
94
- use crate :: offers:: merkle:: TlvStream ;
93
+ use crate :: ln:: msgs:: { DecodeError , MAX_VALUE_MSAT } ;
94
+ use crate :: offers:: merkle:: { TaggedHash , TlvStream } ;
95
95
use crate :: offers:: parse:: { Bech32Encode , Bolt12ParseError , Bolt12SemanticError , ParsedMessage } ;
96
96
use crate :: offers:: signer:: { Metadata , MetadataMaterial , self } ;
97
- use crate :: util:: ser:: { HighZeroBytesDroppedBigSize , WithoutLength , Writeable , Writer } ;
97
+ use crate :: util:: ser:: { HighZeroBytesDroppedBigSize , Readable , WithoutLength , Writeable , Writer } ;
98
98
use crate :: util:: string:: PrintableString ;
99
99
100
100
#[ cfg( not( c_bindings) ) ]
@@ -114,6 +114,31 @@ use std::time::SystemTime;
114
114
115
115
pub ( super ) const IV_BYTES : & [ u8 ; IV_LEN ] = b"LDK Offer ~~~~~~" ;
116
116
117
+ /// An identifier for an [`Offer`] built using [`DerivedMetadata`].
118
+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
119
+ pub struct OfferId ( pub [ u8 ; 32 ] ) ;
120
+
121
+ impl OfferId {
122
+ const ID_TAG : & ' static str = "LDK Offer ID" ;
123
+
124
+ fn from_valid_offer_tlv_stream ( bytes : & [ u8 ] ) -> Self {
125
+ let tagged_hash = TaggedHash :: new ( Self :: ID_TAG , & bytes) ;
126
+ Self ( tagged_hash. to_bytes ( ) )
127
+ }
128
+ }
129
+
130
+ impl Writeable for OfferId {
131
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
132
+ self . 0 . write ( w)
133
+ }
134
+ }
135
+
136
+ impl Readable for OfferId {
137
+ fn read < R : io:: Read > ( r : & mut R ) -> Result < Self , DecodeError > {
138
+ Ok ( OfferId ( Readable :: read ( r) ?) )
139
+ }
140
+ }
141
+
117
142
/// Builds an [`Offer`] for the "offer to be paid" flow.
118
143
///
119
144
/// See [module-level documentation] for usage.
@@ -370,12 +395,15 @@ macro_rules! offer_builder_methods { (
370
395
let mut bytes = Vec :: new( ) ;
371
396
$self. offer. write( & mut bytes) . unwrap( ) ;
372
397
398
+ let id = OfferId :: from_valid_offer_tlv_stream( & bytes) ;
399
+
373
400
Offer {
374
401
bytes,
375
402
#[ cfg( not( c_bindings) ) ]
376
403
contents: $self. offer,
377
404
#[ cfg( c_bindings) ]
378
- contents: $self. offer. clone( )
405
+ contents: $self. offer. clone( ) ,
406
+ id,
379
407
}
380
408
}
381
409
} }
@@ -488,6 +516,7 @@ pub struct Offer {
488
516
// fields.
489
517
pub ( super ) bytes : Vec < u8 > ,
490
518
pub ( super ) contents : OfferContents ,
519
+ id : OfferId ,
491
520
}
492
521
493
522
/// The contents of an [`Offer`], which may be shared with an [`InvoiceRequest`] or a
@@ -577,6 +606,11 @@ macro_rules! offer_accessors { ($self: ident, $contents: expr) => {
577
606
impl Offer {
578
607
offer_accessors ! ( self , self . contents) ;
579
608
609
+ /// Returns the id of the offer.
610
+ pub fn id ( & self ) -> OfferId {
611
+ self . id
612
+ }
613
+
580
614
pub ( super ) fn implied_chain ( & self ) -> ChainHash {
581
615
self . contents . implied_chain ( )
582
616
}
@@ -1002,7 +1036,9 @@ impl TryFrom<Vec<u8>> for Offer {
1002
1036
let offer = ParsedMessage :: < OfferTlvStream > :: try_from ( bytes) ?;
1003
1037
let ParsedMessage { bytes, tlv_stream } = offer;
1004
1038
let contents = OfferContents :: try_from ( tlv_stream) ?;
1005
- Ok ( Offer { bytes, contents } )
1039
+ let id = OfferId :: from_valid_offer_tlv_stream ( & bytes) ;
1040
+
1041
+ Ok ( Offer { bytes, contents, id } )
1006
1042
}
1007
1043
}
1008
1044
0 commit comments