@@ -496,7 +496,9 @@ impl UnsignedBolt12Invoice {
496496 record. write ( & mut bytes) . unwrap ( ) ;
497497 }
498498
499- let ( _, _, _, invoice_tlv_stream, _, _) = contents. as_tlv_stream ( ) ;
499+ let ( _, _, _, invoice_tlv_stream, _, _, experimental_invoice_tlv_stream) =
500+ contents. as_tlv_stream ( ) ;
501+
500502 invoice_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
501503
502504 let mut experimental_bytes = Vec :: new ( ) ;
@@ -505,6 +507,8 @@ impl UnsignedBolt12Invoice {
505507 record. write ( & mut experimental_bytes) . unwrap ( ) ;
506508 }
507509
510+ experimental_invoice_tlv_stream. write ( & mut experimental_bytes) . unwrap ( ) ;
511+
508512 let tlv_stream = TlvStream :: new ( & bytes) . chain ( TlvStream :: new ( & experimental_bytes) ) ;
509513 let tagged_hash = TaggedHash :: from_tlv_stream ( SIGNATURE_TAG , tlv_stream) ;
510514
@@ -862,14 +866,15 @@ impl Bolt12Invoice {
862866 let (
863867 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
864868 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
869+ experimental_invoice_tlv_stream,
865870 ) = self . contents . as_tlv_stream ( ) ;
866871 let signature_tlv_stream = SignatureTlvStreamRef {
867872 signature : Some ( & self . signature ) ,
868873 } ;
869874 (
870875 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
871876 signature_tlv_stream, experimental_offer_tlv_stream,
872- experimental_invoice_request_tlv_stream,
877+ experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream ,
873878 )
874879 }
875880
@@ -1130,9 +1135,12 @@ impl InvoiceContents {
11301135 InvoiceContents :: ForOffer { invoice_request, .. } => invoice_request. as_tlv_stream ( ) ,
11311136 InvoiceContents :: ForRefund { refund, .. } => refund. as_tlv_stream ( ) ,
11321137 } ;
1133- let invoice = self . fields ( ) . as_tlv_stream ( ) ;
1138+ let ( invoice, experimental_invoice ) = self . fields ( ) . as_tlv_stream ( ) ;
11341139
1135- ( payer, offer, invoice_request, invoice, experimental_offer, experimental_invoice_request)
1140+ (
1141+ payer, offer, invoice_request, invoice, experimental_offer,
1142+ experimental_invoice_request, experimental_invoice,
1143+ )
11361144 }
11371145}
11381146
@@ -1181,24 +1189,27 @@ pub(super) fn filter_fallbacks(
11811189}
11821190
11831191impl InvoiceFields {
1184- fn as_tlv_stream ( & self ) -> InvoiceTlvStreamRef {
1192+ fn as_tlv_stream ( & self ) -> ( InvoiceTlvStreamRef , ExperimentalInvoiceTlvStreamRef ) {
11851193 let features = {
11861194 if self . features == Bolt12InvoiceFeatures :: empty ( ) { None }
11871195 else { Some ( & self . features ) }
11881196 } ;
11891197
1190- InvoiceTlvStreamRef {
1191- paths : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |( _, path) | path) ) ) ,
1192- blindedpay : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |( payinfo, _) | payinfo) ) ) ,
1193- created_at : Some ( self . created_at . as_secs ( ) ) ,
1194- relative_expiry : self . relative_expiry . map ( |duration| duration. as_secs ( ) as u32 ) ,
1195- payment_hash : Some ( & self . payment_hash ) ,
1196- amount : Some ( self . amount_msats ) ,
1197- fallbacks : self . fallbacks . as_ref ( ) ,
1198- features,
1199- node_id : Some ( & self . signing_pubkey ) ,
1200- message_paths : None ,
1201- }
1198+ (
1199+ InvoiceTlvStreamRef {
1200+ paths : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |( _, path) | path) ) ) ,
1201+ blindedpay : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |( payinfo, _) | payinfo) ) ) ,
1202+ created_at : Some ( self . created_at . as_secs ( ) ) ,
1203+ relative_expiry : self . relative_expiry . map ( |duration| duration. as_secs ( ) as u32 ) ,
1204+ payment_hash : Some ( & self . payment_hash ) ,
1205+ amount : Some ( self . amount_msats ) ,
1206+ fallbacks : self . fallbacks . as_ref ( ) ,
1207+ features,
1208+ node_id : Some ( & self . signing_pubkey ) ,
1209+ message_paths : None ,
1210+ } ,
1211+ ExperimentalInvoiceTlvStreamRef { } ,
1212+ )
12021213 }
12031214}
12041215
@@ -1236,11 +1247,13 @@ impl TryFrom<Vec<u8>> for UnsignedBolt12Invoice {
12361247 let (
12371248 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
12381249 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1250+ experimental_invoice_tlv_stream,
12391251 ) = tlv_stream;
12401252 let contents = InvoiceContents :: try_from (
12411253 (
12421254 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
12431255 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1256+ experimental_invoice_tlv_stream,
12441257 )
12451258 ) ?;
12461259
@@ -1283,6 +1296,13 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef<'a>, INVOICE_TYPES, {
12831296 ( 236 , message_paths: ( Vec <BlindedPath >, WithoutLength ) ) ,
12841297} ) ;
12851298
1299+ /// Valid type range for experimental invoice TLV records.
1300+ const EXPERIMENTAL_INVOICE_TYPES : core:: ops:: RangeFrom < u64 > = 3_000_000_000 ..;
1301+
1302+ tlv_stream ! (
1303+ ExperimentalInvoiceTlvStream , ExperimentalInvoiceTlvStreamRef , EXPERIMENTAL_INVOICE_TYPES , { }
1304+ ) ;
1305+
12861306pub ( super ) type BlindedPathIter < ' a > = core:: iter:: Map <
12871307 core:: slice:: Iter < ' a , ( BlindedPayInfo , BlindedPath ) > ,
12881308 for <' r > fn ( & ' r ( BlindedPayInfo , BlindedPath ) ) -> & ' r BlindedPath ,
@@ -1342,7 +1362,7 @@ impl_writeable!(FallbackAddress, { version, program });
13421362
13431363type FullInvoiceTlvStream =(
13441364 PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream , SignatureTlvStream ,
1345- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1365+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
13461366) ;
13471367
13481368type FullInvoiceTlvStreamRef < ' a > = (
@@ -1353,6 +1373,7 @@ type FullInvoiceTlvStreamRef<'a> = (
13531373 SignatureTlvStreamRef < ' a > ,
13541374 ExperimentalOfferTlvStreamRef ,
13551375 ExperimentalInvoiceRequestTlvStreamRef ,
1376+ ExperimentalInvoiceTlvStreamRef ,
13561377) ;
13571378
13581379impl SeekReadable for FullInvoiceTlvStream {
@@ -1364,19 +1385,20 @@ impl SeekReadable for FullInvoiceTlvStream {
13641385 let signature = SeekReadable :: read ( r) ?;
13651386 let experimental_offer = SeekReadable :: read ( r) ?;
13661387 let experimental_invoice_request = SeekReadable :: read ( r) ?;
1388+ let experimental_invoice = SeekReadable :: read ( r) ?;
13671389
13681390 Ok (
13691391 (
13701392 payer, offer, invoice_request, invoice, signature, experimental_offer,
1371- experimental_invoice_request,
1393+ experimental_invoice_request, experimental_invoice ,
13721394 )
13731395 )
13741396 }
13751397}
13761398
13771399type PartialInvoiceTlvStream = (
13781400 PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream ,
1379- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1401+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
13801402) ;
13811403
13821404type PartialInvoiceTlvStreamRef < ' a > = (
@@ -1386,6 +1408,7 @@ type PartialInvoiceTlvStreamRef<'a> = (
13861408 InvoiceTlvStreamRef < ' a > ,
13871409 ExperimentalOfferTlvStreamRef ,
13881410 ExperimentalInvoiceRequestTlvStreamRef ,
1411+ ExperimentalInvoiceTlvStreamRef ,
13891412) ;
13901413
13911414impl SeekReadable for PartialInvoiceTlvStream {
@@ -1396,11 +1419,12 @@ impl SeekReadable for PartialInvoiceTlvStream {
13961419 let invoice = SeekReadable :: read ( r) ?;
13971420 let experimental_offer = SeekReadable :: read ( r) ?;
13981421 let experimental_invoice_request = SeekReadable :: read ( r) ?;
1422+ let experimental_invoice= SeekReadable :: read ( r) ?;
13991423
14001424 Ok (
14011425 (
14021426 payer, offer, invoice_request, invoice, experimental_offer,
1403- experimental_invoice_request,
1427+ experimental_invoice_request, experimental_invoice ,
14041428 )
14051429 )
14061430 }
@@ -1416,11 +1440,13 @@ impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Bolt12Invoice {
14161440 SignatureTlvStream { signature } ,
14171441 experimental_offer_tlv_stream,
14181442 experimental_invoice_request_tlv_stream,
1443+ experimental_invoice_tlv_stream,
14191444 ) = tlv_stream;
14201445 let contents = InvoiceContents :: try_from (
14211446 (
14221447 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
14231448 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1449+ experimental_invoice_tlv_stream,
14241450 )
14251451 ) ?;
14261452
@@ -1449,6 +1475,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
14491475 } ,
14501476 experimental_offer_tlv_stream,
14511477 experimental_invoice_request_tlv_stream,
1478+ ExperimentalInvoiceTlvStream { } ,
14521479 ) = tlv_stream;
14531480
14541481 if message_paths. is_some ( ) { return Err ( Bolt12SemanticError :: UnexpectedPaths ) }
@@ -1540,7 +1567,7 @@ pub(super) fn check_invoice_signing_pubkey(
15401567
15411568#[ cfg( test) ]
15421569mod tests {
1543- use super :: { Bolt12Invoice , DEFAULT_RELATIVE_EXPIRY , FallbackAddress , FullInvoiceTlvStreamRef , INVOICE_TYPES , InvoiceTlvStreamRef , SIGNATURE_TAG , UnsignedBolt12Invoice } ;
1570+ use super :: { Bolt12Invoice , DEFAULT_RELATIVE_EXPIRY , ExperimentalInvoiceTlvStreamRef , FallbackAddress , FullInvoiceTlvStreamRef , INVOICE_TYPES , InvoiceTlvStreamRef , SIGNATURE_TAG , UnsignedBolt12Invoice } ;
15441571
15451572 use bitcoin:: { WitnessProgram , WitnessVersion } ;
15461573 use bitcoin:: blockdata:: constants:: ChainHash ;
@@ -1735,6 +1762,7 @@ mod tests {
17351762 ExperimentalInvoiceRequestTlvStreamRef {
17361763 experimental_bar: None ,
17371764 } ,
1765+ ExperimentalInvoiceTlvStreamRef { } ,
17381766 ) ,
17391767 ) ;
17401768
@@ -1834,6 +1862,7 @@ mod tests {
18341862 ExperimentalInvoiceRequestTlvStreamRef {
18351863 experimental_bar: None ,
18361864 } ,
1865+ ExperimentalInvoiceTlvStreamRef { } ,
18371866 ) ,
18381867 ) ;
18391868
@@ -2032,7 +2061,7 @@ mod tests {
20322061 . relative_expiry ( one_hour. as_secs ( ) as u32 )
20332062 . build ( ) . unwrap ( )
20342063 . sign ( recipient_sign) . unwrap ( ) ;
2035- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2064+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20362065 #[ cfg( feature = "std" ) ]
20372066 assert ! ( !invoice. is_expired( ) ) ;
20382067 assert_eq ! ( invoice. relative_expiry( ) , one_hour) ;
@@ -2048,7 +2077,7 @@ mod tests {
20482077 . relative_expiry ( one_hour. as_secs ( ) as u32 - 1 )
20492078 . build ( ) . unwrap ( )
20502079 . sign ( recipient_sign) . unwrap ( ) ;
2051- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2080+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20522081 #[ cfg( feature = "std" ) ]
20532082 assert ! ( invoice. is_expired( ) ) ;
20542083 assert_eq ! ( invoice. relative_expiry( ) , one_hour - Duration :: from_secs( 1 ) ) ;
@@ -2067,7 +2096,7 @@ mod tests {
20672096 . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
20682097 . build ( ) . unwrap ( )
20692098 . sign ( recipient_sign) . unwrap ( ) ;
2070- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2099+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20712100 assert_eq ! ( invoice. amount_msats( ) , 1001 ) ;
20722101 assert_eq ! ( tlv_stream. amount, Some ( 1001 ) ) ;
20732102 }
@@ -2085,7 +2114,7 @@ mod tests {
20852114 . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
20862115 . build ( ) . unwrap ( )
20872116 . sign ( recipient_sign) . unwrap ( ) ;
2088- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2117+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20892118 assert_eq ! ( invoice. amount_msats( ) , 2000 ) ;
20902119 assert_eq ! ( tlv_stream. amount, Some ( 2000 ) ) ;
20912120
@@ -2123,7 +2152,7 @@ mod tests {
21232152 . fallback_v1_p2tr_tweaked ( & tweaked_pubkey)
21242153 . build ( ) . unwrap ( )
21252154 . sign ( recipient_sign) . unwrap ( ) ;
2126- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2155+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
21272156 assert_eq ! (
21282157 invoice. fallbacks( ) ,
21292158 vec![
@@ -2166,7 +2195,7 @@ mod tests {
21662195 . allow_mpp ( )
21672196 . build ( ) . unwrap ( )
21682197 . sign ( recipient_sign) . unwrap ( ) ;
2169- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2198+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
21702199 assert_eq ! ( invoice. invoice_features( ) , & features) ;
21712200 assert_eq ! ( tlv_stream. features, Some ( & features) ) ;
21722201 }
0 commit comments