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