1
+ extern crate bitcoin_hashes;
2
+ extern crate lightning_invoice;
3
+ extern crate secp256k1;
4
+
5
+ use bitcoin_hashes:: hex:: FromHex ;
6
+ use bitcoin_hashes:: sha256:: Sha256Hash ;
7
+ use lightning_invoice:: * ;
8
+ use secp256k1:: { Secp256k1 , RecoverableSignature , RecoveryId } ;
9
+
10
+ // TODO: add more of the examples from BOLT11 and generate ones causing SemanticErrors
11
+
12
+ fn get_test_tuples ( ) -> Vec < ( String , SignedRawInvoice , Option < SemanticError > ) > {
13
+ vec ! [
14
+ (
15
+ "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmw\
16
+ wd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9\
17
+ ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w". to_owned( ) ,
18
+ InvoiceBuilder :: new( Currency :: Bitcoin )
19
+ . timestamp( 1496314658 )
20
+ . payment_hash( Sha256Hash :: from_hex(
21
+ "0001020304050607080900010203040506070809000102030405060708090102"
22
+ ) . unwrap( ) )
23
+ . description( "Please consider supporting this project" . to_owned( ) )
24
+ . build_raw( )
25
+ . unwrap( )
26
+ . sign( |_| {
27
+ RecoverableSignature :: from_compact(
28
+ & Secp256k1 :: without_caps( ) ,
29
+ & [
30
+ 0x38u8 , 0xec , 0x68 , 0x91 , 0x34 , 0x5e , 0x20 , 0x41 , 0x45 , 0xbe , 0x8a ,
31
+ 0x3a , 0x99 , 0xde , 0x38 , 0xe9 , 0x8a , 0x39 , 0xd6 , 0xa5 , 0x69 , 0x43 ,
32
+ 0x4e , 0x18 , 0x45 , 0xc8 , 0xaf , 0x72 , 0x05 , 0xaf , 0xcf , 0xcc , 0x7f ,
33
+ 0x42 , 0x5f , 0xcd , 0x14 , 0x63 , 0xe9 , 0x3c , 0x32 , 0x88 , 0x1e , 0xad ,
34
+ 0x0d , 0x6e , 0x35 , 0x6d , 0x46 , 0x7e , 0xc8 , 0xc0 , 0x25 , 0x53 , 0xf9 ,
35
+ 0xaa , 0xb1 , 0x5e , 0x57 , 0x38 , 0xb1 , 0x1f , 0x12 , 0x7f
36
+ ] ,
37
+ RecoveryId :: from_i32( 0 ) . unwrap( )
38
+ )
39
+ } ) . unwrap( ) ,
40
+ None
41
+ ) ,
42
+ (
43
+ "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3\
44
+ k7enxv4jsxqzpuaztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch\
45
+ 9zw97j25emudupq63nyw24cg27h2rspfj9srp". to_owned( ) ,
46
+ InvoiceBuilder :: new( Currency :: Bitcoin )
47
+ . amount_pico_btc( 2500000000 )
48
+ . timestamp( 1496314658 )
49
+ . payment_hash( Sha256Hash :: from_hex(
50
+ "0001020304050607080900010203040506070809000102030405060708090102"
51
+ ) . unwrap( ) )
52
+ . description( "1 cup coffee" . to_owned( ) )
53
+ . expiry_time_seconds( 60 )
54
+ . build_raw( )
55
+ . unwrap( )
56
+ . sign( |_| {
57
+ RecoverableSignature :: from_compact(
58
+ & Secp256k1 :: without_caps( ) ,
59
+ & [
60
+ 0xe8 , 0x96 , 0x39 , 0xba , 0x68 , 0x14 , 0xe3 , 0x66 , 0x89 , 0xd4 , 0xb9 , 0x1b ,
61
+ 0xf1 , 0x25 , 0xf1 , 0x03 , 0x51 , 0xb5 , 0x5d , 0xa0 , 0x57 , 0xb0 , 0x06 , 0x47 ,
62
+ 0xa8 , 0xda , 0xba , 0xeb , 0x8a , 0x90 , 0xc9 , 0x5f , 0x16 , 0x0f , 0x9d , 0x5a ,
63
+ 0x6e , 0x0f , 0x79 , 0xd1 , 0xfc , 0x2b , 0x96 , 0x42 , 0x38 , 0xb9 , 0x44 , 0xe2 ,
64
+ 0xfa , 0x4a , 0xa6 , 0x77 , 0xc6 , 0xf0 , 0x20 , 0xd4 , 0x66 , 0x47 , 0x2a , 0xb8 ,
65
+ 0x42 , 0xbd , 0x75 , 0x0e
66
+ ] ,
67
+ RecoveryId :: from_i32( 1 ) . unwrap( )
68
+ )
69
+ } ) . unwrap( ) ,
70
+ None
71
+ ) ,
72
+ (
73
+ "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qq\
74
+ dhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqscc6gd6ql3jrc5yzme8v4ntcewwz5cnw92tz0pc8qcuufvq7k\
75
+ hhr8wpald05e92xw006sq94mg8v2ndf4sefvf9sygkshp5zfem29trqq2yxxz7". to_owned( ) ,
76
+ InvoiceBuilder :: new( Currency :: Bitcoin )
77
+ . amount_pico_btc( 20000000000 )
78
+ . timestamp( 1496314658 )
79
+ . payment_hash( Sha256Hash :: from_hex(
80
+ "0001020304050607080900010203040506070809000102030405060708090102"
81
+ ) . unwrap( ) )
82
+ . description_hash( Sha256Hash :: from_hex(
83
+ "3925b6f67e2c340036ed12093dd44e0368df1b6ea26c53dbe4811f58fd5db8c1"
84
+ ) . unwrap( ) )
85
+ . build_raw( )
86
+ . unwrap( )
87
+ . sign( |_| {
88
+ RecoverableSignature :: from_compact(
89
+ & Secp256k1 :: without_caps( ) ,
90
+ & [
91
+ 0xc6 , 0x34 , 0x86 , 0xe8 , 0x1f , 0x8c , 0x87 , 0x8a , 0x10 , 0x5b , 0xc9 , 0xd9 ,
92
+ 0x59 , 0xaf , 0x19 , 0x73 , 0x85 , 0x4c , 0x4d , 0xc5 , 0x52 , 0xc4 , 0xf0 , 0xe0 ,
93
+ 0xe0 , 0xc7 , 0x38 , 0x96 , 0x03 , 0xd6 , 0xbd , 0xc6 , 0x77 , 0x07 , 0xbf , 0x6b ,
94
+ 0xe9 , 0x92 , 0xa8 , 0xce , 0x7b , 0xf5 , 0x00 , 0x16 , 0xbb , 0x41 , 0xd8 , 0xa9 ,
95
+ 0xb5 , 0x35 , 0x86 , 0x52 , 0xc4 , 0x96 , 0x04 , 0x45 , 0xa1 , 0x70 , 0xd0 , 0x49 ,
96
+ 0xce , 0xd4 , 0x55 , 0x8c
97
+ ] ,
98
+ RecoveryId :: from_i32( 0 ) . unwrap( )
99
+ )
100
+ } ) . unwrap( ) ,
101
+ None
102
+ )
103
+ ]
104
+ }
105
+
106
+
107
+ #[ test]
108
+ fn serialize ( ) {
109
+ for ( serialized, deserialized, _) in get_test_tuples ( ) {
110
+ assert_eq ! ( deserialized. to_string( ) , serialized) ;
111
+ }
112
+ }
113
+
114
+ #[ test]
115
+ fn deserialize ( ) {
116
+ for ( serialized, deserialized, maybe_error) in get_test_tuples ( ) {
117
+ let parsed = serialized. parse :: < SignedRawInvoice > ( ) . unwrap ( ) ;
118
+
119
+ assert_eq ! ( parsed, deserialized) ;
120
+
121
+ let validated = Invoice :: from_signed ( parsed) ;
122
+
123
+ if let Some ( error) = maybe_error {
124
+ assert_eq ! ( Err ( error) , validated) ;
125
+ } else {
126
+ assert ! ( validated. is_ok( ) ) ;
127
+ }
128
+ }
129
+ }
0 commit comments