2 extern crate lightning;
3 extern crate lightning_invoice;
4 extern crate secp256k1;
7 use bitcoin::{PubkeyHash, ScriptHash, WitnessVersion};
8 use bitcoin::hashes::hex::FromHex;
9 use bitcoin::hashes::{sha256, Hash};
10 use lightning_invoice::*;
11 use secp256k1::PublicKey;
12 use secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
13 use std::collections::HashSet;
14 use std::time::Duration;
15 use std::str::FromStr;
17 fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> {
20 "lnbc1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq9qrsgq357wnc5r2ueh7ck6q93dj32dlqnls087fxdwk8qakdyafkq3yap9us6v52vjjsrvywa6rt52cm9r9zqt8r2t7mlcwspyetp5h2tztugp9lfyql".to_owned(),
21 InvoiceBuilder::new(Currency::Bitcoin)
22 .duration_since_epoch(Duration::from_secs(1496314658))
23 .payment_secret(PaymentSecret([0x11; 32]))
24 .payment_hash(sha256::Hash::from_str(
25 "0001020304050607080900010203040506070809000102030405060708090102"
27 .description("Please consider supporting this project".to_owned())
31 RecoverableSignature::from_compact(
32 &<Vec<u8>>::from_hex("8d3ce9e28357337f62da0162d9454df827f83cfe499aeb1c1db349d4d81127425e434ca29929406c23bba1ae8ac6ca32880b38d4bf6ff874024cac34ba9625f1").unwrap(),
33 RecoveryId::from_i32(1).unwrap()
36 false, // Same features as set in InvoiceBuilder
37 false, // No unknown fields
40 "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9vdx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh".to_owned(),
41 InvoiceBuilder::new(Currency::Bitcoin)
42 .amount_milli_satoshis(250_000_000)
43 .duration_since_epoch(Duration::from_secs(1496314658))
44 .payment_secret(PaymentSecret([0x11; 32]))
45 .payment_hash(sha256::Hash::from_str(
46 "0001020304050607080900010203040506070809000102030405060708090102"
48 .description("1 cup coffee".to_owned())
49 .expiry_time(Duration::from_secs(60))
53 RecoverableSignature::from_compact(
54 &<Vec<u8>>::from_hex("e59e3ffbd3945e4334879158d31e89b076dff54f3fa7979ae79df2db9dcaf5896cbfe1a478b8d2307e92c88139464cb7e6ef26e414c4abe33337961ddc5e8ab1").unwrap(),
55 RecoveryId::from_i32(1).unwrap()
58 false, // Same features as set in InvoiceBuilder
59 false, // No unknown fields
62 "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpu9qrsgqhtjpauu9ur7fw2thcl4y9vfvh4m9wlfyz2gem29g5ghe2aak2pm3ps8fdhtceqsaagty2vph7utlgj48u0ged6a337aewvraedendscp573dxr".to_owned(),
63 InvoiceBuilder::new(Currency::Bitcoin)
64 .amount_milli_satoshis(250_000_000)
65 .duration_since_epoch(Duration::from_secs(1496314658))
66 .payment_secret(PaymentSecret([0x11; 32]))
67 .payment_hash(sha256::Hash::from_str(
68 "0001020304050607080900010203040506070809000102030405060708090102"
70 .description("ナンセンス 1杯".to_owned())
71 .expiry_time(Duration::from_secs(60))
75 RecoverableSignature::from_compact(
76 &<Vec<u8>>::from_hex("bae41ef385e0fc972977c7ea42b12cbd76577d2412919da8a8a22f9577b6507710c0e96dd78c821dea16453037f717f44aa7e3d196ebb18fbb97307dcb7336c3").unwrap(),
77 RecoveryId::from_i32(1).unwrap()
80 false, // Same features as set in InvoiceBuilder
81 false, // No unknown fields
84 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs9qrsgq7ea976txfraylvgzuxs8kgcw23ezlrszfnh8r6qtfpr6cxga50aj6txm9rxrydzd06dfeawfk6swupvz4erwnyutnjq7x39ymw6j38gp7ynn44".to_owned(),
85 InvoiceBuilder::new(Currency::Bitcoin)
86 .amount_milli_satoshis(2_000_000_000)
87 .duration_since_epoch(Duration::from_secs(1496314658))
88 .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"))
89 .payment_secret(PaymentSecret([0x11; 32]))
90 .payment_hash(sha256::Hash::from_str(
91 "0001020304050607080900010203040506070809000102030405060708090102"
96 RecoverableSignature::from_compact(
97 &<Vec<u8>>::from_hex("f67a5f696648fa4fb102e1a07b230e54722f8e024cee71e80b4847ac191da3fb2d2cdb28cc32344d7e9a9cf5c9b6a0ee0582ae46e9938b9c81e344a4dbb5289d").unwrap(),
98 RecoveryId::from_i32(1).unwrap()
101 false, // Same features as set in InvoiceBuilder
102 false, // No unknown fields
105 "lntb20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfpp3x9et2e20v6pu37c5d9vax37wxq72un989qrsgqdj545axuxtnfemtpwkc45hx9d2ft7x04mt8q7y6t0k2dge9e7h8kpy9p34ytyslj3yu569aalz2xdk8xkd7ltxqld94u8h2esmsmacgpghe9k8".to_owned(),
106 InvoiceBuilder::new(Currency::BitcoinTestnet)
107 .amount_milli_satoshis(2_000_000_000)
108 .duration_since_epoch(Duration::from_secs(1496314658))
109 .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"))
110 .payment_secret(PaymentSecret([0x11; 32]))
111 .payment_hash(sha256::Hash::from_str(
112 "0001020304050607080900010203040506070809000102030405060708090102"
114 .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()))
118 RecoverableSignature::from_compact(
119 &<Vec<u8>>::from_hex("6ca95a74dc32e69ced6175b15a5cc56a92bf19f5dace0f134b7d94d464b9f5cf6090a18d48b243f289394d17bdf89466d8e6b37df5981f696bc3dd5986e1bee1").unwrap(),
120 RecoveryId::from_i32(1).unwrap()
123 false, // Same features as set in InvoiceBuilder
124 false, // No unknown fields
127 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq9qrsgqdfjcdk6w3ak5pca9hwfwfh63zrrz06wwfya0ydlzpgzxkn5xagsqz7x9j4jwe7yj7vaf2k9lqsdk45kts2fd0fkr28am0u4w95tt2nsq76cqw0".to_owned(),
128 InvoiceBuilder::new(Currency::Bitcoin)
129 .amount_milli_satoshis(2_000_000_000)
130 .duration_since_epoch(Duration::from_secs(1496314658))
131 .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"))
132 .payment_secret(PaymentSecret([0x11; 32]))
133 .payment_hash(sha256::Hash::from_str(
134 "0001020304050607080900010203040506070809000102030405060708090102"
136 .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()))
137 .private_route(RouteHint(vec![RouteHintHop {
138 src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
139 "029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"
140 ).unwrap()).unwrap(),
141 short_channel_id: (66051 << 40) | (263430 << 16) | 1800,
142 fees: RoutingFees { base_msat: 1, proportional_millionths: 20 },
143 cltv_expiry_delta: 3,
144 htlc_maximum_msat: None, htlc_minimum_msat: None,
146 src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
147 "039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"
148 ).unwrap()).unwrap(),
149 short_channel_id: (197637 << 40) | (395016 << 16) | 2314,
150 fees: RoutingFees { base_msat: 2, proportional_millionths: 30 },
151 cltv_expiry_delta: 4,
152 htlc_maximum_msat: None, htlc_minimum_msat: None,
157 RecoverableSignature::from_compact(
158 &<Vec<u8>>::from_hex("6a6586db4e8f6d40e3a5bb92e4df5110c627e9ce493af237e20a046b4e86ea200178c59564ecf892f33a9558bf041b6ad2cb8292d7a6c351fbb7f2ae2d16b54e").unwrap(),
159 RecoveryId::from_i32(0).unwrap()
162 false, // Same features as set in InvoiceBuilder
163 false, // No unknown fields
166 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppj3a24vwu6r8ejrss3axul8rxldph2q7z99qrsgqz6qsgww34xlatfj6e3sngrwfy3ytkt29d2qttr8qz2mnedfqysuqypgqex4haa2h8fx3wnypranf3pdwyluftwe680jjcfp438u82xqphf75ym".to_owned(),
167 InvoiceBuilder::new(Currency::Bitcoin)
168 .amount_milli_satoshis(2_000_000_000)
169 .duration_since_epoch(Duration::from_secs(1496314658))
170 .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"))
171 .payment_secret(PaymentSecret([0x11; 32]))
172 .payment_hash(sha256::Hash::from_str(
173 "0001020304050607080900010203040506070809000102030405060708090102"
175 .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()))
179 RecoverableSignature::from_compact(
180 &<Vec<u8>>::from_hex("16810439d1a9bfd5a65acc61340dc92448bb2d456a80b58ce012b73cb5202438020500c9ab7ef5573a4d174c811f669885ae27f895bb3a3be52c243589f87518").unwrap(),
181 RecoveryId::from_i32(1).unwrap()
184 false, // Same features as set in InvoiceBuilder
185 false, // No unknown fields
188 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppqw508d6qejxtdg4y5r3zarvary0c5xw7k9qrsgqt29a0wturnys2hhxpner2e3plp6jyj8qx7548zr2z7ptgjjc7hljm98xhjym0dg52sdrvqamxdezkmqg4gdrvwwnf0kv2jdfnl4xatsqmrnsse".to_owned(),
189 InvoiceBuilder::new(Currency::Bitcoin)
190 .amount_milli_satoshis(2_000_000_000)
191 .duration_since_epoch(Duration::from_secs(1496314658))
192 .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"))
193 .payment_secret(PaymentSecret([0x11; 32]))
194 .payment_hash(sha256::Hash::from_str(
195 "0001020304050607080900010203040506070809000102030405060708090102"
197 .fallback(Fallback::SegWitProgram { version: WitnessVersion::V0,
198 program: vec![117, 30, 118, 232, 25, 145, 150, 212, 84, 148, 28, 69, 209, 179, 163, 35, 241, 67, 59, 214]
203 RecoverableSignature::from_compact(
204 &<Vec<u8>>::from_hex("5a8bd7b97c1cc9055ee60cf2356621f8752248e037a953886a1782b44a58f5ff2d94e6bc89b7b514541a3603bb33722b6c08aa1a3639d34becc549a99fea6eae").unwrap(),
205 RecoveryId::from_i32(0).unwrap()
208 false, // Same features as set in InvoiceBuilder
209 false, // No unknown fields
212 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq9vlvyj8cqvq6ggvpwd53jncp9nwc47xlrsnenq2zp70fq83qlgesn4u3uyf4tesfkkwwfg3qs54qe426hp3tz7z6sweqdjg05axsrjqp9yrrwc".to_owned(),
213 InvoiceBuilder::new(Currency::Bitcoin)
214 .amount_milli_satoshis(2_000_000_000)
215 .duration_since_epoch(Duration::from_secs(1496314658))
216 .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"))
217 .payment_secret(PaymentSecret([0x11; 32]))
218 .payment_hash(sha256::Hash::from_str(
219 "0001020304050607080900010203040506070809000102030405060708090102"
221 .fallback(Fallback::SegWitProgram { version: WitnessVersion::V0,
222 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 RecoverableSignature::from_compact(
228 &<Vec<u8>>::from_hex("2b3ec248f80301a421817369194f012cdd8af8df1c279981420f9e901e20fa3309d791e11355e609b59ce4a220852a0cd55ab862b1785a83b206c90fa74d01c8").unwrap(),
229 RecoveryId::from_i32(1).unwrap()
232 false, // Same features as set in InvoiceBuilder
233 false, // No unknown fields
236 "lnbc9678785340p1pwmna7lpp5gc3xfm08u9qy06djf8dfflhugl6p7lgza6dsjxq454gxhj9t7a0sd8dgfkx7cmtwd68yetpd5s9xar0wfjn5gpc8qhrsdfq24f5ggrxdaezqsnvda3kkum5wfjkzmfqf3jkgem9wgsyuctwdus9xgrcyqcjcgpzgfskx6eqf9hzqnteypzxz7fzypfhg6trddjhygrcyqezcgpzfysywmm5ypxxjemgw3hxjmn8yptk7untd9hxwg3q2d6xjcmtv4ezq7pqxgsxzmnyyqcjqmt0wfjjq6t5v4khxsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsxqyjw5qcqp2rzjq0gxwkzc8w6323m55m4jyxcjwmy7stt9hwkwe2qxmy8zpsgg7jcuwz87fcqqeuqqqyqqqqlgqqqqn3qq9q9qrsgqrvgkpnmps664wgkp43l22qsgdw4ve24aca4nymnxddlnp8vh9v2sdxlu5ywdxefsfvm0fq3sesf08uf6q9a2ke0hc9j6z6wlxg5z5kqpu2v9wz".to_owned(),
237 InvoiceBuilder::new(Currency::Bitcoin)
238 .amount_milli_satoshis(967878534)
239 .duration_since_epoch(Duration::from_secs(1572468703))
240 .payment_secret(PaymentSecret([0x11; 32]))
241 .payment_hash(sha256::Hash::from_str(
242 "462264ede7e14047e9b249da94fefc47f41f7d02ee9b091815a5506bc8abf75f"
244 .expiry_time(Duration::from_secs(604800))
245 .min_final_cltv_expiry_delta(10)
246 .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())
247 .private_route(RouteHint(vec![RouteHintHop {
248 src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
249 "03d06758583bb5154774a6eb221b1276c9e82d65bbaceca806d90e20c108f4b1c7"
250 ).unwrap()).unwrap(),
251 short_channel_id: (589390 << 40) | (3312 << 16) | 1,
252 fees: RoutingFees { base_msat: 1000, proportional_millionths: 2500 },
253 cltv_expiry_delta: 40,
254 htlc_maximum_msat: None, htlc_minimum_msat: None,
259 RecoverableSignature::from_compact(
260 &<Vec<u8>>::from_hex("1b1160cf6186b55722c1ac7ea502086baaccaabdc76b326e666b7f309d972b15069bfca11cd365304b36f48230cc12f3f13a017aab65f7c165a169df32282a58").unwrap(),
261 RecoveryId::from_i32(1).unwrap()
264 false, // Same features as set in InvoiceBuilder
265 false, // No unknown fields
268 "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2a25dxl5hrntdtn6zvydt7d66hyzsyhqs4wdynavys42xgl6sgx9c4g7me86a27t07mdtfry458rtjr0v92cnmswpsjscgt2vcse3sgpz3uapa".to_owned(),
269 InvoiceBuilder::new(Currency::Bitcoin)
270 .amount_milli_satoshis(2_500_000_000)
271 .duration_since_epoch(Duration::from_secs(1496314658))
272 .payment_secret(PaymentSecret([0x11; 32]))
273 .payment_hash(sha256::Hash::from_str(
274 "0001020304050607080900010203040506070809000102030405060708090102"
276 .description("coffee beans".to_owned())
280 RecoverableSignature::from_compact(
281 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
282 RecoveryId::from_i32(1).unwrap()
285 true, // Different features than set in InvoiceBuilder
286 false, // No unknown fields
289 "LNBC25M1PVJLUEZPP5QQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQYPQDQ5VDHKVEN9V5SXYETPDEESSP5ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYGS9Q5SQQQQQQQQQQQQQQQQSGQ2A25DXL5HRNTDTN6ZVYDT7D66HYZSYHQS4WDYNAVYS42XGL6SGX9C4G7ME86A27T07MDTFRY458RTJR0V92CNMSWPSJSCGT2VCSE3SGPZ3UAPA".to_owned(),
290 InvoiceBuilder::new(Currency::Bitcoin)
291 .amount_milli_satoshis(2_500_000_000)
292 .duration_since_epoch(Duration::from_secs(1496314658))
293 .payment_secret(PaymentSecret([0x11; 32]))
294 .payment_hash(sha256::Hash::from_str(
295 "0001020304050607080900010203040506070809000102030405060708090102"
297 .description("coffee beans".to_owned())
301 RecoverableSignature::from_compact(
302 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
303 RecoveryId::from_i32(1).unwrap()
306 true, // Different features than set in InvoiceBuilder
307 false, // No unknown fields
310 "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2qrqqqfppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhpnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqspnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnp5qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnpkqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqz599y53s3ujmcfjp5xrdap68qxymkqphwsexhmhr8wdz5usdzkzrse33chw6dlp3jhuhge9ley7j2ayx36kawe7kmgg8sv5ugdyusdcqzn8z9x".to_owned(),
311 InvoiceBuilder::new(Currency::Bitcoin)
312 .amount_milli_satoshis(2_500_000_000)
313 .duration_since_epoch(Duration::from_secs(1496314658))
314 .payment_secret(PaymentSecret([0x11; 32]))
315 .payment_hash(sha256::Hash::from_str(
316 "0001020304050607080900010203040506070809000102030405060708090102"
318 .description("coffee beans".to_owned())
322 RecoverableSignature::from_compact(
323 &<Vec<u8>>::from_hex("150a5252308f25bc2641a186de87470189bb003774326beee33b9a2a720d1584386631c5dda6fc3195f97464bfc93d2574868eadd767d6da1078329c4349c837").unwrap(),
324 RecoveryId::from_i32(0).unwrap()
327 true, // Different features than set in InvoiceBuilder
328 true, // Some unknown fields
330 ( // Older version of the payment metadata test with a payment_pubkey set
331 "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqnp4q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66sp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgqy9gw6ymamd20jumvdgpfphkhp8fzhhdhycw36egcmla5vlrtrmhs9t7psfy3hkkdqzm9eq64fjg558znccds5nhsfmxveha5xe0dykgpspdha0".to_owned(),
332 InvoiceBuilder::new(Currency::Bitcoin)
333 .amount_milli_satoshis(1_000_000_000)
334 .duration_since_epoch(Duration::from_secs(1496314658))
335 .payment_hash(sha256::Hash::from_str(
336 "0001020304050607080900010203040506070809000102030405060708090102"
338 .description("payment metadata inside".to_owned())
339 .payment_metadata(<Vec<u8>>::from_hex("01fafaf0").unwrap())
340 .require_payment_metadata()
341 .payee_pub_key(PublicKey::from_slice(&<Vec<u8>>::from_hex(
342 "03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad"
343 ).unwrap()).unwrap())
344 .payment_secret(PaymentSecret([0x11; 32]))
348 RecoverableSignature::from_compact(
349 &<Vec<u8>>::from_hex("2150ed137ddb54f9736c6a0290ded709d22bddb7261d1d6518dffb467c6b1eef02afc182491bdacd00b65c83554c914a1c53c61b0a4ef04eccccdfb4365ed259").unwrap(),
350 RecoveryId::from_i32(1).unwrap()
353 false, // Different features than set in InvoiceBuilder
354 true, // Some unknown fields
357 "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgq7hf8he7ecf7n4ffphs6awl9t6676rrclv9ckg3d3ncn7fct63p6s365duk5wrk202cfy3aj5xnnp5gs3vrdvruverwwq7yzhkf5a3xqpd05wjc".to_owned(),
358 InvoiceBuilder::new(Currency::Bitcoin)
359 .amount_milli_satoshis(1_000_000_000)
360 .duration_since_epoch(Duration::from_secs(1496314658))
361 .payment_hash(sha256::Hash::from_str(
362 "0001020304050607080900010203040506070809000102030405060708090102"
364 .description("payment metadata inside".to_owned())
365 .payment_metadata(<Vec<u8>>::from_hex("01fafaf0").unwrap())
366 .require_payment_metadata()
367 .payment_secret(PaymentSecret([0x11; 32]))
371 RecoverableSignature::from_compact(
372 &<Vec<u8>>::from_hex("f5d27be7d9c27d3aa521bc35d77cabd6bda18f1f61716445b19e27e4e17a887508ea8de5a8e1d94f561248f65434e61a221160dac1f1991b9c0f1057b269d898").unwrap(),
373 RecoveryId::from_i32(1).unwrap()
376 false, // Different features than set in InvoiceBuilder
377 true, // Some unknown fields
384 fn invoice_deserialize() {
385 for (serialized, deserialized, ignore_feature_diff, ignore_unknown_fields) in get_test_tuples() {
386 eprintln!("Testing invoice {}...", serialized);
387 let parsed = serialized.parse::<SignedRawBolt11Invoice>().unwrap();
389 let (parsed_invoice, _, parsed_sig) = parsed.into_parts();
390 let (deserialized_invoice, _, deserialized_sig) = deserialized.into_parts();
392 assert_eq!(deserialized_sig, parsed_sig);
393 assert_eq!(deserialized_invoice.hrp, parsed_invoice.hrp);
394 assert_eq!(deserialized_invoice.data.timestamp, parsed_invoice.data.timestamp);
396 let mut deserialized_hunks: HashSet<_> = deserialized_invoice.data.tagged_fields.iter().collect();
397 let mut parsed_hunks: HashSet<_> = parsed_invoice.data.tagged_fields.iter().collect();
398 if ignore_feature_diff {
399 deserialized_hunks.retain(|h|
400 if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true });
401 parsed_hunks.retain(|h|
402 if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true });
404 if ignore_unknown_fields {
405 parsed_hunks.retain(|h|
406 if let RawTaggedField::UnknownSemantics(_) = h { false } else { true });
408 assert_eq!(deserialized_hunks, parsed_hunks);
410 Bolt11Invoice::from_signed(serialized.parse::<SignedRawBolt11Invoice>().unwrap()).unwrap();
415 fn test_bolt_invalid_invoices() {
416 // Tests the BOLT 11 invalid invoice test vectors
417 assert_eq!(Bolt11Invoice::from_str(
418 "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqqsgqtqyx5vggfcsll4wu246hz02kp85x4katwsk9639we5n5yngc3yhqkm35jnjw4len8vrnqnf5ejh0mzj9n3vz2px97evektfm2l6wqccp3y7372"
419 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::InvalidFeatures)));
420 assert_eq!(Bolt11Invoice::from_str(
421 "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt"
422 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::InvalidChecksum))));
423 assert_eq!(Bolt11Invoice::from_str(
424 "pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
425 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MissingSeparator))));
426 assert_eq!(Bolt11Invoice::from_str(
427 "LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
428 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MixedCase))));
429 assert_eq!(Bolt11Invoice::from_str(
430 "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqwgt7mcn5yqw3yx0w94pswkpq6j9uh6xfqqqtsk4tnarugeektd4hg5975x9am52rz4qskukxdmjemg92vvqz8nvmsye63r5ykel43pgz7zq0g2"
431 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::InvalidSignature)));
432 assert_eq!(Bolt11Invoice::from_str(
433 "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh"
434 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::TooShortDataPart)));
435 assert_eq!(Bolt11Invoice::from_str(
436 "lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqrrzc4cvfue4zp3hggxp47ag7xnrlr8vgcmkjxk3j5jqethnumgkpqp23z9jclu3v0a7e0aruz366e9wqdykw6dxhdzcjjhldxq0w6wgqcnu43j"
437 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::UnknownSiPrefix)));
438 assert_eq!(Bolt11Invoice::from_str(
439 "lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgq0lzc236j96a95uv0m3umg28gclm5lqxtqqwk32uuk4k6673k6n5kfvx3d2h8s295fad45fdhmusm8sjudfhlf6dcsxmfvkeywmjdkxcp99202x"
440 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::ImpreciseAmount)));