6868use crate :: blinded_path:: message:: BlindedMessagePath ;
6969use crate :: blinded_path:: payment:: BlindedPaymentPath ;
7070use crate :: io;
71+ use crate :: io:: Read ;
7172use crate :: ln:: channelmanager:: PaymentId ;
7273use crate :: ln:: inbound_payment:: { ExpandedKey , IV_LEN } ;
7374use crate :: ln:: msgs:: DecodeError ;
@@ -499,7 +500,11 @@ impl UnsignedInvoiceRequest {
499500
500501 invoice_request_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
501502
502- const EXPERIMENTAL_TLV_ALLOCATION_SIZE : usize = 0 ;
503+ // Allocate sufficient capacity for experimental TLV fields to avoid reallocations.
504+ // The new fields (invreq_contact_secret: ~48 bytes, invreq_payer_offer: ~116 bytes,
505+ // invreq_payer_bip_353_name: ~116 bytes) total ~280 bytes, with 600 providing headroom
506+ // for future experimental fields and variable-length data.
507+ const EXPERIMENTAL_TLV_ALLOCATION_SIZE : usize = 600 ;
503508 let mut experimental_bytes = Vec :: with_capacity ( EXPERIMENTAL_TLV_ALLOCATION_SIZE ) ;
504509
505510 let experimental_tlv_stream =
@@ -1137,6 +1142,9 @@ impl InvoiceRequestContentsWithoutPayerSigningPubkey {
11371142 } ;
11381143
11391144 let experimental_invoice_request = ExperimentalInvoiceRequestTlvStreamRef {
1145+ invreq_contact_secret : None ,
1146+ invreq_payer_offer : None ,
1147+ invreq_payer_bip_353_name : None ,
11401148 #[ cfg( test) ]
11411149 experimental_bar : self . experimental_bar ,
11421150 } ;
@@ -1200,21 +1208,47 @@ tlv_stream!(InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef<'a>, INVOICE_REQ
12001208pub ( super ) const EXPERIMENTAL_INVOICE_REQUEST_TYPES : core:: ops:: Range < u64 > =
12011209 2_000_000_000 ..3_000_000_000 ;
12021210
1211+ /// A contact secret used in experimental TLV fields.
1212+ #[ derive( Clone , Copy , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
1213+ pub struct ContactSecret {
1214+ contents : [ u8 ; 32 ] ,
1215+ }
1216+
1217+ impl Readable for ContactSecret {
1218+ fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
1219+ let mut buf = [ 0u8 ; 32 ] ;
1220+ r. read_exact ( & mut buf) ?;
1221+ Ok ( ContactSecret { contents : buf } )
1222+ }
1223+ }
1224+
1225+ impl Writeable for ContactSecret {
1226+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1227+ w. write_all ( & self . contents )
1228+ }
1229+ }
1230+
12031231#[ cfg( not( test) ) ]
12041232tlv_stream ! (
12051233 ExperimentalInvoiceRequestTlvStream ,
1206- ExperimentalInvoiceRequestTlvStreamRef ,
1234+ ExperimentalInvoiceRequestTlvStreamRef < ' a> ,
12071235 EXPERIMENTAL_INVOICE_REQUEST_TYPES ,
12081236 {
1237+ ( 2_000_001_729 , invreq_contact_secret: ( Vec <u8 >, WithoutLength ) ) ,
1238+ ( 2_000_001_731 , invreq_payer_offer: ( Vec <u8 >, WithoutLength ) ) ,
1239+ ( 2_000_001_733 , invreq_payer_bip_353_name: ( Vec <u8 >, WithoutLength ) ) ,
12091240 // When adding experimental TLVs, update EXPERIMENTAL_TLV_ALLOCATION_SIZE accordingly in
12101241 // UnsignedInvoiceRequest::new to avoid unnecessary allocations.
12111242 }
12121243) ;
12131244
12141245#[ cfg( test) ]
12151246tlv_stream ! (
1216- ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceRequestTlvStreamRef ,
1247+ ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceRequestTlvStreamRef < ' a> ,
12171248 EXPERIMENTAL_INVOICE_REQUEST_TYPES , {
1249+ ( 2_000_001_729 , invreq_contact_secret: ( Vec <u8 >, WithoutLength ) ) ,
1250+ ( 2_000_001_731 , invreq_payer_offer: ( Vec <u8 >, WithoutLength ) ) ,
1251+ ( 2_000_001_733 , invreq_payer_bip_353_name: ( Vec <u8 >, WithoutLength ) ) ,
12181252 ( 2_999_999_999 , experimental_bar: ( u64 , HighZeroBytesDroppedBigSize ) ) ,
12191253 }
12201254) ;
@@ -1234,7 +1268,7 @@ type FullInvoiceRequestTlvStreamRef<'a> = (
12341268 InvoiceRequestTlvStreamRef < ' a > ,
12351269 SignatureTlvStreamRef < ' a > ,
12361270 ExperimentalOfferTlvStreamRef ,
1237- ExperimentalInvoiceRequestTlvStreamRef ,
1271+ ExperimentalInvoiceRequestTlvStreamRef < ' a > ,
12381272) ;
12391273
12401274impl CursorReadable for FullInvoiceRequestTlvStream {
@@ -1270,7 +1304,7 @@ type PartialInvoiceRequestTlvStreamRef<'a> = (
12701304 OfferTlvStreamRef < ' a > ,
12711305 InvoiceRequestTlvStreamRef < ' a > ,
12721306 ExperimentalOfferTlvStreamRef ,
1273- ExperimentalInvoiceRequestTlvStreamRef ,
1307+ ExperimentalInvoiceRequestTlvStreamRef < ' a > ,
12741308) ;
12751309
12761310impl TryFrom < Vec < u8 > > for UnsignedInvoiceRequest {
@@ -1349,6 +1383,9 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
13491383 } ,
13501384 experimental_offer_tlv_stream,
13511385 ExperimentalInvoiceRequestTlvStream {
1386+ invreq_contact_secret : _,
1387+ invreq_payer_offer : _,
1388+ invreq_payer_bip_353_name : _,
13521389 #[ cfg( test) ]
13531390 experimental_bar,
13541391 } ,
@@ -1572,7 +1609,12 @@ mod tests {
15721609 } ,
15731610 SignatureTlvStreamRef { signature: Some ( & invoice_request. signature( ) ) } ,
15741611 ExperimentalOfferTlvStreamRef { experimental_foo: None } ,
1575- ExperimentalInvoiceRequestTlvStreamRef { experimental_bar: None } ,
1612+ ExperimentalInvoiceRequestTlvStreamRef {
1613+ invreq_contact_secret: None ,
1614+ invreq_payer_offer: None ,
1615+ invreq_payer_bip_353_name: None ,
1616+ experimental_bar: None ,
1617+ } ,
15761618 ) ,
15771619 ) ;
15781620
0 commit comments