Drop explicit `bitcoin_hashes` dependency in `lightning-invoice`
[rust-lightning] / lightning-invoice / tests / ser_de.rs
1 extern crate bech32;
2 extern crate lightning;
3 extern crate lightning_invoice;
4 extern crate secp256k1;
5 extern crate hex;
6
7 use bitcoin::address::WitnessVersion;
8 use bitcoin::{PubkeyHash, ScriptHash};
9 use bitcoin::hashes::hex::FromHex;
10 use bitcoin::hashes::{sha256, Hash};
11 use lightning::ln::PaymentSecret;
12 use lightning::routing::gossip::RoutingFees;
13 use lightning::routing::router::{RouteHint, RouteHintHop};
14 use lightning_invoice::*;
15 use secp256k1::PublicKey;
16 use secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
17 use std::collections::HashSet;
18 use std::time::Duration;
19 use std::str::FromStr;
20
21 fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> {
22         vec![
23                 (
24                         "lnbc1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq9qrsgq357wnc5r2ueh7ck6q93dj32dlqnls087fxdwk8qakdyafkq3yap9us6v52vjjsrvywa6rt52cm9r9zqt8r2t7mlcwspyetp5h2tztugp9lfyql".to_owned(),
25                         InvoiceBuilder::new(Currency::Bitcoin)
26                                 .duration_since_epoch(Duration::from_secs(1496314658))
27                                 .payment_secret(PaymentSecret([0x11; 32]))
28                                 .payment_hash(sha256::Hash::from_str(
29                                                 "0001020304050607080900010203040506070809000102030405060708090102"
30                                 ).unwrap())
31                                 .description("Please consider supporting this project".to_owned())
32                                 .build_raw()
33                                 .unwrap()
34                                 .sign(|_| {
35                                         RecoverableSignature::from_compact(
36                                                 &<Vec<u8>>::from_hex("8d3ce9e28357337f62da0162d9454df827f83cfe499aeb1c1db349d4d81127425e434ca29929406c23bba1ae8ac6ca32880b38d4bf6ff874024cac34ba9625f1").unwrap(),
37                                                 RecoveryId::from_i32(1).unwrap()
38                                         )
39                                 }).unwrap(),
40                         false, // Same features as set in InvoiceBuilder
41                         false, // No unknown fields
42                 ),
43                 (
44                         "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9vdx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh".to_owned(),
45                         InvoiceBuilder::new(Currency::Bitcoin)
46                                 .amount_milli_satoshis(250_000_000)
47                                 .duration_since_epoch(Duration::from_secs(1496314658))
48                                 .payment_secret(PaymentSecret([0x11; 32]))
49                                 .payment_hash(sha256::Hash::from_str(
50                                         "0001020304050607080900010203040506070809000102030405060708090102"
51                                 ).unwrap())
52                                 .description("1 cup coffee".to_owned())
53                                 .expiry_time(Duration::from_secs(60))
54                                 .build_raw()
55                                 .unwrap()
56                                 .sign(|_| {
57                                         RecoverableSignature::from_compact(
58                                                 &<Vec<u8>>::from_hex("e59e3ffbd3945e4334879158d31e89b076dff54f3fa7979ae79df2db9dcaf5896cbfe1a478b8d2307e92c88139464cb7e6ef26e414c4abe33337961ddc5e8ab1").unwrap(),
59                                                 RecoveryId::from_i32(1).unwrap()
60                                         )
61                                 }).unwrap(),
62                         false, // Same features as set in InvoiceBuilder
63                         false, // No unknown fields
64                 ),
65                 (
66                         "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpu9qrsgqhtjpauu9ur7fw2thcl4y9vfvh4m9wlfyz2gem29g5ghe2aak2pm3ps8fdhtceqsaagty2vph7utlgj48u0ged6a337aewvraedendscp573dxr".to_owned(),
67                         InvoiceBuilder::new(Currency::Bitcoin)
68                                 .amount_milli_satoshis(250_000_000)
69                                 .duration_since_epoch(Duration::from_secs(1496314658))
70                                 .payment_secret(PaymentSecret([0x11; 32]))
71                                 .payment_hash(sha256::Hash::from_str(
72                                         "0001020304050607080900010203040506070809000102030405060708090102"
73                                 ).unwrap())
74                                 .description("ナンセンス 1杯".to_owned())
75                                 .expiry_time(Duration::from_secs(60))
76                                 .build_raw()
77                                 .unwrap()
78                                 .sign(|_| {
79                                         RecoverableSignature::from_compact(
80                                                 &<Vec<u8>>::from_hex("bae41ef385e0fc972977c7ea42b12cbd76577d2412919da8a8a22f9577b6507710c0e96dd78c821dea16453037f717f44aa7e3d196ebb18fbb97307dcb7336c3").unwrap(),
81                                                 RecoveryId::from_i32(1).unwrap()
82                                         )
83                                 }).unwrap(),
84                         false, // Same features as set in InvoiceBuilder
85                         false, // No unknown fields
86                 ),
87                 (
88                         "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs9qrsgq7ea976txfraylvgzuxs8kgcw23ezlrszfnh8r6qtfpr6cxga50aj6txm9rxrydzd06dfeawfk6swupvz4erwnyutnjq7x39ymw6j38gp7ynn44".to_owned(),
89                         InvoiceBuilder::new(Currency::Bitcoin)
90                                 .amount_milli_satoshis(2_000_000_000)
91                                 .duration_since_epoch(Duration::from_secs(1496314658))
92                                 .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon"))
93                                 .payment_secret(PaymentSecret([0x11; 32]))
94                                 .payment_hash(sha256::Hash::from_str(
95                                         "0001020304050607080900010203040506070809000102030405060708090102"
96                                 ).unwrap())
97                                 .build_raw()
98                                 .unwrap()
99                                 .sign(|_| {
100                                         RecoverableSignature::from_compact(
101                                                 &<Vec<u8>>::from_hex("f67a5f696648fa4fb102e1a07b230e54722f8e024cee71e80b4847ac191da3fb2d2cdb28cc32344d7e9a9cf5c9b6a0ee0582ae46e9938b9c81e344a4dbb5289d").unwrap(),
102                                                 RecoveryId::from_i32(1).unwrap()
103                                         )
104                                 }).unwrap(),
105                         false, // Same features as set in InvoiceBuilder
106                         false, // No unknown fields
107                 ),
108                 (
109                         "lntb20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfpp3x9et2e20v6pu37c5d9vax37wxq72un989qrsgqdj545axuxtnfemtpwkc45hx9d2ft7x04mt8q7y6t0k2dge9e7h8kpy9p34ytyslj3yu569aalz2xdk8xkd7ltxqld94u8h2esmsmacgpghe9k8".to_owned(),
110                         InvoiceBuilder::new(Currency::BitcoinTestnet)
111                                 .amount_milli_satoshis(2_000_000_000)
112                                 .duration_since_epoch(Duration::from_secs(1496314658))
113                                 .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon"))
114                                 .payment_secret(PaymentSecret([0x11; 32]))
115                                 .payment_hash(sha256::Hash::from_str(
116                                         "0001020304050607080900010203040506070809000102030405060708090102"
117                                 ).unwrap())
118                                 .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[49, 114, 181, 101, 79, 102, 131, 200, 251, 20, 105, 89, 211, 71, 206, 48, 60, 174, 76, 167]).unwrap()))
119                                 .build_raw()
120                                 .unwrap()
121                                 .sign(|_| {
122                                         RecoverableSignature::from_compact(
123                                                 &<Vec<u8>>::from_hex("6ca95a74dc32e69ced6175b15a5cc56a92bf19f5dace0f134b7d94d464b9f5cf6090a18d48b243f289394d17bdf89466d8e6b37df5981f696bc3dd5986e1bee1").unwrap(),
124                                                 RecoveryId::from_i32(1).unwrap()
125                                         )
126                                 }).unwrap(),
127                         false, // Same features as set in InvoiceBuilder
128                         false, // No unknown fields
129                 ),
130                 (
131                         "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq9qrsgqdfjcdk6w3ak5pca9hwfwfh63zrrz06wwfya0ydlzpgzxkn5xagsqz7x9j4jwe7yj7vaf2k9lqsdk45kts2fd0fkr28am0u4w95tt2nsq76cqw0".to_owned(),
132                         InvoiceBuilder::new(Currency::Bitcoin)
133                                 .amount_milli_satoshis(2_000_000_000)
134                                 .duration_since_epoch(Duration::from_secs(1496314658))
135                                 .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon"))
136                                 .payment_secret(PaymentSecret([0x11; 32]))
137                                 .payment_hash(sha256::Hash::from_str(
138                                         "0001020304050607080900010203040506070809000102030405060708090102"
139                                 ).unwrap())
140                                 .fallback(Fallback::PubKeyHash(PubkeyHash::from_slice(&[4, 182, 31, 125, 193, 234, 13, 201, 148, 36, 70, 76, 196, 6, 77, 197, 100, 217, 30, 137]).unwrap()))
141                                 .private_route(RouteHint(vec![RouteHintHop {
142                                         src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
143                                                         "029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"
144                                                 ).unwrap()).unwrap(),
145                                         short_channel_id: (66051 << 40) | (263430 << 16) | 1800,
146                                         fees: RoutingFees { base_msat: 1, proportional_millionths: 20 },
147                                         cltv_expiry_delta: 3,
148                                         htlc_maximum_msat: None, htlc_minimum_msat: None,
149                                 }, RouteHintHop {
150                                         src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
151                                                         "039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"
152                                                 ).unwrap()).unwrap(),
153                                         short_channel_id: (197637 << 40) | (395016 << 16) | 2314,
154                                         fees: RoutingFees { base_msat: 2, proportional_millionths: 30 },
155                                         cltv_expiry_delta: 4,
156                                         htlc_maximum_msat: None, htlc_minimum_msat: None,
157                                 }]))
158                                 .build_raw()
159                                 .unwrap()
160                                 .sign(|_| {
161                                         RecoverableSignature::from_compact(
162                                                 &<Vec<u8>>::from_hex("6a6586db4e8f6d40e3a5bb92e4df5110c627e9ce493af237e20a046b4e86ea200178c59564ecf892f33a9558bf041b6ad2cb8292d7a6c351fbb7f2ae2d16b54e").unwrap(),
163                                                 RecoveryId::from_i32(0).unwrap()
164                                         )
165                                 }).unwrap(),
166                         false, // Same features as set in InvoiceBuilder
167                         false, // No unknown fields
168                 ),
169                 (
170                         "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppj3a24vwu6r8ejrss3axul8rxldph2q7z99qrsgqz6qsgww34xlatfj6e3sngrwfy3ytkt29d2qttr8qz2mnedfqysuqypgqex4haa2h8fx3wnypranf3pdwyluftwe680jjcfp438u82xqphf75ym".to_owned(),
171                         InvoiceBuilder::new(Currency::Bitcoin)
172                                 .amount_milli_satoshis(2_000_000_000)
173                                 .duration_since_epoch(Duration::from_secs(1496314658))
174                                 .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon"))
175                                 .payment_secret(PaymentSecret([0x11; 32]))
176                                 .payment_hash(sha256::Hash::from_str(
177                                         "0001020304050607080900010203040506070809000102030405060708090102"
178                                 ).unwrap())
179                                 .fallback(Fallback::ScriptHash(ScriptHash::from_slice(&[143, 85, 86, 59, 154, 25, 243, 33, 194, 17, 233, 185, 243, 140, 223, 104, 110, 160, 120, 69]).unwrap()))
180                                 .build_raw()
181                                 .unwrap()
182                                 .sign(|_| {
183                                         RecoverableSignature::from_compact(
184                                                 &<Vec<u8>>::from_hex("16810439d1a9bfd5a65acc61340dc92448bb2d456a80b58ce012b73cb5202438020500c9ab7ef5573a4d174c811f669885ae27f895bb3a3be52c243589f87518").unwrap(),
185                                                 RecoveryId::from_i32(1).unwrap()
186                                         )
187                                 }).unwrap(),
188                         false, // Same features as set in InvoiceBuilder
189                         false, // No unknown fields
190                 ),
191                 (
192                         "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppqw508d6qejxtdg4y5r3zarvary0c5xw7k9qrsgqt29a0wturnys2hhxpner2e3plp6jyj8qx7548zr2z7ptgjjc7hljm98xhjym0dg52sdrvqamxdezkmqg4gdrvwwnf0kv2jdfnl4xatsqmrnsse".to_owned(),
193                         InvoiceBuilder::new(Currency::Bitcoin)
194                                 .amount_milli_satoshis(2_000_000_000)
195                                 .duration_since_epoch(Duration::from_secs(1496314658))
196                                 .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon"))
197                                 .payment_secret(PaymentSecret([0x11; 32]))
198                                 .payment_hash(sha256::Hash::from_str(
199                                         "0001020304050607080900010203040506070809000102030405060708090102"
200                                 ).unwrap())
201                                 .fallback(Fallback::SegWitProgram { version: WitnessVersion::V0,
202                                         program: vec![117, 30, 118, 232, 25, 145, 150, 212, 84, 148, 28, 69, 209, 179, 163, 35, 241, 67, 59, 214]
203                                 })
204                                 .build_raw()
205                                 .unwrap()
206                                 .sign(|_| {
207                                         RecoverableSignature::from_compact(
208                                                 &<Vec<u8>>::from_hex("5a8bd7b97c1cc9055ee60cf2356621f8752248e037a953886a1782b44a58f5ff2d94e6bc89b7b514541a3603bb33722b6c08aa1a3639d34becc549a99fea6eae").unwrap(),
209                                                 RecoveryId::from_i32(0).unwrap()
210                                         )
211                                 }).unwrap(),
212                         false, // Same features as set in InvoiceBuilder
213                         false, // No unknown fields
214                 ),
215                 (
216                         "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq9vlvyj8cqvq6ggvpwd53jncp9nwc47xlrsnenq2zp70fq83qlgesn4u3uyf4tesfkkwwfg3qs54qe426hp3tz7z6sweqdjg05axsrjqp9yrrwc".to_owned(),
217                         InvoiceBuilder::new(Currency::Bitcoin)
218                                 .amount_milli_satoshis(2_000_000_000)
219                                 .duration_since_epoch(Duration::from_secs(1496314658))
220                                 .description_hash(sha256::Hash::hash(b"One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon"))
221                                 .payment_secret(PaymentSecret([0x11; 32]))
222                                 .payment_hash(sha256::Hash::from_str(
223                                         "0001020304050607080900010203040506070809000102030405060708090102"
224                                 ).unwrap())
225                                 .fallback(Fallback::SegWitProgram { version: WitnessVersion::V0,
226                                         program: vec![24, 99, 20, 60, 20, 197, 22, 104, 4, 189, 25, 32, 51, 86, 218, 19, 108, 152, 86, 120, 205, 77, 39, 161, 184, 198, 50, 150, 4, 144, 50, 98]
227                                 })
228                                 .build_raw()
229                                 .unwrap()
230                                 .sign(|_| {
231                                         RecoverableSignature::from_compact(
232                                                 &<Vec<u8>>::from_hex("2b3ec248f80301a421817369194f012cdd8af8df1c279981420f9e901e20fa3309d791e11355e609b59ce4a220852a0cd55ab862b1785a83b206c90fa74d01c8").unwrap(),
233                                                 RecoveryId::from_i32(1).unwrap()
234                                         )
235                                 }).unwrap(),
236                         false, // Same features as set in InvoiceBuilder
237                         false, // No unknown fields
238                 ),
239                 (
240                         "lnbc9678785340p1pwmna7lpp5gc3xfm08u9qy06djf8dfflhugl6p7lgza6dsjxq454gxhj9t7a0sd8dgfkx7cmtwd68yetpd5s9xar0wfjn5gpc8qhrsdfq24f5ggrxdaezqsnvda3kkum5wfjkzmfqf3jkgem9wgsyuctwdus9xgrcyqcjcgpzgfskx6eqf9hzqnteypzxz7fzypfhg6trddjhygrcyqezcgpzfysywmm5ypxxjemgw3hxjmn8yptk7untd9hxwg3q2d6xjcmtv4ezq7pqxgsxzmnyyqcjqmt0wfjjq6t5v4khxsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsxqyjw5qcqp2rzjq0gxwkzc8w6323m55m4jyxcjwmy7stt9hwkwe2qxmy8zpsgg7jcuwz87fcqqeuqqqyqqqqlgqqqqn3qq9q9qrsgqrvgkpnmps664wgkp43l22qsgdw4ve24aca4nymnxddlnp8vh9v2sdxlu5ywdxefsfvm0fq3sesf08uf6q9a2ke0hc9j6z6wlxg5z5kqpu2v9wz".to_owned(),
241                         InvoiceBuilder::new(Currency::Bitcoin)
242                                 .amount_milli_satoshis(967878534)
243                                 .duration_since_epoch(Duration::from_secs(1572468703))
244                                 .payment_secret(PaymentSecret([0x11; 32]))
245                                 .payment_hash(sha256::Hash::from_str(
246                                         "462264ede7e14047e9b249da94fefc47f41f7d02ee9b091815a5506bc8abf75f"
247                                 ).unwrap())
248                                 .expiry_time(Duration::from_secs(604800))
249                                 .min_final_cltv_expiry_delta(10)
250                                 .description("Blockstream Store: 88.85 USD for Blockstream Ledger Nano S x 1, \"Back In My Day\" Sticker x 2, \"I Got Lightning Working\" Sticker x 2 and 1 more items".to_owned())
251                                 .private_route(RouteHint(vec![RouteHintHop {
252                                         src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
253                                                         "03d06758583bb5154774a6eb221b1276c9e82d65bbaceca806d90e20c108f4b1c7"
254                                                 ).unwrap()).unwrap(),
255                                         short_channel_id: (589390 << 40) | (3312 << 16) | 1,
256                                         fees: RoutingFees { base_msat: 1000, proportional_millionths: 2500 },
257                                         cltv_expiry_delta: 40,
258                                         htlc_maximum_msat: None, htlc_minimum_msat: None,
259                                 }]))
260                                 .build_raw()
261                                 .unwrap()
262                                 .sign(|_| {
263                                         RecoverableSignature::from_compact(
264                                                 &<Vec<u8>>::from_hex("1b1160cf6186b55722c1ac7ea502086baaccaabdc76b326e666b7f309d972b15069bfca11cd365304b36f48230cc12f3f13a017aab65f7c165a169df32282a58").unwrap(),
265                                                 RecoveryId::from_i32(1).unwrap()
266                                         )
267                                 }).unwrap(),
268                         false, // Same features as set in InvoiceBuilder
269                         false, // No unknown fields
270                 ),
271                 (
272                         "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2a25dxl5hrntdtn6zvydt7d66hyzsyhqs4wdynavys42xgl6sgx9c4g7me86a27t07mdtfry458rtjr0v92cnmswpsjscgt2vcse3sgpz3uapa".to_owned(),
273                         InvoiceBuilder::new(Currency::Bitcoin)
274                                 .amount_milli_satoshis(2_500_000_000)
275                                 .duration_since_epoch(Duration::from_secs(1496314658))
276                                 .payment_secret(PaymentSecret([0x11; 32]))
277                                 .payment_hash(sha256::Hash::from_str(
278                                         "0001020304050607080900010203040506070809000102030405060708090102"
279                                 ).unwrap())
280                                 .description("coffee beans".to_owned())
281                                 .build_raw()
282                                 .unwrap()
283                                 .sign(|_| {
284                                         RecoverableSignature::from_compact(
285                                                 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
286                                                 RecoveryId::from_i32(1).unwrap()
287                                         )
288                                 }).unwrap(),
289                         true, // Different features than set in InvoiceBuilder
290                         false, // No unknown fields
291                 ),
292                 (
293                         "LNBC25M1PVJLUEZPP5QQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQYPQDQ5VDHKVEN9V5SXYETPDEESSP5ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYGS9Q5SQQQQQQQQQQQQQQQQSGQ2A25DXL5HRNTDTN6ZVYDT7D66HYZSYHQS4WDYNAVYS42XGL6SGX9C4G7ME86A27T07MDTFRY458RTJR0V92CNMSWPSJSCGT2VCSE3SGPZ3UAPA".to_owned(),
294                         InvoiceBuilder::new(Currency::Bitcoin)
295                                 .amount_milli_satoshis(2_500_000_000)
296                                 .duration_since_epoch(Duration::from_secs(1496314658))
297                                 .payment_secret(PaymentSecret([0x11; 32]))
298                                 .payment_hash(sha256::Hash::from_str(
299                                         "0001020304050607080900010203040506070809000102030405060708090102"
300                                 ).unwrap())
301                                 .description("coffee beans".to_owned())
302                                 .build_raw()
303                                 .unwrap()
304                                 .sign(|_| {
305                                         RecoverableSignature::from_compact(
306                                                 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
307                                                 RecoveryId::from_i32(1).unwrap()
308                                         )
309                                 }).unwrap(),
310                         true, // Different features than set in InvoiceBuilder
311                         false, // No unknown fields
312                 ),
313                 (
314                         "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2qrqqqfppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhpnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqspnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnp5qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnpkqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqz599y53s3ujmcfjp5xrdap68qxymkqphwsexhmhr8wdz5usdzkzrse33chw6dlp3jhuhge9ley7j2ayx36kawe7kmgg8sv5ugdyusdcqzn8z9x".to_owned(),
315                         InvoiceBuilder::new(Currency::Bitcoin)
316                                 .amount_milli_satoshis(2_500_000_000)
317                                 .duration_since_epoch(Duration::from_secs(1496314658))
318                                 .payment_secret(PaymentSecret([0x11; 32]))
319                                 .payment_hash(sha256::Hash::from_str(
320                                         "0001020304050607080900010203040506070809000102030405060708090102"
321                                 ).unwrap())
322                                 .description("coffee beans".to_owned())
323                                 .build_raw()
324                                 .unwrap()
325                                 .sign(|_| {
326                                         RecoverableSignature::from_compact(
327                                                 &<Vec<u8>>::from_hex("150a5252308f25bc2641a186de87470189bb003774326beee33b9a2a720d1584386631c5dda6fc3195f97464bfc93d2574868eadd767d6da1078329c4349c837").unwrap(),
328                                                 RecoveryId::from_i32(0).unwrap()
329                                         )
330                                 }).unwrap(),
331                         true, // Different features than set in InvoiceBuilder
332                         true, // Some unknown fields
333                 ),
334                 ( // Older version of the payment metadata test with a payment_pubkey set
335                         "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqnp4q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66sp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgqy9gw6ymamd20jumvdgpfphkhp8fzhhdhycw36egcmla5vlrtrmhs9t7psfy3hkkdqzm9eq64fjg558znccds5nhsfmxveha5xe0dykgpspdha0".to_owned(),
336                         InvoiceBuilder::new(Currency::Bitcoin)
337                                 .amount_milli_satoshis(1_000_000_000)
338                                 .duration_since_epoch(Duration::from_secs(1496314658))
339                                 .payment_hash(sha256::Hash::from_str(
340                                         "0001020304050607080900010203040506070809000102030405060708090102"
341                                 ).unwrap())
342                                 .description("payment metadata inside".to_owned())
343                                 .payment_metadata(<Vec<u8>>::from_hex("01fafaf0").unwrap())
344                                 .require_payment_metadata()
345                                 .payee_pub_key(PublicKey::from_slice(&<Vec<u8>>::from_hex(
346                                                 "03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad"
347                                         ).unwrap()).unwrap())
348                                 .payment_secret(PaymentSecret([0x11; 32]))
349                                 .build_raw()
350                                 .unwrap()
351                                 .sign(|_| {
352                                         RecoverableSignature::from_compact(
353                                                 &<Vec<u8>>::from_hex("2150ed137ddb54f9736c6a0290ded709d22bddb7261d1d6518dffb467c6b1eef02afc182491bdacd00b65c83554c914a1c53c61b0a4ef04eccccdfb4365ed259").unwrap(),
354                                                 RecoveryId::from_i32(1).unwrap()
355                                         )
356                                 }).unwrap(),
357                         false, // Different features than set in InvoiceBuilder
358                         true, // Some unknown fields
359                 ),
360                 (
361                         "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgq7hf8he7ecf7n4ffphs6awl9t6676rrclv9ckg3d3ncn7fct63p6s365duk5wrk202cfy3aj5xnnp5gs3vrdvruverwwq7yzhkf5a3xqpd05wjc".to_owned(),
362                         InvoiceBuilder::new(Currency::Bitcoin)
363                                 .amount_milli_satoshis(1_000_000_000)
364                                 .duration_since_epoch(Duration::from_secs(1496314658))
365                                 .payment_hash(sha256::Hash::from_str(
366                                         "0001020304050607080900010203040506070809000102030405060708090102"
367                                 ).unwrap())
368                                 .description("payment metadata inside".to_owned())
369                                 .payment_metadata(<Vec<u8>>::from_hex("01fafaf0").unwrap())
370                                 .require_payment_metadata()
371                                 .payment_secret(PaymentSecret([0x11; 32]))
372                                 .build_raw()
373                                 .unwrap()
374                                 .sign(|_| {
375                                         RecoverableSignature::from_compact(
376                                                 &<Vec<u8>>::from_hex("f5d27be7d9c27d3aa521bc35d77cabd6bda18f1f61716445b19e27e4e17a887508ea8de5a8e1d94f561248f65434e61a221160dac1f1991b9c0f1057b269d898").unwrap(),
377                                                 RecoveryId::from_i32(1).unwrap()
378                                         )
379                                 }).unwrap(),
380                         false, // Different features than set in InvoiceBuilder
381                         true, // Some unknown fields
382                 ),
383
384         ]
385 }
386
387 #[test]
388 fn invoice_deserialize() {
389         for (serialized, deserialized, ignore_feature_diff, ignore_unknown_fields) in get_test_tuples() {
390                 eprintln!("Testing invoice {}...", serialized);
391                 let parsed = serialized.parse::<SignedRawBolt11Invoice>().unwrap();
392
393                 let (parsed_invoice, _, parsed_sig) = parsed.into_parts();
394                 let (deserialized_invoice, _, deserialized_sig) = deserialized.into_parts();
395
396                 assert_eq!(deserialized_sig, parsed_sig);
397                 assert_eq!(deserialized_invoice.hrp, parsed_invoice.hrp);
398                 assert_eq!(deserialized_invoice.data.timestamp, parsed_invoice.data.timestamp);
399
400                 let mut deserialized_hunks: HashSet<_> = deserialized_invoice.data.tagged_fields.iter().collect();
401                 let mut parsed_hunks: HashSet<_> = parsed_invoice.data.tagged_fields.iter().collect();
402                 if ignore_feature_diff {
403                         deserialized_hunks.retain(|h|
404                                 if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true });
405                         parsed_hunks.retain(|h|
406                                 if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true });
407                 }
408                 if ignore_unknown_fields {
409                         parsed_hunks.retain(|h|
410                                 if let RawTaggedField::UnknownSemantics(_) = h { false } else { true });
411                 }
412                 assert_eq!(deserialized_hunks, parsed_hunks);
413
414                 Bolt11Invoice::from_signed(serialized.parse::<SignedRawBolt11Invoice>().unwrap()).unwrap();
415         }
416 }
417
418 #[test]
419 fn test_bolt_invalid_invoices() {
420         // Tests the BOLT 11 invalid invoice test vectors
421         assert_eq!(Bolt11Invoice::from_str(
422                 "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqqsgqtqyx5vggfcsll4wu246hz02kp85x4katwsk9639we5n5yngc3yhqkm35jnjw4len8vrnqnf5ejh0mzj9n3vz2px97evektfm2l6wqccp3y7372"
423                 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::InvalidFeatures)));
424         assert_eq!(Bolt11Invoice::from_str(
425                 "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt"
426                 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::InvalidChecksum))));
427         assert_eq!(Bolt11Invoice::from_str(
428                 "pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
429                 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MissingSeparator))));
430         assert_eq!(Bolt11Invoice::from_str(
431                 "LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
432                 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MixedCase))));
433         assert_eq!(Bolt11Invoice::from_str(
434                 "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqwgt7mcn5yqw3yx0w94pswkpq6j9uh6xfqqqtsk4tnarugeektd4hg5975x9am52rz4qskukxdmjemg92vvqz8nvmsye63r5ykel43pgz7zq0g2"
435                 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::InvalidSignature)));
436         assert_eq!(Bolt11Invoice::from_str(
437                 "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh"
438                 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::TooShortDataPart)));
439         assert_eq!(Bolt11Invoice::from_str(
440                 "lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqrrzc4cvfue4zp3hggxp47ag7xnrlr8vgcmkjxk3j5jqethnumgkpqp23z9jclu3v0a7e0aruz366e9wqdykw6dxhdzcjjhldxq0w6wgqcnu43j"
441                 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::UnknownSiPrefix)));
442         assert_eq!(Bolt11Invoice::from_str(
443                 "lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgq0lzc236j96a95uv0m3umg28gclm5lqxtqqwk32uuk4k6673k6n5kfvx3d2h8s295fad45fdhmusm8sjudfhlf6dcsxmfvkeywmjdkxcp99202x"
444                 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::ImpreciseAmount)));
445 }