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 ;
@@ -500,7 +501,11 @@ impl UnsignedInvoiceRequest {
500501
501502 invoice_request_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
502503
503- const EXPERIMENTAL_TLV_ALLOCATION_SIZE : usize = 0 ;
504+ // Allocate sufficient capacity for experimental TLV fields to avoid reallocations.
505+ // The new fields (invreq_contact_secret: ~48 bytes, invreq_payer_offer: ~116 bytes,
506+ // invreq_payer_bip_353_name: ~116 bytes) total ~280 bytes, with 600 providing headroom
507+ // for future experimental fields and variable-length data.
508+ const EXPERIMENTAL_TLV_ALLOCATION_SIZE : usize = 600 ;
504509 let mut experimental_bytes = Vec :: with_capacity ( EXPERIMENTAL_TLV_ALLOCATION_SIZE ) ;
505510
506511 let experimental_tlv_stream =
@@ -1225,6 +1230,9 @@ impl InvoiceRequestContentsWithoutPayerSigningPubkey {
12251230 } ;
12261231
12271232 let experimental_invoice_request = ExperimentalInvoiceRequestTlvStreamRef {
1233+ invreq_contact_secret : None ,
1234+ invreq_payer_offer : None ,
1235+ invreq_payer_bip_353_name : None ,
12281236 #[ cfg( test) ]
12291237 experimental_bar : self . experimental_bar ,
12301238 } ;
@@ -1288,21 +1296,47 @@ tlv_stream!(InvoiceRequestTlvStream, InvoiceRequestTlvStreamRef<'a>, INVOICE_REQ
12881296pub ( super ) const EXPERIMENTAL_INVOICE_REQUEST_TYPES : core:: ops:: Range < u64 > =
12891297 2_000_000_000 ..3_000_000_000 ;
12901298
1299+ /// A contact secret used in experimental TLV fields.
1300+ #[ derive( Clone , Copy , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
1301+ pub struct ContactSecret {
1302+ contents : [ u8 ; 32 ] ,
1303+ }
1304+
1305+ impl Readable for ContactSecret {
1306+ fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
1307+ let mut buf = [ 0u8 ; 32 ] ;
1308+ r. read_exact ( & mut buf) ?;
1309+ Ok ( ContactSecret { contents : buf } )
1310+ }
1311+ }
1312+
1313+ impl Writeable for ContactSecret {
1314+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
1315+ w. write_all ( & self . contents )
1316+ }
1317+ }
1318+
12911319#[ cfg( not( test) ) ]
12921320tlv_stream ! (
12931321 ExperimentalInvoiceRequestTlvStream ,
1294- ExperimentalInvoiceRequestTlvStreamRef ,
1322+ ExperimentalInvoiceRequestTlvStreamRef < ' a> ,
12951323 EXPERIMENTAL_INVOICE_REQUEST_TYPES ,
12961324 {
1325+ ( 2_000_001_729 , invreq_contact_secret: ( Vec <u8 >, WithoutLength ) ) ,
1326+ ( 2_000_001_731 , invreq_payer_offer: ( Vec <u8 >, WithoutLength ) ) ,
1327+ ( 2_000_001_733 , invreq_payer_bip_353_name: ( Vec <u8 >, WithoutLength ) ) ,
12971328 // When adding experimental TLVs, update EXPERIMENTAL_TLV_ALLOCATION_SIZE accordingly in
12981329 // UnsignedInvoiceRequest::new to avoid unnecessary allocations.
12991330 }
13001331) ;
13011332
13021333#[ cfg( test) ]
13031334tlv_stream ! (
1304- ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceRequestTlvStreamRef ,
1335+ ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceRequestTlvStreamRef < ' a> ,
13051336 EXPERIMENTAL_INVOICE_REQUEST_TYPES , {
1337+ ( 2_000_001_729 , invreq_contact_secret: ( Vec <u8 >, WithoutLength ) ) ,
1338+ ( 2_000_001_731 , invreq_payer_offer: ( Vec <u8 >, WithoutLength ) ) ,
1339+ ( 2_000_001_733 , invreq_payer_bip_353_name: ( Vec <u8 >, WithoutLength ) ) ,
13061340 ( 2_999_999_999 , experimental_bar: ( u64 , HighZeroBytesDroppedBigSize ) ) ,
13071341 }
13081342) ;
@@ -1322,7 +1356,7 @@ type FullInvoiceRequestTlvStreamRef<'a> = (
13221356 InvoiceRequestTlvStreamRef < ' a > ,
13231357 SignatureTlvStreamRef < ' a > ,
13241358 ExperimentalOfferTlvStreamRef ,
1325- ExperimentalInvoiceRequestTlvStreamRef ,
1359+ ExperimentalInvoiceRequestTlvStreamRef < ' a > ,
13261360) ;
13271361
13281362impl CursorReadable for FullInvoiceRequestTlvStream {
@@ -1358,7 +1392,7 @@ type PartialInvoiceRequestTlvStreamRef<'a> = (
13581392 OfferTlvStreamRef < ' a > ,
13591393 InvoiceRequestTlvStreamRef < ' a > ,
13601394 ExperimentalOfferTlvStreamRef ,
1361- ExperimentalInvoiceRequestTlvStreamRef ,
1395+ ExperimentalInvoiceRequestTlvStreamRef < ' a > ,
13621396) ;
13631397
13641398impl TryFrom < Vec < u8 > > for UnsignedInvoiceRequest {
@@ -1437,6 +1471,9 @@ impl TryFrom<PartialInvoiceRequestTlvStream> for InvoiceRequestContents {
14371471 } ,
14381472 experimental_offer_tlv_stream,
14391473 ExperimentalInvoiceRequestTlvStream {
1474+ invreq_contact_secret : _,
1475+ invreq_payer_offer : _,
1476+ invreq_payer_bip_353_name : _,
14401477 #[ cfg( test) ]
14411478 experimental_bar,
14421479 } ,
@@ -1660,7 +1697,12 @@ mod tests {
16601697 } ,
16611698 SignatureTlvStreamRef { signature: Some ( & invoice_request. signature( ) ) } ,
16621699 ExperimentalOfferTlvStreamRef { experimental_foo: None } ,
1663- ExperimentalInvoiceRequestTlvStreamRef { experimental_bar: None } ,
1700+ ExperimentalInvoiceRequestTlvStreamRef {
1701+ invreq_contact_secret: None ,
1702+ invreq_payer_offer: None ,
1703+ invreq_payer_bip_353_name: None ,
1704+ experimental_bar: None ,
1705+ } ,
16641706 ) ,
16651707 ) ;
16661708
0 commit comments