@@ -505,7 +505,9 @@ impl UnsignedBolt12Invoice {
505505 record. write ( & mut bytes) . unwrap ( ) ;
506506 }
507507
508- let ( _, _, _, invoice_tlv_stream, _, _) = contents. as_tlv_stream ( ) ;
508+ let ( _, _, _, invoice_tlv_stream, _, _, experimental_invoice_tlv_stream) =
509+ contents. as_tlv_stream ( ) ;
510+
509511 invoice_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
510512
511513 let mut experimental_bytes = Vec :: new ( ) ;
@@ -514,6 +516,8 @@ impl UnsignedBolt12Invoice {
514516 record. write ( & mut experimental_bytes) . unwrap ( ) ;
515517 }
516518
519+ experimental_invoice_tlv_stream. write ( & mut experimental_bytes) . unwrap ( ) ;
520+
517521 let tlv_stream = TlvStream :: new ( & bytes) . chain ( TlvStream :: new ( & experimental_bytes) ) ;
518522 let tagged_hash = TaggedHash :: from_tlv_stream ( SIGNATURE_TAG , tlv_stream) ;
519523
@@ -871,14 +875,15 @@ impl Bolt12Invoice {
871875 let (
872876 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
873877 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
878+ experimental_invoice_tlv_stream,
874879 ) = self . contents . as_tlv_stream ( ) ;
875880 let signature_tlv_stream = SignatureTlvStreamRef {
876881 signature : Some ( & self . signature ) ,
877882 } ;
878883 (
879884 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
880885 signature_tlv_stream, experimental_offer_tlv_stream,
881- experimental_invoice_request_tlv_stream,
886+ experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream ,
882887 )
883888 }
884889
@@ -1139,9 +1144,12 @@ impl InvoiceContents {
11391144 InvoiceContents :: ForOffer { invoice_request, .. } => invoice_request. as_tlv_stream ( ) ,
11401145 InvoiceContents :: ForRefund { refund, .. } => refund. as_tlv_stream ( ) ,
11411146 } ;
1142- let invoice = self . fields ( ) . as_tlv_stream ( ) ;
1147+ let ( invoice, experimental_invoice ) = self . fields ( ) . as_tlv_stream ( ) ;
11431148
1144- ( payer, offer, invoice_request, invoice, experimental_offer, experimental_invoice_request)
1149+ (
1150+ payer, offer, invoice_request, invoice, experimental_offer,
1151+ experimental_invoice_request, experimental_invoice,
1152+ )
11451153 }
11461154}
11471155
@@ -1189,24 +1197,27 @@ pub(super) fn filter_fallbacks(
11891197}
11901198
11911199impl InvoiceFields {
1192- fn as_tlv_stream ( & self ) -> InvoiceTlvStreamRef {
1200+ fn as_tlv_stream ( & self ) -> ( InvoiceTlvStreamRef , ExperimentalInvoiceTlvStreamRef ) {
11931201 let features = {
11941202 if self . features == Bolt12InvoiceFeatures :: empty ( ) { None }
11951203 else { Some ( & self . features ) }
11961204 } ;
11971205
1198- InvoiceTlvStreamRef {
1199- paths : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| path. inner_blinded_path ( ) ) ) ) ,
1200- blindedpay : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| & path. payinfo ) ) ) ,
1201- created_at : Some ( self . created_at . as_secs ( ) ) ,
1202- relative_expiry : self . relative_expiry . map ( |duration| duration. as_secs ( ) as u32 ) ,
1203- payment_hash : Some ( & self . payment_hash ) ,
1204- amount : Some ( self . amount_msats ) ,
1205- fallbacks : self . fallbacks . as_ref ( ) ,
1206- features,
1207- node_id : Some ( & self . signing_pubkey ) ,
1208- message_paths : None ,
1209- }
1206+ (
1207+ InvoiceTlvStreamRef {
1208+ paths : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| path. inner_blinded_path ( ) ) ) ) ,
1209+ blindedpay : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| & path. payinfo ) ) ) ,
1210+ created_at : Some ( self . created_at . as_secs ( ) ) ,
1211+ relative_expiry : self . relative_expiry . map ( |duration| duration. as_secs ( ) as u32 ) ,
1212+ payment_hash : Some ( & self . payment_hash ) ,
1213+ amount : Some ( self . amount_msats ) ,
1214+ fallbacks : self . fallbacks . as_ref ( ) ,
1215+ features,
1216+ node_id : Some ( & self . signing_pubkey ) ,
1217+ message_paths : None ,
1218+ } ,
1219+ ExperimentalInvoiceTlvStreamRef { } ,
1220+ )
12101221 }
12111222}
12121223
@@ -1244,11 +1255,13 @@ impl TryFrom<Vec<u8>> for UnsignedBolt12Invoice {
12441255 let (
12451256 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
12461257 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1258+ experimental_invoice_tlv_stream,
12471259 ) = tlv_stream;
12481260 let contents = InvoiceContents :: try_from (
12491261 (
12501262 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
12511263 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1264+ experimental_invoice_tlv_stream,
12521265 )
12531266 ) ?;
12541267
@@ -1291,6 +1304,13 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef<'a>, INVOICE_TYPES, {
12911304 ( 236 , message_paths: ( Vec <BlindedMessagePath >, WithoutLength ) ) ,
12921305} ) ;
12931306
1307+ /// Valid type range for experimental invoice TLV records.
1308+ const EXPERIMENTAL_INVOICE_TYPES : core:: ops:: RangeFrom < u64 > = 3_000_000_000 ..;
1309+
1310+ tlv_stream ! (
1311+ ExperimentalInvoiceTlvStream , ExperimentalInvoiceTlvStreamRef , EXPERIMENTAL_INVOICE_TYPES , { }
1312+ ) ;
1313+
12941314pub ( super ) type BlindedPathIter < ' a > = core:: iter:: Map <
12951315 core:: slice:: Iter < ' a , BlindedPaymentPath > ,
12961316 for <' r > fn ( & ' r BlindedPaymentPath ) -> & ' r BlindedPath ,
@@ -1312,7 +1332,7 @@ impl_writeable!(FallbackAddress, { version, program });
13121332
13131333type FullInvoiceTlvStream =(
13141334 PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream , SignatureTlvStream ,
1315- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1335+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
13161336) ;
13171337
13181338type FullInvoiceTlvStreamRef < ' a > = (
@@ -1323,6 +1343,7 @@ type FullInvoiceTlvStreamRef<'a> = (
13231343 SignatureTlvStreamRef < ' a > ,
13241344 ExperimentalOfferTlvStreamRef ,
13251345 ExperimentalInvoiceRequestTlvStreamRef ,
1346+ ExperimentalInvoiceTlvStreamRef ,
13261347) ;
13271348
13281349impl CursorReadable for FullInvoiceTlvStream {
@@ -1334,19 +1355,20 @@ impl CursorReadable for FullInvoiceTlvStream {
13341355 let signature = CursorReadable :: read ( r) ?;
13351356 let experimental_offer = CursorReadable :: read ( r) ?;
13361357 let experimental_invoice_request = CursorReadable :: read ( r) ?;
1358+ let experimental_invoice = CursorReadable :: read ( r) ?;
13371359
13381360 Ok (
13391361 (
13401362 payer, offer, invoice_request, invoice, signature, experimental_offer,
1341- experimental_invoice_request,
1363+ experimental_invoice_request, experimental_invoice ,
13421364 )
13431365 )
13441366 }
13451367}
13461368
13471369type PartialInvoiceTlvStream = (
13481370 PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream ,
1349- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1371+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
13501372) ;
13511373
13521374type PartialInvoiceTlvStreamRef < ' a > = (
@@ -1356,6 +1378,7 @@ type PartialInvoiceTlvStreamRef<'a> = (
13561378 InvoiceTlvStreamRef < ' a > ,
13571379 ExperimentalOfferTlvStreamRef ,
13581380 ExperimentalInvoiceRequestTlvStreamRef ,
1381+ ExperimentalInvoiceTlvStreamRef ,
13591382) ;
13601383
13611384impl CursorReadable for PartialInvoiceTlvStream {
@@ -1366,11 +1389,12 @@ impl CursorReadable for PartialInvoiceTlvStream {
13661389 let invoice = CursorReadable :: read ( r) ?;
13671390 let experimental_offer = CursorReadable :: read ( r) ?;
13681391 let experimental_invoice_request = CursorReadable :: read ( r) ?;
1392+ let experimental_invoice = CursorReadable :: read ( r) ?;
13691393
13701394 Ok (
13711395 (
13721396 payer, offer, invoice_request, invoice, experimental_offer,
1373- experimental_invoice_request,
1397+ experimental_invoice_request, experimental_invoice ,
13741398 )
13751399 )
13761400 }
@@ -1386,11 +1410,13 @@ impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Bolt12Invoice {
13861410 SignatureTlvStream { signature } ,
13871411 experimental_offer_tlv_stream,
13881412 experimental_invoice_request_tlv_stream,
1413+ experimental_invoice_tlv_stream,
13891414 ) = tlv_stream;
13901415 let contents = InvoiceContents :: try_from (
13911416 (
13921417 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
13931418 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1419+ experimental_invoice_tlv_stream,
13941420 )
13951421 ) ?;
13961422
@@ -1419,6 +1445,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
14191445 } ,
14201446 experimental_offer_tlv_stream,
14211447 experimental_invoice_request_tlv_stream,
1448+ ExperimentalInvoiceTlvStream { } ,
14221449 ) = tlv_stream;
14231450
14241451 if message_paths. is_some ( ) { return Err ( Bolt12SemanticError :: UnexpectedPaths ) }
@@ -1515,7 +1542,7 @@ pub(super) fn check_invoice_signing_pubkey(
15151542
15161543#[ cfg( test) ]
15171544mod tests {
1518- use super :: { Bolt12Invoice , DEFAULT_RELATIVE_EXPIRY , FallbackAddress , FullInvoiceTlvStreamRef , INVOICE_TYPES , InvoiceTlvStreamRef , SIGNATURE_TAG , UnsignedBolt12Invoice } ;
1545+ use super :: { Bolt12Invoice , DEFAULT_RELATIVE_EXPIRY , ExperimentalInvoiceTlvStreamRef , FallbackAddress , FullInvoiceTlvStreamRef , INVOICE_TYPES , InvoiceTlvStreamRef , SIGNATURE_TAG , UnsignedBolt12Invoice } ;
15191546
15201547 use bitcoin:: { CompressedPublicKey , WitnessProgram , WitnessVersion } ;
15211548 use bitcoin:: constants:: ChainHash ;
@@ -1711,6 +1738,7 @@ mod tests {
17111738 ExperimentalInvoiceRequestTlvStreamRef {
17121739 experimental_bar: None ,
17131740 } ,
1741+ ExperimentalInvoiceTlvStreamRef { } ,
17141742 ) ,
17151743 ) ;
17161744
@@ -1810,6 +1838,7 @@ mod tests {
18101838 ExperimentalInvoiceRequestTlvStreamRef {
18111839 experimental_bar: None ,
18121840 } ,
1841+ ExperimentalInvoiceTlvStreamRef { } ,
18131842 ) ,
18141843 ) ;
18151844
@@ -2006,7 +2035,7 @@ mod tests {
20062035 . relative_expiry ( one_hour. as_secs ( ) as u32 )
20072036 . build ( ) . unwrap ( )
20082037 . sign ( recipient_sign) . unwrap ( ) ;
2009- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2038+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20102039 #[ cfg( feature = "std" ) ]
20112040 assert ! ( !invoice. is_expired( ) ) ;
20122041 assert_eq ! ( invoice. relative_expiry( ) , one_hour) ;
@@ -2022,7 +2051,7 @@ mod tests {
20222051 . relative_expiry ( one_hour. as_secs ( ) as u32 - 1 )
20232052 . build ( ) . unwrap ( )
20242053 . sign ( recipient_sign) . unwrap ( ) ;
2025- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2054+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20262055 #[ cfg( feature = "std" ) ]
20272056 assert ! ( invoice. is_expired( ) ) ;
20282057 assert_eq ! ( invoice. relative_expiry( ) , one_hour - Duration :: from_secs( 1 ) ) ;
@@ -2041,7 +2070,7 @@ mod tests {
20412070 . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
20422071 . build ( ) . unwrap ( )
20432072 . sign ( recipient_sign) . unwrap ( ) ;
2044- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2073+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20452074 assert_eq ! ( invoice. amount_msats( ) , 1001 ) ;
20462075 assert_eq ! ( tlv_stream. amount, Some ( 1001 ) ) ;
20472076 }
@@ -2059,7 +2088,7 @@ mod tests {
20592088 . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
20602089 . build ( ) . unwrap ( )
20612090 . sign ( recipient_sign) . unwrap ( ) ;
2062- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2091+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20632092 assert_eq ! ( invoice. amount_msats( ) , 2000 ) ;
20642093 assert_eq ! ( tlv_stream. amount, Some ( 2000 ) ) ;
20652094
@@ -2097,7 +2126,7 @@ mod tests {
20972126 . fallback_v1_p2tr_tweaked ( & tweaked_pubkey)
20982127 . build ( ) . unwrap ( )
20992128 . sign ( recipient_sign) . unwrap ( ) ;
2100- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2129+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
21012130 assert_eq ! (
21022131 invoice. fallbacks( ) ,
21032132 vec![
@@ -2140,7 +2169,7 @@ mod tests {
21402169 . allow_mpp ( )
21412170 . build ( ) . unwrap ( )
21422171 . sign ( recipient_sign) . unwrap ( ) ;
2143- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2172+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
21442173 assert_eq ! ( invoice. invoice_features( ) , & features) ;
21452174 assert_eq ! ( tlv_stream. features, Some ( & features) ) ;
21462175 }
0 commit comments