@@ -523,6 +523,12 @@ impl Writeable for Invoice {
523
523
}
524
524
}
525
525
526
+ impl Writeable for InvoiceContents {
527
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
528
+ self . as_tlv_stream ( ) . write ( writer)
529
+ }
530
+ }
531
+
526
532
impl TryFrom < Vec < u8 > > for Invoice {
527
533
type Error = ParseError ;
528
534
@@ -717,7 +723,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
717
723
718
724
#[ cfg( test) ]
719
725
mod tests {
720
- use super :: { DEFAULT_RELATIVE_EXPIRY , BlindedPayInfo , FallbackAddress , Invoice , InvoiceTlvStreamRef , SIGNATURE_TAG } ;
726
+ use super :: { DEFAULT_RELATIVE_EXPIRY , BlindedPayInfo , FallbackAddress , FullInvoiceTlvStreamRef , Invoice , InvoiceTlvStreamRef , SIGNATURE_TAG } ;
721
727
722
728
use bitcoin:: blockdata:: script:: Script ;
723
729
use bitcoin:: hashes:: Hash ;
@@ -730,15 +736,16 @@ mod tests {
730
736
#[ cfg( feature = "std" ) ]
731
737
use core:: time:: Duration ;
732
738
use crate :: ln:: PaymentHash ;
739
+ use crate :: ln:: msgs:: DecodeError ;
733
740
use crate :: ln:: features:: { BlindedHopFeatures , Bolt12InvoiceFeatures } ;
734
741
use crate :: offers:: invoice_request:: InvoiceRequestTlvStreamRef ;
735
742
use crate :: offers:: merkle:: { SignError , SignatureTlvStreamRef , self } ;
736
743
use crate :: offers:: offer:: { OfferBuilder , OfferTlvStreamRef } ;
737
- use crate :: offers:: parse:: SemanticError ;
744
+ use crate :: offers:: parse:: { ParseError , SemanticError } ;
738
745
use crate :: offers:: payer:: PayerTlvStreamRef ;
739
746
use crate :: offers:: refund:: RefundBuilder ;
740
747
use crate :: onion_message:: { BlindedHop , BlindedPath } ;
741
- use crate :: util:: ser:: { Iterable , Writeable } ;
748
+ use crate :: util:: ser:: { BigSize , Iterable , Writeable } ;
742
749
743
750
fn payer_keys ( ) -> KeyPair {
744
751
let secp_ctx = Secp256k1 :: new ( ) ;
@@ -779,6 +786,22 @@ mod tests {
779
786
SecretKey :: from_slice ( & [ byte; 32 ] ) . unwrap ( )
780
787
}
781
788
789
+ trait ToBytes {
790
+ fn to_bytes ( & self ) -> Vec < u8 > ;
791
+ }
792
+
793
+ impl < ' a > ToBytes for FullInvoiceTlvStreamRef < ' a > {
794
+ fn to_bytes ( & self ) -> Vec < u8 > {
795
+ let mut buffer = Vec :: new ( ) ;
796
+ self . 0 . write ( & mut buffer) . unwrap ( ) ;
797
+ self . 1 . write ( & mut buffer) . unwrap ( ) ;
798
+ self . 2 . write ( & mut buffer) . unwrap ( ) ;
799
+ self . 3 . write ( & mut buffer) . unwrap ( ) ;
800
+ self . 4 . write ( & mut buffer) . unwrap ( ) ;
801
+ buffer
802
+ }
803
+ }
804
+
782
805
fn payment_paths ( ) -> Vec < ( BlindedPath , BlindedPayInfo ) > {
783
806
let paths = vec ! [
784
807
BlindedPath {
@@ -1165,4 +1188,246 @@ mod tests {
1165
1188
Err ( e) => assert_eq ! ( e, SignError :: Verification ( secp256k1:: Error :: InvalidSignature ) ) ,
1166
1189
}
1167
1190
}
1191
+
1192
+ #[ test]
1193
+ fn parses_invoice_with_payment_paths ( ) {
1194
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1195
+ . amount_msats ( 1000 )
1196
+ . build ( ) . unwrap ( )
1197
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1198
+ . build ( ) . unwrap ( )
1199
+ . sign ( payer_sign) . unwrap ( )
1200
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1201
+ . build ( ) . unwrap ( )
1202
+ . sign ( recipient_sign) . unwrap ( ) ;
1203
+
1204
+ let mut buffer = Vec :: new ( ) ;
1205
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1206
+
1207
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1208
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1209
+ }
1210
+
1211
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1212
+ tlv_stream. 3 . paths = None ;
1213
+
1214
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1215
+ Ok ( _) => panic ! ( "expected error" ) ,
1216
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPaths ) ) ,
1217
+ }
1218
+
1219
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1220
+ tlv_stream. 3 . blindedpay = None ;
1221
+
1222
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1223
+ Ok ( _) => panic ! ( "expected error" ) ,
1224
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InvalidPayInfo ) ) ,
1225
+ }
1226
+
1227
+ let empty_payment_paths = vec ! [ ] ;
1228
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1229
+ tlv_stream. 3 . paths = Some ( Iterable ( empty_payment_paths. iter ( ) . map ( |( path, _) | path) ) ) ;
1230
+
1231
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1232
+ Ok ( _) => panic ! ( "expected error" ) ,
1233
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPaths ) ) ,
1234
+ }
1235
+
1236
+ let mut payment_paths = payment_paths ( ) ;
1237
+ payment_paths. pop ( ) ;
1238
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1239
+ tlv_stream. 3 . blindedpay = Some ( Iterable ( payment_paths. iter ( ) . map ( |( _, payinfo) | payinfo) ) ) ;
1240
+
1241
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1242
+ Ok ( _) => panic ! ( "expected error" ) ,
1243
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InvalidPayInfo ) ) ,
1244
+ }
1245
+ }
1246
+
1247
+ #[ test]
1248
+ fn parses_invoice_with_created_at ( ) {
1249
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1250
+ . amount_msats ( 1000 )
1251
+ . build ( ) . unwrap ( )
1252
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1253
+ . build ( ) . unwrap ( )
1254
+ . sign ( payer_sign) . unwrap ( )
1255
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1256
+ . build ( ) . unwrap ( )
1257
+ . sign ( recipient_sign) . unwrap ( ) ;
1258
+
1259
+ let mut buffer = Vec :: new ( ) ;
1260
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1261
+
1262
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1263
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1264
+ }
1265
+
1266
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1267
+ tlv_stream. 3 . created_at = None ;
1268
+
1269
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1270
+ Ok ( _) => panic ! ( "expected error" ) ,
1271
+ Err ( e) => {
1272
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingCreationTime ) ) ;
1273
+ } ,
1274
+ }
1275
+ }
1276
+
1277
+ #[ test]
1278
+ fn parses_invoice_with_payment_hash ( ) {
1279
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1280
+ . amount_msats ( 1000 )
1281
+ . build ( ) . unwrap ( )
1282
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1283
+ . build ( ) . unwrap ( )
1284
+ . sign ( payer_sign) . unwrap ( )
1285
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1286
+ . build ( ) . unwrap ( )
1287
+ . sign ( recipient_sign) . unwrap ( ) ;
1288
+
1289
+ let mut buffer = Vec :: new ( ) ;
1290
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1291
+
1292
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1293
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1294
+ }
1295
+
1296
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1297
+ tlv_stream. 3 . payment_hash = None ;
1298
+
1299
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1300
+ Ok ( _) => panic ! ( "expected error" ) ,
1301
+ Err ( e) => {
1302
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPaymentHash ) ) ;
1303
+ } ,
1304
+ }
1305
+ }
1306
+
1307
+ #[ test]
1308
+ fn parses_invoice_with_amount ( ) {
1309
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1310
+ . amount_msats ( 1000 )
1311
+ . build ( ) . unwrap ( )
1312
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1313
+ . build ( ) . unwrap ( )
1314
+ . sign ( payer_sign) . unwrap ( )
1315
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1316
+ . build ( ) . unwrap ( )
1317
+ . sign ( recipient_sign) . unwrap ( ) ;
1318
+
1319
+ let mut buffer = Vec :: new ( ) ;
1320
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1321
+
1322
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1323
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1324
+ }
1325
+
1326
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1327
+ tlv_stream. 3 . amount = None ;
1328
+
1329
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1330
+ Ok ( _) => panic ! ( "expected error" ) ,
1331
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingAmount ) ) ,
1332
+ }
1333
+ }
1334
+
1335
+ #[ test]
1336
+ fn parses_invoice_with_node_id ( ) {
1337
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1338
+ . amount_msats ( 1000 )
1339
+ . build ( ) . unwrap ( )
1340
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1341
+ . build ( ) . unwrap ( )
1342
+ . sign ( payer_sign) . unwrap ( )
1343
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1344
+ . build ( ) . unwrap ( )
1345
+ . sign ( recipient_sign) . unwrap ( ) ;
1346
+
1347
+ let mut buffer = Vec :: new ( ) ;
1348
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1349
+
1350
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1351
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1352
+ }
1353
+
1354
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1355
+ tlv_stream. 3 . node_id = None ;
1356
+
1357
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1358
+ Ok ( _) => panic ! ( "expected error" ) ,
1359
+ Err ( e) => {
1360
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingSigningPubkey ) ) ;
1361
+ } ,
1362
+ }
1363
+ }
1364
+
1365
+ #[ test]
1366
+ fn fails_parsing_invoice_without_signature ( ) {
1367
+ let mut buffer = Vec :: new ( ) ;
1368
+ OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1369
+ . amount_msats ( 1000 )
1370
+ . build ( ) . unwrap ( )
1371
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1372
+ . build ( ) . unwrap ( )
1373
+ . sign ( payer_sign) . unwrap ( )
1374
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1375
+ . build ( ) . unwrap ( )
1376
+ . invoice
1377
+ . write ( & mut buffer) . unwrap ( ) ;
1378
+
1379
+ match Invoice :: try_from ( buffer) {
1380
+ Ok ( _) => panic ! ( "expected error" ) ,
1381
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingSignature ) ) ,
1382
+ }
1383
+ }
1384
+
1385
+ #[ test]
1386
+ fn fails_parsing_invoice_with_invalid_signature ( ) {
1387
+ let mut invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1388
+ . amount_msats ( 1000 )
1389
+ . build ( ) . unwrap ( )
1390
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1391
+ . build ( ) . unwrap ( )
1392
+ . sign ( payer_sign) . unwrap ( )
1393
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1394
+ . build ( ) . unwrap ( )
1395
+ . sign ( recipient_sign) . unwrap ( ) ;
1396
+ let last_signature_byte = invoice. bytes . last_mut ( ) . unwrap ( ) ;
1397
+ * last_signature_byte = last_signature_byte. wrapping_add ( 1 ) ;
1398
+
1399
+ let mut buffer = Vec :: new ( ) ;
1400
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1401
+
1402
+ match Invoice :: try_from ( buffer) {
1403
+ Ok ( _) => panic ! ( "expected error" ) ,
1404
+ Err ( e) => {
1405
+ assert_eq ! ( e, ParseError :: InvalidSignature ( secp256k1:: Error :: InvalidSignature ) ) ;
1406
+ } ,
1407
+ }
1408
+ }
1409
+
1410
+ #[ test]
1411
+ fn fails_parsing_invoice_with_extra_tlv_records ( ) {
1412
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1413
+ . amount_msats ( 1000 )
1414
+ . build ( ) . unwrap ( )
1415
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1416
+ . build ( ) . unwrap ( )
1417
+ . sign ( payer_sign) . unwrap ( )
1418
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1419
+ . build ( ) . unwrap ( )
1420
+ . sign ( recipient_sign) . unwrap ( ) ;
1421
+
1422
+ let mut encoded_invoice = Vec :: new ( ) ;
1423
+ invoice. write ( & mut encoded_invoice) . unwrap ( ) ;
1424
+ BigSize ( 1002 ) . write ( & mut encoded_invoice) . unwrap ( ) ;
1425
+ BigSize ( 32 ) . write ( & mut encoded_invoice) . unwrap ( ) ;
1426
+ [ 42u8 ; 32 ] . write ( & mut encoded_invoice) . unwrap ( ) ;
1427
+
1428
+ match Invoice :: try_from ( encoded_invoice) {
1429
+ Ok ( _) => panic ! ( "expected error" ) ,
1430
+ Err ( e) => assert_eq ! ( e, ParseError :: Decode ( DecodeError :: InvalidValue ) ) ,
1431
+ }
1432
+ }
1168
1433
}
0 commit comments