@@ -496,7 +496,9 @@ impl UnsignedBolt12Invoice {
496
496
record. write ( & mut bytes) . unwrap ( ) ;
497
497
}
498
498
499
- let ( _, _, _, invoice_tlv_stream, _, _) = contents. as_tlv_stream ( ) ;
499
+ let ( _, _, _, invoice_tlv_stream, _, _, experimental_invoice_tlv_stream) =
500
+ contents. as_tlv_stream ( ) ;
501
+
500
502
invoice_tlv_stream. write ( & mut bytes) . unwrap ( ) ;
501
503
502
504
let mut experimental_bytes = Vec :: new ( ) ;
@@ -505,6 +507,8 @@ impl UnsignedBolt12Invoice {
505
507
record. write ( & mut experimental_bytes) . unwrap ( ) ;
506
508
}
507
509
510
+ experimental_invoice_tlv_stream. write ( & mut experimental_bytes) . unwrap ( ) ;
511
+
508
512
let tlv_stream = TlvStream :: new ( & bytes) . chain ( TlvStream :: new ( & experimental_bytes) ) ;
509
513
let tagged_hash = TaggedHash :: from_tlv_stream ( SIGNATURE_TAG , tlv_stream) ;
510
514
@@ -862,14 +866,15 @@ impl Bolt12Invoice {
862
866
let (
863
867
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
864
868
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
869
+ experimental_invoice_tlv_stream,
865
870
) = self . contents . as_tlv_stream ( ) ;
866
871
let signature_tlv_stream = SignatureTlvStreamRef {
867
872
signature : Some ( & self . signature ) ,
868
873
} ;
869
874
(
870
875
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
871
876
signature_tlv_stream, experimental_offer_tlv_stream,
872
- experimental_invoice_request_tlv_stream,
877
+ experimental_invoice_request_tlv_stream, experimental_invoice_tlv_stream ,
873
878
)
874
879
}
875
880
@@ -1130,9 +1135,12 @@ impl InvoiceContents {
1130
1135
InvoiceContents :: ForOffer { invoice_request, .. } => invoice_request. as_tlv_stream ( ) ,
1131
1136
InvoiceContents :: ForRefund { refund, .. } => refund. as_tlv_stream ( ) ,
1132
1137
} ;
1133
- let invoice = self . fields ( ) . as_tlv_stream ( ) ;
1138
+ let ( invoice, experimental_invoice ) = self . fields ( ) . as_tlv_stream ( ) ;
1134
1139
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
+ )
1136
1144
}
1137
1145
}
1138
1146
@@ -1181,24 +1189,27 @@ pub(super) fn filter_fallbacks(
1181
1189
}
1182
1190
1183
1191
impl InvoiceFields {
1184
- fn as_tlv_stream ( & self ) -> InvoiceTlvStreamRef {
1192
+ fn as_tlv_stream ( & self ) -> ( InvoiceTlvStreamRef , ExperimentalInvoiceTlvStreamRef ) {
1185
1193
let features = {
1186
1194
if self . features == Bolt12InvoiceFeatures :: empty ( ) { None }
1187
1195
else { Some ( & self . features ) }
1188
1196
} ;
1189
1197
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
+ )
1202
1213
}
1203
1214
}
1204
1215
@@ -1236,11 +1247,13 @@ impl TryFrom<Vec<u8>> for UnsignedBolt12Invoice {
1236
1247
let (
1237
1248
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
1238
1249
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1250
+ experimental_invoice_tlv_stream,
1239
1251
) = tlv_stream;
1240
1252
let contents = InvoiceContents :: try_from (
1241
1253
(
1242
1254
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
1243
1255
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1256
+ experimental_invoice_tlv_stream,
1244
1257
)
1245
1258
) ?;
1246
1259
@@ -1283,6 +1296,13 @@ tlv_stream!(InvoiceTlvStream, InvoiceTlvStreamRef<'a>, INVOICE_TYPES, {
1283
1296
( 236 , message_paths: ( Vec <BlindedPath >, WithoutLength ) ) ,
1284
1297
} ) ;
1285
1298
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
+
1286
1306
pub ( super ) type BlindedPathIter < ' a > = core:: iter:: Map <
1287
1307
core:: slice:: Iter < ' a , ( BlindedPayInfo , BlindedPath ) > ,
1288
1308
for <' r > fn ( & ' r ( BlindedPayInfo , BlindedPath ) ) -> & ' r BlindedPath ,
@@ -1342,7 +1362,7 @@ impl_writeable!(FallbackAddress, { version, program });
1342
1362
1343
1363
type FullInvoiceTlvStream =(
1344
1364
PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream , SignatureTlvStream ,
1345
- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1365
+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
1346
1366
) ;
1347
1367
1348
1368
type FullInvoiceTlvStreamRef < ' a > = (
@@ -1353,6 +1373,7 @@ type FullInvoiceTlvStreamRef<'a> = (
1353
1373
SignatureTlvStreamRef < ' a > ,
1354
1374
ExperimentalOfferTlvStreamRef ,
1355
1375
ExperimentalInvoiceRequestTlvStreamRef ,
1376
+ ExperimentalInvoiceTlvStreamRef ,
1356
1377
) ;
1357
1378
1358
1379
impl SeekReadable for FullInvoiceTlvStream {
@@ -1364,19 +1385,20 @@ impl SeekReadable for FullInvoiceTlvStream {
1364
1385
let signature = SeekReadable :: read ( r) ?;
1365
1386
let experimental_offer = SeekReadable :: read ( r) ?;
1366
1387
let experimental_invoice_request = SeekReadable :: read ( r) ?;
1388
+ let experimental_invoice = SeekReadable :: read ( r) ?;
1367
1389
1368
1390
Ok (
1369
1391
(
1370
1392
payer, offer, invoice_request, invoice, signature, experimental_offer,
1371
- experimental_invoice_request,
1393
+ experimental_invoice_request, experimental_invoice ,
1372
1394
)
1373
1395
)
1374
1396
}
1375
1397
}
1376
1398
1377
1399
type PartialInvoiceTlvStream = (
1378
1400
PayerTlvStream , OfferTlvStream , InvoiceRequestTlvStream , InvoiceTlvStream ,
1379
- ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream ,
1401
+ ExperimentalOfferTlvStream , ExperimentalInvoiceRequestTlvStream , ExperimentalInvoiceTlvStream ,
1380
1402
) ;
1381
1403
1382
1404
type PartialInvoiceTlvStreamRef < ' a > = (
@@ -1386,6 +1408,7 @@ type PartialInvoiceTlvStreamRef<'a> = (
1386
1408
InvoiceTlvStreamRef < ' a > ,
1387
1409
ExperimentalOfferTlvStreamRef ,
1388
1410
ExperimentalInvoiceRequestTlvStreamRef ,
1411
+ ExperimentalInvoiceTlvStreamRef ,
1389
1412
) ;
1390
1413
1391
1414
impl SeekReadable for PartialInvoiceTlvStream {
@@ -1396,11 +1419,12 @@ impl SeekReadable for PartialInvoiceTlvStream {
1396
1419
let invoice = SeekReadable :: read ( r) ?;
1397
1420
let experimental_offer = SeekReadable :: read ( r) ?;
1398
1421
let experimental_invoice_request = SeekReadable :: read ( r) ?;
1422
+ let experimental_invoice= SeekReadable :: read ( r) ?;
1399
1423
1400
1424
Ok (
1401
1425
(
1402
1426
payer, offer, invoice_request, invoice, experimental_offer,
1403
- experimental_invoice_request,
1427
+ experimental_invoice_request, experimental_invoice ,
1404
1428
)
1405
1429
)
1406
1430
}
@@ -1416,11 +1440,13 @@ impl TryFrom<ParsedMessage<FullInvoiceTlvStream>> for Bolt12Invoice {
1416
1440
SignatureTlvStream { signature } ,
1417
1441
experimental_offer_tlv_stream,
1418
1442
experimental_invoice_request_tlv_stream,
1443
+ experimental_invoice_tlv_stream,
1419
1444
) = tlv_stream;
1420
1445
let contents = InvoiceContents :: try_from (
1421
1446
(
1422
1447
payer_tlv_stream, offer_tlv_stream, invoice_request_tlv_stream, invoice_tlv_stream,
1423
1448
experimental_offer_tlv_stream, experimental_invoice_request_tlv_stream,
1449
+ experimental_invoice_tlv_stream,
1424
1450
)
1425
1451
) ?;
1426
1452
@@ -1449,6 +1475,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
1449
1475
} ,
1450
1476
experimental_offer_tlv_stream,
1451
1477
experimental_invoice_request_tlv_stream,
1478
+ ExperimentalInvoiceTlvStream { } ,
1452
1479
) = tlv_stream;
1453
1480
1454
1481
if message_paths. is_some ( ) { return Err ( Bolt12SemanticError :: UnexpectedPaths ) }
@@ -1540,7 +1567,7 @@ pub(super) fn check_invoice_signing_pubkey(
1540
1567
1541
1568
#[ cfg( test) ]
1542
1569
mod 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 } ;
1544
1571
1545
1572
use bitcoin:: { WitnessProgram , WitnessVersion } ;
1546
1573
use bitcoin:: blockdata:: constants:: ChainHash ;
@@ -1735,6 +1762,7 @@ mod tests {
1735
1762
ExperimentalInvoiceRequestTlvStreamRef {
1736
1763
experimental_bar: None ,
1737
1764
} ,
1765
+ ExperimentalInvoiceTlvStreamRef { } ,
1738
1766
) ,
1739
1767
) ;
1740
1768
@@ -1834,6 +1862,7 @@ mod tests {
1834
1862
ExperimentalInvoiceRequestTlvStreamRef {
1835
1863
experimental_bar: None ,
1836
1864
} ,
1865
+ ExperimentalInvoiceTlvStreamRef { } ,
1837
1866
) ,
1838
1867
) ;
1839
1868
@@ -2032,7 +2061,7 @@ mod tests {
2032
2061
. relative_expiry ( one_hour. as_secs ( ) as u32 )
2033
2062
. build ( ) . unwrap ( )
2034
2063
. sign ( recipient_sign) . unwrap ( ) ;
2035
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2064
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2036
2065
#[ cfg( feature = "std" ) ]
2037
2066
assert ! ( !invoice. is_expired( ) ) ;
2038
2067
assert_eq ! ( invoice. relative_expiry( ) , one_hour) ;
@@ -2048,7 +2077,7 @@ mod tests {
2048
2077
. relative_expiry ( one_hour. as_secs ( ) as u32 - 1 )
2049
2078
. build ( ) . unwrap ( )
2050
2079
. sign ( recipient_sign) . unwrap ( ) ;
2051
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2080
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2052
2081
#[ cfg( feature = "std" ) ]
2053
2082
assert ! ( invoice. is_expired( ) ) ;
2054
2083
assert_eq ! ( invoice. relative_expiry( ) , one_hour - Duration :: from_secs( 1 ) ) ;
@@ -2067,7 +2096,7 @@ mod tests {
2067
2096
. respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
2068
2097
. build ( ) . unwrap ( )
2069
2098
. sign ( recipient_sign) . unwrap ( ) ;
2070
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2099
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2071
2100
assert_eq ! ( invoice. amount_msats( ) , 1001 ) ;
2072
2101
assert_eq ! ( tlv_stream. amount, Some ( 1001 ) ) ;
2073
2102
}
@@ -2085,7 +2114,7 @@ mod tests {
2085
2114
. respond_with_no_std ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
2086
2115
. build ( ) . unwrap ( )
2087
2116
. sign ( recipient_sign) . unwrap ( ) ;
2088
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2117
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2089
2118
assert_eq ! ( invoice. amount_msats( ) , 2000 ) ;
2090
2119
assert_eq ! ( tlv_stream. amount, Some ( 2000 ) ) ;
2091
2120
@@ -2123,7 +2152,7 @@ mod tests {
2123
2152
. fallback_v1_p2tr_tweaked ( & tweaked_pubkey)
2124
2153
. build ( ) . unwrap ( )
2125
2154
. sign ( recipient_sign) . unwrap ( ) ;
2126
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2155
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2127
2156
assert_eq ! (
2128
2157
invoice. fallbacks( ) ,
2129
2158
vec![
@@ -2166,7 +2195,7 @@ mod tests {
2166
2195
. allow_mpp ( )
2167
2196
. build ( ) . unwrap ( )
2168
2197
. sign ( recipient_sign) . unwrap ( ) ;
2169
- let ( _, _, _, tlv_stream, _, _, _) = invoice. as_tlv_stream ( ) ;
2198
+ let ( _, _, _, tlv_stream, _, _, _, _ ) = invoice. as_tlv_stream ( ) ;
2170
2199
assert_eq ! ( invoice. invoice_features( ) , & features) ;
2171
2200
assert_eq ! ( tlv_stream. features, Some ( & features) ) ;
2172
2201
}
0 commit comments