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