@@ -450,6 +450,12 @@ impl Writeable for Invoice {
450
450
}
451
451
}
452
452
453
+ impl Writeable for InvoiceContents {
454
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
455
+ self . as_tlv_stream ( ) . write ( writer)
456
+ }
457
+ }
458
+
453
459
impl TryFrom < Vec < u8 > > for Invoice {
454
460
type Error = ParseError ;
455
461
@@ -644,7 +650,7 @@ impl TryFrom<PartialInvoiceTlvStream> for InvoiceContents {
644
650
645
651
#[ cfg( test) ]
646
652
mod tests {
647
- use super :: { DEFAULT_RELATIVE_EXPIRY , BlindedPayInfo , FallbackAddress , Invoice , InvoiceTlvStreamRef , SIGNATURE_TAG } ;
653
+ use super :: { DEFAULT_RELATIVE_EXPIRY , BlindedPayInfo , FallbackAddress , FullInvoiceTlvStreamRef , Invoice , InvoiceTlvStreamRef , SIGNATURE_TAG } ;
648
654
649
655
use bitcoin:: blockdata:: script:: Script ;
650
656
use bitcoin:: hashes:: Hash ;
@@ -657,15 +663,16 @@ mod tests {
657
663
#[ cfg( feature = "std" ) ]
658
664
use core:: time:: Duration ;
659
665
use crate :: ln:: PaymentHash ;
666
+ use crate :: ln:: msgs:: DecodeError ;
660
667
use crate :: ln:: features:: { BlindedHopFeatures , Bolt12InvoiceFeatures } ;
661
668
use crate :: offers:: invoice_request:: InvoiceRequestTlvStreamRef ;
662
669
use crate :: offers:: merkle:: { SignError , SignatureTlvStreamRef , self } ;
663
670
use crate :: offers:: offer:: { OfferBuilder , OfferTlvStreamRef } ;
664
- use crate :: offers:: parse:: SemanticError ;
671
+ use crate :: offers:: parse:: { ParseError , SemanticError } ;
665
672
use crate :: offers:: payer:: PayerTlvStreamRef ;
666
673
use crate :: offers:: refund:: RefundBuilder ;
667
674
use crate :: onion_message:: { BlindedHop , BlindedPath } ;
668
- use crate :: util:: ser:: { Iterable , Writeable } ;
675
+ use crate :: util:: ser:: { BigSize , Iterable , Writeable } ;
669
676
670
677
fn payer_keys ( ) -> KeyPair {
671
678
let secp_ctx = Secp256k1 :: new ( ) ;
@@ -706,6 +713,22 @@ mod tests {
706
713
SecretKey :: from_slice ( & [ byte; 32 ] ) . unwrap ( )
707
714
}
708
715
716
+ trait ToBytes {
717
+ fn to_bytes ( & self ) -> Vec < u8 > ;
718
+ }
719
+
720
+ impl < ' a > ToBytes for FullInvoiceTlvStreamRef < ' a > {
721
+ fn to_bytes ( & self ) -> Vec < u8 > {
722
+ let mut buffer = Vec :: new ( ) ;
723
+ self . 0 . write ( & mut buffer) . unwrap ( ) ;
724
+ self . 1 . write ( & mut buffer) . unwrap ( ) ;
725
+ self . 2 . write ( & mut buffer) . unwrap ( ) ;
726
+ self . 3 . write ( & mut buffer) . unwrap ( ) ;
727
+ self . 4 . write ( & mut buffer) . unwrap ( ) ;
728
+ buffer
729
+ }
730
+ }
731
+
709
732
fn payment_paths ( ) -> Vec < ( BlindedPath , BlindedPayInfo ) > {
710
733
let paths = vec ! [
711
734
BlindedPath {
@@ -1092,4 +1115,246 @@ mod tests {
1092
1115
Err ( e) => assert_eq ! ( e, SignError :: Verification ( secp256k1:: Error :: InvalidSignature ) ) ,
1093
1116
}
1094
1117
}
1118
+
1119
+ #[ test]
1120
+ fn parses_invoice_with_payment_paths ( ) {
1121
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1122
+ . amount_msats ( 1000 )
1123
+ . build ( ) . unwrap ( )
1124
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1125
+ . build ( ) . unwrap ( )
1126
+ . sign ( payer_sign) . unwrap ( )
1127
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1128
+ . build ( ) . unwrap ( )
1129
+ . sign ( recipient_sign) . unwrap ( ) ;
1130
+
1131
+ let mut buffer = Vec :: new ( ) ;
1132
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1133
+
1134
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1135
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1136
+ }
1137
+
1138
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1139
+ tlv_stream. 3 . paths = None ;
1140
+
1141
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1142
+ Ok ( _) => panic ! ( "expected error" ) ,
1143
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPaths ) ) ,
1144
+ }
1145
+
1146
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1147
+ tlv_stream. 3 . blindedpay = None ;
1148
+
1149
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1150
+ Ok ( _) => panic ! ( "expected error" ) ,
1151
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InvalidPayInfo ) ) ,
1152
+ }
1153
+
1154
+ let empty_payment_paths = vec ! [ ] ;
1155
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1156
+ tlv_stream. 3 . paths = Some ( Iterable ( empty_payment_paths. iter ( ) . map ( |( path, _) | path) ) ) ;
1157
+
1158
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1159
+ Ok ( _) => panic ! ( "expected error" ) ,
1160
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPaths ) ) ,
1161
+ }
1162
+
1163
+ let mut payment_paths = payment_paths ( ) ;
1164
+ payment_paths. pop ( ) ;
1165
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1166
+ tlv_stream. 3 . blindedpay = Some ( Iterable ( payment_paths. iter ( ) . map ( |( _, payinfo) | payinfo) ) ) ;
1167
+
1168
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1169
+ Ok ( _) => panic ! ( "expected error" ) ,
1170
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: InvalidPayInfo ) ) ,
1171
+ }
1172
+ }
1173
+
1174
+ #[ test]
1175
+ fn parses_invoice_with_created_at ( ) {
1176
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1177
+ . amount_msats ( 1000 )
1178
+ . build ( ) . unwrap ( )
1179
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1180
+ . build ( ) . unwrap ( )
1181
+ . sign ( payer_sign) . unwrap ( )
1182
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1183
+ . build ( ) . unwrap ( )
1184
+ . sign ( recipient_sign) . unwrap ( ) ;
1185
+
1186
+ let mut buffer = Vec :: new ( ) ;
1187
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1188
+
1189
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1190
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1191
+ }
1192
+
1193
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1194
+ tlv_stream. 3 . created_at = None ;
1195
+
1196
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1197
+ Ok ( _) => panic ! ( "expected error" ) ,
1198
+ Err ( e) => {
1199
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingCreationTime ) ) ;
1200
+ } ,
1201
+ }
1202
+ }
1203
+
1204
+ #[ test]
1205
+ fn parses_invoice_with_payment_hash ( ) {
1206
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1207
+ . amount_msats ( 1000 )
1208
+ . build ( ) . unwrap ( )
1209
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1210
+ . build ( ) . unwrap ( )
1211
+ . sign ( payer_sign) . unwrap ( )
1212
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1213
+ . build ( ) . unwrap ( )
1214
+ . sign ( recipient_sign) . unwrap ( ) ;
1215
+
1216
+ let mut buffer = Vec :: new ( ) ;
1217
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1218
+
1219
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1220
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1221
+ }
1222
+
1223
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1224
+ tlv_stream. 3 . payment_hash = None ;
1225
+
1226
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1227
+ Ok ( _) => panic ! ( "expected error" ) ,
1228
+ Err ( e) => {
1229
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingPaymentHash ) ) ;
1230
+ } ,
1231
+ }
1232
+ }
1233
+
1234
+ #[ test]
1235
+ fn parses_invoice_with_amount ( ) {
1236
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1237
+ . amount_msats ( 1000 )
1238
+ . build ( ) . unwrap ( )
1239
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1240
+ . build ( ) . unwrap ( )
1241
+ . sign ( payer_sign) . unwrap ( )
1242
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1243
+ . build ( ) . unwrap ( )
1244
+ . sign ( recipient_sign) . unwrap ( ) ;
1245
+
1246
+ let mut buffer = Vec :: new ( ) ;
1247
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1248
+
1249
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1250
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1251
+ }
1252
+
1253
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1254
+ tlv_stream. 3 . amount = None ;
1255
+
1256
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1257
+ Ok ( _) => panic ! ( "expected error" ) ,
1258
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingAmount ) ) ,
1259
+ }
1260
+ }
1261
+
1262
+ #[ test]
1263
+ fn parses_invoice_with_node_id ( ) {
1264
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1265
+ . amount_msats ( 1000 )
1266
+ . build ( ) . unwrap ( )
1267
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1268
+ . build ( ) . unwrap ( )
1269
+ . sign ( payer_sign) . unwrap ( )
1270
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1271
+ . build ( ) . unwrap ( )
1272
+ . sign ( recipient_sign) . unwrap ( ) ;
1273
+
1274
+ let mut buffer = Vec :: new ( ) ;
1275
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1276
+
1277
+ if let Err ( e) = Invoice :: try_from ( buffer) {
1278
+ panic ! ( "error parsing invoice: {:?}" , e) ;
1279
+ }
1280
+
1281
+ let mut tlv_stream = invoice. as_tlv_stream ( ) ;
1282
+ tlv_stream. 3 . node_id = None ;
1283
+
1284
+ match Invoice :: try_from ( tlv_stream. to_bytes ( ) ) {
1285
+ Ok ( _) => panic ! ( "expected error" ) ,
1286
+ Err ( e) => {
1287
+ assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingSigningPubkey ) ) ;
1288
+ } ,
1289
+ }
1290
+ }
1291
+
1292
+ #[ test]
1293
+ fn fails_parsing_invoice_without_signature ( ) {
1294
+ let mut buffer = Vec :: new ( ) ;
1295
+ OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1296
+ . amount_msats ( 1000 )
1297
+ . build ( ) . unwrap ( )
1298
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1299
+ . build ( ) . unwrap ( )
1300
+ . sign ( payer_sign) . unwrap ( )
1301
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1302
+ . build ( ) . unwrap ( )
1303
+ . invoice
1304
+ . write ( & mut buffer) . unwrap ( ) ;
1305
+
1306
+ match Invoice :: try_from ( buffer) {
1307
+ Ok ( _) => panic ! ( "expected error" ) ,
1308
+ Err ( e) => assert_eq ! ( e, ParseError :: InvalidSemantics ( SemanticError :: MissingSignature ) ) ,
1309
+ }
1310
+ }
1311
+
1312
+ #[ test]
1313
+ fn fails_parsing_invoice_with_invalid_signature ( ) {
1314
+ let mut invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1315
+ . amount_msats ( 1000 )
1316
+ . build ( ) . unwrap ( )
1317
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1318
+ . build ( ) . unwrap ( )
1319
+ . sign ( payer_sign) . unwrap ( )
1320
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1321
+ . build ( ) . unwrap ( )
1322
+ . sign ( recipient_sign) . unwrap ( ) ;
1323
+ let last_signature_byte = invoice. bytes . last_mut ( ) . unwrap ( ) ;
1324
+ * last_signature_byte = last_signature_byte. wrapping_add ( 1 ) ;
1325
+
1326
+ let mut buffer = Vec :: new ( ) ;
1327
+ invoice. write ( & mut buffer) . unwrap ( ) ;
1328
+
1329
+ match Invoice :: try_from ( buffer) {
1330
+ Ok ( _) => panic ! ( "expected error" ) ,
1331
+ Err ( e) => {
1332
+ assert_eq ! ( e, ParseError :: InvalidSignature ( secp256k1:: Error :: InvalidSignature ) ) ;
1333
+ } ,
1334
+ }
1335
+ }
1336
+
1337
+ #[ test]
1338
+ fn fails_parsing_invoice_with_extra_tlv_records ( ) {
1339
+ let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
1340
+ . amount_msats ( 1000 )
1341
+ . build ( ) . unwrap ( )
1342
+ . request_invoice ( vec ! [ 1 ; 32 ] , payer_pubkey ( ) ) . unwrap ( )
1343
+ . build ( ) . unwrap ( )
1344
+ . sign ( payer_sign) . unwrap ( )
1345
+ . respond_with ( payment_paths ( ) , payment_hash ( ) , now ( ) ) . unwrap ( )
1346
+ . build ( ) . unwrap ( )
1347
+ . sign ( recipient_sign) . unwrap ( ) ;
1348
+
1349
+ let mut encoded_invoice = Vec :: new ( ) ;
1350
+ invoice. write ( & mut encoded_invoice) . unwrap ( ) ;
1351
+ BigSize ( 1002 ) . write ( & mut encoded_invoice) . unwrap ( ) ;
1352
+ BigSize ( 32 ) . write ( & mut encoded_invoice) . unwrap ( ) ;
1353
+ [ 42u8 ; 32 ] . write ( & mut encoded_invoice) . unwrap ( ) ;
1354
+
1355
+ match Invoice :: try_from ( encoded_invoice) {
1356
+ Ok ( _) => panic ! ( "expected error" ) ,
1357
+ Err ( e) => assert_eq ! ( e, ParseError :: Decode ( DecodeError :: InvalidValue ) ) ,
1358
+ }
1359
+ }
1095
1360
}
0 commit comments