@@ -505,7 +505,9 @@ impl UnsignedBolt12Invoice {
505
505
record. write ( & mut bytes) . unwrap ( ) ;
506
506
}
507
507
508
- let ( _, _, _, invoice_tlv_stream, _, _) = contents. as_tlv_stream ( ) ;
508
+ let ( _, _, _, invoice_tlv_stream, _, _, experimental_invoice_tlv_stream) =
509
+ contents. as_tlv_stream ( ) ;
510
+
509
511
invoice_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
510
512
511
513
let mut experimental_bytes = Vec :: new ( ) ;
@@ -514,6 +516,8 @@ impl UnsignedBolt12Invoice {
514
516
record. write ( & mut experimental_bytes) . unwrap ( ) ;
515
517
}
516
518
519
+ experimental_invoice_tlv_stream. write ( & mut experimental_bytes) . unwrap ( ) ;
520
+
517
521
let tlv_stream = TlvStream :: new ( & bytes) . chain ( TlvStream :: new ( & experimental_bytes) ) ;
518
522
let tagged_hash = TaggedHash :: from_tlv_stream ( SIGNATURE_TAG , tlv_stream) ;
519
523
@@ -871,14 +875,15 @@ impl Bolt12Invoice {
871
875
let (
872
876
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
873
877
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
878
+ experimental_invoice_tlv_stream,
874
879
) = self . contents . as_tlv_stream ( ) ;
875
880
let signature_tlv_stream = SignatureTlvStreamRef {
876
881
signature : Some ( & self . signature ) ,
877
882
} ;
878
883
(
879
884
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
880
885
signature_tlv_stream, experimental_offer_tlv_stream,
881
- experimental_invoice_request_tlv_stream,
886
+ experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream ,
882
887
)
883
888
}
884
889
@@ -1139,9 +1144,12 @@ impl InvoiceContents {
1139
1144
InvoiceContents :: ForOffer { invoice_request, .. } => invoice_request. as_tlv_stream ( ) ,
1140
1145
InvoiceContents :: ForRefund { refund, .. } => refund. as_tlv_stream ( ) ,
1141
1146
} ;
1142
- let invoice = self . fields ( ) . as_tlv_stream ( ) ;
1147
+ let ( invoice, experimental_invoice ) = self . fields ( ) . as_tlv_stream ( ) ;
1143
1148
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
+ )
1145
1153
}
1146
1154
}
1147
1155
@@ -1189,24 +1197,27 @@ pub(super) fn filter_fallbacks(
1189
1197
}
1190
1198
1191
1199
impl InvoiceFields {
1192
- fn as_tlv_stream ( & self ) -> InvoiceTlvStreamRef {
1200
+ fn as_tlv_stream ( & self ) -> ( InvoiceTlvStreamRef , ExperimentalInvoiceTlvStreamRef ) {
1193
1201
let features = {
1194
1202
if self . features == Bolt12InvoiceFeatures :: empty ( ) { None }
1195
1203
else { Some ( & self . features ) }
1196
1204
} ;
1197
1205
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
+ )
1210
1221
}
1211
1222
}
1212
1223
@@ -1244,11 +1255,13 @@ impl TryFrom<Vec<u8>> for UnsignedBolt12Invoice {
1244
1255
let (
1245
1256
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
1246
1257
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1258
+ experimental_invoice_tlv_stream,
1247
1259
) = tlv_stream;
1248
1260
let contents = InvoiceContents :: try_from (
1249
1261
(
1250
1262
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
1251
1263
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1264
+ experimental_invoice_tlv_stream,
1252
1265
)
1253
1266
) ?;
1254
1267
@@ -1291,6 +1304,13 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef<'a>, INVOICE_TYPES, {
1291
1304
( 236 , message_paths: ( Vec <BlindedMessagePath >, WithoutLength ) ) ,
1292
1305
} ) ;
1293
1306
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
+
1294
1314
pub ( super ) type BlindedPathIter < ' a > = core:: iter:: Map <
1295
1315
core:: slice:: Iter < ' a , BlindedPaymentPath > ,
1296
1316
for <' r > fn ( & ' r BlindedPaymentPath ) -> & ' r BlindedPath ,
@@ -1312,7 +1332,7 @@ impl_writeable!(FallbackAddress, { version, program });
1312
1332
1313
1333
type FullInvoiceTlvStream =(
1314
1334
PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream , SignatureTlvStream ,
1315
- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1335
+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
1316
1336
) ;
1317
1337
1318
1338
type FullInvoiceTlvStreamRef < ' a > = (
@@ -1323,6 +1343,7 @@ type FullInvoiceTlvStreamRef<'a> = (
1323
1343
SignatureTlvStreamRef < ' a > ,
1324
1344
ExperimentalOfferTlvStreamRef ,
1325
1345
ExperimentalInvoiceRequestTlvStreamRef ,
1346
+ ExperimentalInvoiceTlvStreamRef ,
1326
1347
) ;
1327
1348
1328
1349
impl CursorReadable for FullInvoiceTlvStream {
@@ -1334,19 +1355,20 @@ impl CursorReadable for FullInvoiceTlvStream {
1334
1355
let signature = CursorReadable :: read ( r) ?;
1335
1356
let experimental_offer = CursorReadable :: read ( r) ?;
1336
1357
let experimental_invoice_request = CursorReadable :: read ( r) ?;
1358
+ let experimental_invoice = CursorReadable :: read ( r) ?;
1337
1359
1338
1360
Ok (
1339
1361
(
1340
1362
payer, offer, invoice_request, invoice, signature, experimental_offer,
1341
- experimental_invoice_request,
1363
+ experimental_invoice_request, experimental_invoice ,
1342
1364
)
1343
1365
)
1344
1366
}
1345
1367
}
1346
1368
1347
1369
type PartialInvoiceTlvStream = (
1348
1370
PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream ,
1349
- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1371
+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
1350
1372
) ;
1351
1373
1352
1374
type PartialInvoiceTlvStreamRef < ' a > = (
@@ -1356,6 +1378,7 @@ type PartialInvoiceTlvStreamRef<'a> = (
1356
1378
InvoiceTlvStreamRef < ' a > ,
1357
1379
ExperimentalOfferTlvStreamRef ,
1358
1380
ExperimentalInvoiceRequestTlvStreamRef ,
1381
+ ExperimentalInvoiceTlvStreamRef ,
1359
1382
) ;
1360
1383
1361
1384
impl CursorReadable for PartialInvoiceTlvStream {
@@ -1366,11 +1389,12 @@ impl CursorReadable for PartialInvoiceTlvStream {
1366
1389
let invoice = CursorReadable :: read ( r) ?;
1367
1390
let experimental_offer = CursorReadable :: read ( r) ?;
1368
1391
let experimental_invoice_request = CursorReadable :: read ( r) ?;
1392
+ let experimental_invoice = CursorReadable :: read ( r) ?;
1369
1393
1370
1394
Ok (
1371
1395
(
1372
1396
payer, offer, invoice_request, invoice, experimental_offer,
1373
- experimental_invoice_request,
1397
+ experimental_invoice_request, experimental_invoice ,
1374
1398
)
1375
1399
)
1376
1400
}
@@ -1386,11 +1410,13 @@ impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Bolt12Invoice {
1386
1410
SignatureTlvStream { signature } ,
1387
1411
experimental_offer_tlv_stream,
1388
1412
experimental_invoice_request_tlv_stream,
1413
+ experimental_invoice_tlv_stream,
1389
1414
) = tlv_stream;
1390
1415
let contents = InvoiceContents :: try_from (
1391
1416
(
1392
1417
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
1393
1418
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1419
+ experimental_invoice_tlv_stream,
1394
1420
)
1395
1421
) ?;
1396
1422
@@ -1419,6 +1445,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
1419
1445
} ,
1420
1446
experimental_offer_tlv_stream,
1421
1447
experimental_invoice_request_tlv_stream,
1448
+ ExperimentalInvoiceTlvStream { } ,
1422
1449
) = tlv_stream;
1423
1450
1424
1451
if message_paths. is_some ( ) { return Err ( Bolt12SemanticError :: UnexpectedPaths ) }
@@ -1515,7 +1542,7 @@ pub(super) fn check_invoice_signing_pubkey(
1515
1542
1516
1543
#[ cfg( test) ]
1517
1544
mod 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 } ;
1519
1546
1520
1547
use bitcoin:: { CompressedPublicKey , WitnessProgram , WitnessVersion } ;
1521
1548
use bitcoin:: constants:: ChainHash ;
@@ -1711,6 +1738,7 @@ mod tests {
1711
1738
ExperimentalInvoiceRequestTlvStreamRef {
1712
1739
experimental_bar: None ,
1713
1740
} ,
1741
+ ExperimentalInvoiceTlvStreamRef { } ,
1714
1742
) ,
1715
1743
) ;
1716
1744
@@ -1810,6 +1838,7 @@ mod tests {
1810
1838
ExperimentalInvoiceRequestTlvStreamRef {
1811
1839
experimental_bar: None ,
1812
1840
} ,
1841
+ ExperimentalInvoiceTlvStreamRef { } ,
1813
1842
) ,
1814
1843
) ;
1815
1844
@@ -2006,7 +2035,7 @@ mod tests {
2006
2035
. relative_expiry ( one_hour. as_secs ( ) as u32 )
2007
2036
. build ( ) . unwrap ( )
2008
2037
. sign ( recipient_sign) . unwrap ( ) ;
2009
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2038
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2010
2039
#[ cfg( feature = "std" ) ]
2011
2040
assert ! ( !invoice. is_expired( ) ) ;
2012
2041
assert_eq ! ( invoice. relative_expiry( ) , one_hour) ;
@@ -2022,7 +2051,7 @@ mod tests {
2022
2051
. relative_expiry ( one_hour. as_secs ( ) as u32 - 1 )
2023
2052
. build ( ) . unwrap ( )
2024
2053
. sign ( recipient_sign) . unwrap ( ) ;
2025
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2054
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2026
2055
#[ cfg( feature = "std" ) ]
2027
2056
assert ! ( invoice. is_expired( ) ) ;
2028
2057
assert_eq ! ( invoice. relative_expiry( ) , one_hour - Duration :: from_secs( 1 ) ) ;
@@ -2041,7 +2070,7 @@ mod tests {
2041
2070
. respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
2042
2071
. build ( ) . unwrap ( )
2043
2072
. sign ( recipient_sign) . unwrap ( ) ;
2044
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2073
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2045
2074
assert_eq ! ( invoice. amount_msats( ) , 1001 ) ;
2046
2075
assert_eq ! ( tlv_stream. amount, Some ( 1001 ) ) ;
2047
2076
}
@@ -2059,7 +2088,7 @@ mod tests {
2059
2088
. respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
2060
2089
. build ( ) . unwrap ( )
2061
2090
. sign ( recipient_sign) . unwrap ( ) ;
2062
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2091
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2063
2092
assert_eq ! ( invoice. amount_msats( ) , 2000 ) ;
2064
2093
assert_eq ! ( tlv_stream. amount, Some ( 2000 ) ) ;
2065
2094
@@ -2097,7 +2126,7 @@ mod tests {
2097
2126
. fallback_v1_p2tr_tweaked ( & tweaked_pubkey)
2098
2127
. build ( ) . unwrap ( )
2099
2128
. sign ( recipient_sign) . unwrap ( ) ;
2100
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2129
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2101
2130
assert_eq ! (
2102
2131
invoice. fallbacks( ) ,
2103
2132
vec![
@@ -2140,7 +2169,7 @@ mod tests {
2140
2169
. allow_mpp ( )
2141
2170
. build ( ) . unwrap ( )
2142
2171
. sign ( recipient_sign) . unwrap ( ) ;
2143
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2172
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2144
2173
assert_eq ! ( invoice. invoice_features( ) , & features) ;
2145
2174
assert_eq ! ( tlv_stream. features, Some ( & features) ) ;
2146
2175
}
0 commit comments