@@ -506,7 +506,9 @@ impl UnsignedBolt12Invoice {
506506 record. write ( & mut bytes) . unwrap ( ) ;
507507 }
508508
509- let ( _, _, _, invoice_tlv_stream, _, _) = contents. as_tlv_stream ( ) ;
509+ let ( _, _, _, invoice_tlv_stream, _, _, experimental_invoice_tlv_stream) =
510+ contents. as_tlv_stream ( ) ;
511+
510512 invoice_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
511513
512514 let mut experimental_bytes = Vec :: new ( ) ;
@@ -515,6 +517,8 @@ impl UnsignedBolt12Invoice {
515517 record. write ( & mut experimental_bytes) . unwrap ( ) ;
516518 }
517519
520+ experimental_invoice_tlv_stream. write ( & mut experimental_bytes) . unwrap ( ) ;
521+
518522 let tlv_stream = TlvStream :: new ( & bytes) . chain ( TlvStream :: new ( & experimental_bytes) ) ;
519523 let tagged_hash = TaggedHash :: from_tlv_stream ( SIGNATURE_TAG , tlv_stream) ;
520524
@@ -872,14 +876,15 @@ impl Bolt12Invoice {
872876 let (
873877 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
874878 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
879+ experimental_invoice_tlv_stream,
875880 ) = self . contents . as_tlv_stream ( ) ;
876881 let signature_tlv_stream = SignatureTlvStreamRef {
877882 signature : Some ( & self . signature ) ,
878883 } ;
879884 (
880885 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
881886 signature_tlv_stream, experimental_offer_tlv_stream,
882- experimental_invoice_request_tlv_stream,
887+ experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream ,
883888 )
884889 }
885890
@@ -1140,9 +1145,12 @@ impl InvoiceContents {
11401145 InvoiceContents :: ForOffer { invoice_request, .. } => invoice_request. as_tlv_stream ( ) ,
11411146 InvoiceContents :: ForRefund { refund, .. } => refund. as_tlv_stream ( ) ,
11421147 } ;
1143- let invoice = self . fields ( ) . as_tlv_stream ( ) ;
1148+ let ( invoice, experimental_invoice ) = self . fields ( ) . as_tlv_stream ( ) ;
11441149
1145- ( payer, offer, invoice_request, invoice, experimental_offer, experimental_invoice_request)
1150+ (
1151+ payer, offer, invoice_request, invoice, experimental_offer,
1152+ experimental_invoice_request, experimental_invoice,
1153+ )
11461154 }
11471155}
11481156
@@ -1190,24 +1198,27 @@ pub(super) fn filter_fallbacks(
11901198}
11911199
11921200impl InvoiceFields {
1193- fn as_tlv_stream ( & self ) -> InvoiceTlvStreamRef {
1201+ fn as_tlv_stream ( & self ) -> ( InvoiceTlvStreamRef , ExperimentalInvoiceTlvStreamRef ) {
11941202 let features = {
11951203 if self . features == Bolt12InvoiceFeatures :: empty ( ) { None }
11961204 else { Some ( & self . features ) }
11971205 } ;
11981206
1199- InvoiceTlvStreamRef {
1200- paths : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| path. inner_blinded_path ( ) ) ) ) ,
1201- blindedpay : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| & path. 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- }
1207+ (
1208+ InvoiceTlvStreamRef {
1209+ paths : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| path. inner_blinded_path ( ) ) ) ) ,
1210+ blindedpay : Some ( Iterable ( self . payment_paths . iter ( ) . map ( |path| & path. payinfo ) ) ) ,
1211+ created_at : Some ( self . created_at . as_secs ( ) ) ,
1212+ relative_expiry : self . relative_expiry . map ( |duration| duration. as_secs ( ) as u32 ) ,
1213+ payment_hash : Some ( & self . payment_hash ) ,
1214+ amount : Some ( self . amount_msats ) ,
1215+ fallbacks : self . fallbacks . as_ref ( ) ,
1216+ features,
1217+ node_id : Some ( & self . signing_pubkey ) ,
1218+ message_paths : None ,
1219+ } ,
1220+ ExperimentalInvoiceTlvStreamRef { } ,
1221+ )
12111222 }
12121223}
12131224
@@ -1245,11 +1256,13 @@ impl TryFrom<Vec<u8>> for UnsignedBolt12Invoice {
12451256 let (
12461257 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
12471258 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1259+ experimental_invoice_tlv_stream,
12481260 ) = tlv_stream;
12491261 let contents = InvoiceContents :: try_from (
12501262 (
12511263 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
12521264 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1265+ experimental_invoice_tlv_stream,
12531266 )
12541267 ) ?;
12551268
@@ -1292,6 +1305,13 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef<'a>, INVOICE_TYPES, {
12921305 ( 236 , message_paths: ( Vec <BlindedMessagePath >, WithoutLength ) ) ,
12931306} ) ;
12941307
1308+ /// Valid type range for experimental invoice TLV records.
1309+ const EXPERIMENTAL_INVOICE_TYPES : core:: ops:: RangeFrom < u64 > = 3_000_000_000 ..;
1310+
1311+ tlv_stream ! (
1312+ ExperimentalInvoiceTlvStream , ExperimentalInvoiceTlvStreamRef , EXPERIMENTAL_INVOICE_TYPES , { }
1313+ ) ;
1314+
12951315pub ( super ) type BlindedPathIter < ' a > = core:: iter:: Map <
12961316 core:: slice:: Iter < ' a , BlindedPaymentPath > ,
12971317 for <' r > fn ( & ' r BlindedPaymentPath ) -> & ' r BlindedPath ,
@@ -1313,7 +1333,7 @@ impl_writeable!(FallbackAddress, { version, program });
13131333
13141334type FullInvoiceTlvStream =(
13151335 PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream , SignatureTlvStream ,
1316- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1336+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
13171337) ;
13181338
13191339type FullInvoiceTlvStreamRef < ' a > = (
@@ -1324,6 +1344,7 @@ type FullInvoiceTlvStreamRef<'a> = (
13241344 SignatureTlvStreamRef < ' a > ,
13251345 ExperimentalOfferTlvStreamRef ,
13261346 ExperimentalInvoiceRequestTlvStreamRef ,
1347+ ExperimentalInvoiceTlvStreamRef ,
13271348) ;
13281349
13291350impl CursorReadable for FullInvoiceTlvStream {
@@ -1335,19 +1356,20 @@ impl CursorReadable for FullInvoiceTlvStream {
13351356 let signature = CursorReadable :: read ( r) ?;
13361357 let experimental_offer = CursorReadable :: read ( r) ?;
13371358 let experimental_invoice_request = CursorReadable :: read ( r) ?;
1359+ let experimental_invoice = CursorReadable :: read ( r) ?;
13381360
13391361 Ok (
13401362 (
13411363 payer, offer, invoice_request, invoice, signature, experimental_offer,
1342- experimental_invoice_request,
1364+ experimental_invoice_request, experimental_invoice ,
13431365 )
13441366 )
13451367 }
13461368}
13471369
13481370type PartialInvoiceTlvStream = (
13491371 PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream ,
1350- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1372+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
13511373) ;
13521374
13531375type PartialInvoiceTlvStreamRef < ' a > = (
@@ -1357,6 +1379,7 @@ type PartialInvoiceTlvStreamRef<'a> = (
13571379 InvoiceTlvStreamRef < ' a > ,
13581380 ExperimentalOfferTlvStreamRef ,
13591381 ExperimentalInvoiceRequestTlvStreamRef ,
1382+ ExperimentalInvoiceTlvStreamRef ,
13601383) ;
13611384
13621385impl CursorReadable for PartialInvoiceTlvStream {
@@ -1367,11 +1390,12 @@ impl CursorReadable for PartialInvoiceTlvStream {
13671390 let invoice = CursorReadable :: read ( r) ?;
13681391 let experimental_offer = CursorReadable :: read ( r) ?;
13691392 let experimental_invoice_request = CursorReadable :: read ( r) ?;
1393+ let experimental_invoice = CursorReadable :: read ( r) ?;
13701394
13711395 Ok (
13721396 (
13731397 payer, offer, invoice_request, invoice, experimental_offer,
1374- experimental_invoice_request,
1398+ experimental_invoice_request, experimental_invoice ,
13751399 )
13761400 )
13771401 }
@@ -1387,11 +1411,13 @@ impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Bolt12Invoice {
13871411 SignatureTlvStream { signature } ,
13881412 experimental_offer_tlv_stream,
13891413 experimental_invoice_request_tlv_stream,
1414+ experimental_invoice_tlv_stream,
13901415 ) = tlv_stream;
13911416 let contents = InvoiceContents :: try_from (
13921417 (
13931418 payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
13941419 experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1420+ experimental_invoice_tlv_stream,
13951421 )
13961422 ) ?;
13971423
@@ -1420,6 +1446,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
14201446 } ,
14211447 experimental_offer_tlv_stream,
14221448 experimental_invoice_request_tlv_stream,
1449+ ExperimentalInvoiceTlvStream { } ,
14231450 ) = tlv_stream;
14241451
14251452 if message_paths. is_some ( ) { return Err ( Bolt12SemanticError :: UnexpectedPaths ) }
@@ -1516,7 +1543,7 @@ pub(super) fn check_invoice_signing_pubkey(
15161543
15171544#[ cfg( test) ]
15181545mod tests {
1519- use super :: { Bolt12Invoice , DEFAULT_RELATIVE_EXPIRY , FallbackAddress , FullInvoiceTlvStreamRef , INVOICE_TYPES , InvoiceTlvStreamRef , SIGNATURE_TAG , UnsignedBolt12Invoice } ;
1546+ use super :: { Bolt12Invoice , DEFAULT_RELATIVE_EXPIRY , ExperimentalInvoiceTlvStreamRef , FallbackAddress , FullInvoiceTlvStreamRef , INVOICE_TYPES , InvoiceTlvStreamRef , SIGNATURE_TAG , UnsignedBolt12Invoice } ;
15201547
15211548 use bitcoin:: { CompressedPublicKey , WitnessProgram , WitnessVersion } ;
15221549 use bitcoin:: constants:: ChainHash ;
@@ -1712,6 +1739,7 @@ mod tests {
17121739 ExperimentalInvoiceRequestTlvStreamRef {
17131740 experimental_bar: None ,
17141741 } ,
1742+ ExperimentalInvoiceTlvStreamRef { } ,
17151743 ) ,
17161744 ) ;
17171745
@@ -1811,6 +1839,7 @@ mod tests {
18111839 ExperimentalInvoiceRequestTlvStreamRef {
18121840 experimental_bar: None ,
18131841 } ,
1842+ ExperimentalInvoiceTlvStreamRef { } ,
18141843 ) ,
18151844 ) ;
18161845
@@ -2007,7 +2036,7 @@ mod tests {
20072036 . relative_expiry ( one_hour. as_secs ( ) as u32 )
20082037 . build ( ) . unwrap ( )
20092038 . sign ( recipient_sign) . unwrap ( ) ;
2010- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2039+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20112040 #[ cfg( feature = "std" ) ]
20122041 assert ! ( !invoice. is_expired( ) ) ;
20132042 assert_eq ! ( invoice. relative_expiry( ) , one_hour) ;
@@ -2023,7 +2052,7 @@ mod tests {
20232052 . relative_expiry ( one_hour. as_secs ( ) as u32 - 1 )
20242053 . build ( ) . unwrap ( )
20252054 . sign ( recipient_sign) . unwrap ( ) ;
2026- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2055+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20272056 #[ cfg( feature = "std" ) ]
20282057 assert ! ( invoice. is_expired( ) ) ;
20292058 assert_eq ! ( invoice. relative_expiry( ) , one_hour - Duration :: from_secs( 1 ) ) ;
@@ -2042,7 +2071,7 @@ mod tests {
20422071 . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
20432072 . build ( ) . unwrap ( )
20442073 . sign ( recipient_sign) . unwrap ( ) ;
2045- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2074+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20462075 assert_eq ! ( invoice. amount_msats( ) , 1001 ) ;
20472076 assert_eq ! ( tlv_stream. amount, Some ( 1001 ) ) ;
20482077 }
@@ -2060,7 +2089,7 @@ mod tests {
20602089 . respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
20612090 . build ( ) . unwrap ( )
20622091 . sign ( recipient_sign) . unwrap ( ) ;
2063- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2092+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
20642093 assert_eq ! ( invoice. amount_msats( ) , 2000 ) ;
20652094 assert_eq ! ( tlv_stream. amount, Some ( 2000 ) ) ;
20662095
@@ -2098,7 +2127,7 @@ mod tests {
20982127 . fallback_v1_p2tr_tweaked ( & tweaked_pubkey)
20992128 . build ( ) . unwrap ( )
21002129 . sign ( recipient_sign) . unwrap ( ) ;
2101- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2130+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
21022131 assert_eq ! (
21032132 invoice. fallbacks( ) ,
21042133 vec![
@@ -2141,7 +2170,7 @@ mod tests {
21412170 . allow_mpp ( )
21422171 . build ( ) . unwrap ( )
21432172 . sign ( recipient_sign) . unwrap ( ) ;
2144- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2173+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
21452174 assert_eq ! ( invoice. invoice_features( ) , & features) ;
21462175 assert_eq ! ( tlv_stream. features, Some ( & features) ) ;
21472176 }
0 commit comments