6767//! ```
6868
6969use bitcoin:: blockdata:: constants:: ChainHash ;
70- use bitcoin:: hashes:: { Hash , HashEngine } ;
71- use bitcoin:: hashes:: hmac:: { Hmac , HmacEngine } ;
72- use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
7370use bitcoin:: network:: constants:: Network ;
7471use bitcoin:: secp256k1:: PublicKey ;
75- use core:: convert:: { TryFrom , TryInto } ;
72+ use core:: convert:: TryFrom ;
7673use core:: num:: NonZeroU64 ;
7774use core:: str:: FromStr ;
7875use core:: time:: Duration ;
@@ -83,7 +80,7 @@ use crate::ln::msgs::MAX_VALUE_MSAT;
8380use crate :: offers:: invoice_request:: InvoiceRequestBuilder ;
8481use crate :: offers:: merkle:: TlvStream ;
8582use crate :: offers:: parse:: { Bech32Encode , ParseError , ParsedMessage , SemanticError } ;
86- use crate :: offers:: signer:: SigningPubkey ;
83+ use crate :: offers:: signer:: { MetadataMaterial , SigningPubkey , self } ;
8784use crate :: onion_message:: BlindedPath ;
8885use crate :: util:: ser:: { HighZeroBytesDroppedBigSize , WithoutLength , Writeable , Writer } ;
8986use crate :: util:: string:: PrintableString ;
@@ -100,7 +97,7 @@ use std::time::SystemTime;
10097/// [module-level documentation]: self
10198pub struct OfferBuilder {
10299 offer : OfferContents ,
103- metadata_material : Option < ( Nonce , HmacEngine < Sha256 > ) > ,
100+ metadata_material : Option < MetadataMaterial > ,
104101}
105102
106103impl OfferBuilder {
@@ -110,14 +107,7 @@ impl OfferBuilder {
110107 ///
111108 /// Use a different pubkey per offer to avoid correlating offers.
112109 pub fn new ( description : String , signing_pubkey : SigningPubkey ) -> Self {
113- let ( metadata_material, signing_pubkey) = match signing_pubkey {
114- SigningPubkey :: Explicit ( pubkey) => ( None , pubkey) ,
115- SigningPubkey :: Derived ( expanded_key, nonce) => {
116- let metadata_material = ( nonce, expanded_key. hmac_for_offer ( nonce) ) ;
117- let signing_pubkey = expanded_key. signing_pubkey_for_offer ( nonce) ;
118- ( Some ( metadata_material) , signing_pubkey)
119- } ,
120- } ;
110+ let ( metadata_material, signing_pubkey) = signing_pubkey. into_parts ( ) ;
121111 let offer = OfferContents {
122112 chains : None , metadata : None , amount : None , description,
123113 features : OfferFeatures :: empty ( ) , absolute_expiry : None , issuer : None , paths : None ,
@@ -167,7 +157,7 @@ impl OfferBuilder {
167157 /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
168158 pub fn metadata_derived ( mut self , key : & ExpandedKey , nonce : Nonce ) -> Self {
169159 self . offer . metadata = None ;
170- self . metadata_material = Some ( ( nonce, key. hmac_for_offer ( nonce ) ) ) ;
160+ self . metadata_material = Some ( MetadataMaterial :: new ( nonce, key) ) ;
171161 self
172162 }
173163
@@ -240,18 +230,14 @@ impl OfferBuilder {
240230 }
241231 }
242232
243- // Create the metadata for stateless verification. It consists of a 16-byte nonce and a
244- // 32-byte HMAC of the offer bytes excluding the signing pubkey.
245- if let Some ( ( nonce, mut hmac) ) = self . metadata_material {
233+ // Create the metadata for stateless verification of an InvoiceRequest.
234+ if let Some ( mut metadata_material) = self . metadata_material {
246235 debug_assert ! ( self . offer. metadata. is_none( ) ) ;
247236 let mut tlv_stream = self . offer . as_tlv_stream ( ) ;
248237 tlv_stream. node_id = None ;
249- tlv_stream. write ( & mut hmac) . unwrap ( ) ;
250-
251- let mut metadata = nonce. as_slice ( ) . to_vec ( ) ;
252- metadata. extend_from_slice ( & Hmac :: from_engine ( hmac) . into_inner ( ) ) ;
238+ tlv_stream. write ( & mut metadata_material) . unwrap ( ) ;
253239
254- self . offer . metadata = Some ( metadata ) ;
240+ self . offer . metadata = Some ( metadata_material . into_metadata ( ) ) ;
255241 }
256242
257243 let mut bytes = Vec :: new ( ) ;
@@ -536,23 +522,15 @@ impl OfferContents {
536522 pub ( super ) fn verify ( & self , tlv_stream : TlvStream < ' _ > , key : & ExpandedKey ) -> bool {
537523 match & self . metadata {
538524 Some ( metadata) => {
539- let mut hmac = if metadata. len ( ) < Nonce :: LENGTH {
540- return false ;
541- } else {
542- let nonce = Nonce ( metadata[ ..Nonce :: LENGTH ] . try_into ( ) . unwrap ( ) ) ;
543- key. hmac_for_offer ( nonce)
544- } ;
545-
546- for record in tlv_stream. range ( OFFER_TYPES ) {
525+ let tlv_stream = tlv_stream. range ( OFFER_TYPES ) . filter ( |record| {
547526 match record. r#type {
548527 // TODO: Assert value bytes == metadata?
549- OFFER_METADATA_TYPE => { } ,
550- OFFER_NODE_ID_TYPE => { } ,
551- _ => hmac . input ( record . record_bytes ) ,
528+ OFFER_METADATA_TYPE => false ,
529+ OFFER_NODE_ID_TYPE => false ,
530+ _ => true ,
552531 }
553- }
554-
555- & metadata[ Nonce :: LENGTH ..] == & Hmac :: from_engine ( hmac) . into_inner ( )
532+ } ) ;
533+ signer:: verify_metadata ( metadata, key, tlv_stream)
556534 } ,
557535 None => false ,
558536 }
0 commit comments