2 extern crate lightning;
3 extern crate lightning_invoice;
4 extern crate secp256k1;
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;
18 fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> {
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"
28 .description("Please consider supporting this project".to_owned())
32 RecoverableSignature::from_compact(
33 &<Vec<u8>>::from_hex("8d3ce9e28357337f62da0162d9454df827f83cfe499aeb1c1db349d4d81127425e434ca29929406c23bba1ae8ac6ca32880b38d4bf6ff874024cac34ba9625f1").unwrap(),
34 RecoveryId::from_i32(1).unwrap()
37 false, // Same features as set in InvoiceBuilder
38 false, // No unknown fields
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"
49 .description("1 cup coffee".to_owned())
50 .expiry_time(Duration::from_secs(60))
54 RecoverableSignature::from_compact(
55 &<Vec<u8>>::from_hex("e59e3ffbd3945e4334879158d31e89b076dff54f3fa7979ae79df2db9dcaf5896cbfe1a478b8d2307e92c88139464cb7e6ef26e414c4abe33337961ddc5e8ab1").unwrap(),
56 RecoveryId::from_i32(1).unwrap()
59 false, // Same features as set in InvoiceBuilder
60 false, // No unknown fields
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"
71 .description("ナンセンス 1杯".to_owned())
72 .expiry_time(Duration::from_secs(60))
76 RecoverableSignature::from_compact(
77 &<Vec<u8>>::from_hex("bae41ef385e0fc972977c7ea42b12cbd76577d2412919da8a8a22f9577b6507710c0e96dd78c821dea16453037f717f44aa7e3d196ebb18fbb97307dcb7336c3").unwrap(),
78 RecoveryId::from_i32(1).unwrap()
81 false, // Same features as set in InvoiceBuilder
82 false, // No unknown fields
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"
97 RecoverableSignature::from_compact(
98 &<Vec<u8>>::from_hex("f67a5f696648fa4fb102e1a07b230e54722f8e024cee71e80b4847ac191da3fb2d2cdb28cc32344d7e9a9cf5c9b6a0ee0582ae46e9938b9c81e344a4dbb5289d").unwrap(),
99 RecoveryId::from_i32(1).unwrap()
102 false, // Same features as set in InvoiceBuilder
103 false, // No unknown fields
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"
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()))
119 RecoverableSignature::from_compact(
120 &<Vec<u8>>::from_hex("6ca95a74dc32e69ced6175b15a5cc56a92bf19f5dace0f134b7d94d464b9f5cf6090a18d48b243f289394d17bdf89466d8e6b37df5981f696bc3dd5986e1bee1").unwrap(),
121 RecoveryId::from_i32(1).unwrap()
124 false, // Same features as set in InvoiceBuilder
125 false, // No unknown fields
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"
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,
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,
158 RecoverableSignature::from_compact(
159 &<Vec<u8>>::from_hex("6a6586db4e8f6d40e3a5bb92e4df5110c627e9ce493af237e20a046b4e86ea200178c59564ecf892f33a9558bf041b6ad2cb8292d7a6c351fbb7f2ae2d16b54e").unwrap(),
160 RecoveryId::from_i32(0).unwrap()
163 false, // Same features as set in InvoiceBuilder
164 false, // No unknown fields
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"
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()))
180 RecoverableSignature::from_compact(
181 &<Vec<u8>>::from_hex("16810439d1a9bfd5a65acc61340dc92448bb2d456a80b58ce012b73cb5202438020500c9ab7ef5573a4d174c811f669885ae27f895bb3a3be52c243589f87518").unwrap(),
182 RecoveryId::from_i32(1).unwrap()
185 false, // Same features as set in InvoiceBuilder
186 false, // No unknown fields
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"
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]
204 RecoverableSignature::from_compact(
205 &<Vec<u8>>::from_hex("5a8bd7b97c1cc9055ee60cf2356621f8752248e037a953886a1782b44a58f5ff2d94e6bc89b7b514541a3603bb33722b6c08aa1a3639d34becc549a99fea6eae").unwrap(),
206 RecoveryId::from_i32(0).unwrap()
209 false, // Same features as set in InvoiceBuilder
210 false, // No unknown fields
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"
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]
228 RecoverableSignature::from_compact(
229 &<Vec<u8>>::from_hex("2b3ec248f80301a421817369194f012cdd8af8df1c279981420f9e901e20fa3309d791e11355e609b59ce4a220852a0cd55ab862b1785a83b206c90fa74d01c8").unwrap(),
230 RecoveryId::from_i32(1).unwrap()
233 false, // Same features as set in InvoiceBuilder
234 false, // No unknown fields
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"
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,
260 RecoverableSignature::from_compact(
261 &<Vec<u8>>::from_hex("1b1160cf6186b55722c1ac7ea502086baaccaabdc76b326e666b7f309d972b15069bfca11cd365304b36f48230cc12f3f13a017aab65f7c165a169df32282a58").unwrap(),
262 RecoveryId::from_i32(1).unwrap()
265 false, // Same features as set in InvoiceBuilder
266 false, // No unknown fields
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"
277 .description("coffee beans".to_owned())
281 RecoverableSignature::from_compact(
282 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
283 RecoveryId::from_i32(1).unwrap()
286 true, // Different features than set in InvoiceBuilder
287 false, // No unknown fields
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"
298 .description("coffee beans".to_owned())
302 RecoverableSignature::from_compact(
303 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
304 RecoveryId::from_i32(1).unwrap()
307 true, // Different features than set in InvoiceBuilder
308 false, // No unknown fields
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"
319 .description("coffee beans".to_owned())
323 RecoverableSignature::from_compact(
324 &<Vec<u8>>::from_hex("150a5252308f25bc2641a186de87470189bb003774326beee33b9a2a720d1584386631c5dda6fc3195f97464bfc93d2574868eadd767d6da1078329c4349c837").unwrap(),
325 RecoveryId::from_i32(0).unwrap()
328 true, // Different features than set in InvoiceBuilder
329 true, // Some unknown fields
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"
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]))
349 RecoverableSignature::from_compact(
350 &<Vec<u8>>::from_hex("2150ed137ddb54f9736c6a0290ded709d22bddb7261d1d6518dffb467c6b1eef02afc182491bdacd00b65c83554c914a1c53c61b0a4ef04eccccdfb4365ed259").unwrap(),
351 RecoveryId::from_i32(1).unwrap()
354 false, // Different features than set in InvoiceBuilder
355 true, // Some unknown fields
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"
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]))
372 RecoverableSignature::from_compact(
373 &<Vec<u8>>::from_hex("f5d27be7d9c27d3aa521bc35d77cabd6bda18f1f61716445b19e27e4e17a887508ea8de5a8e1d94f561248f65434e61a221160dac1f1991b9c0f1057b269d898").unwrap(),
374 RecoveryId::from_i32(1).unwrap()
377 false, // Different features than set in InvoiceBuilder
378 true, // Some unknown fields
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();
390 let (parsed_invoice, _, parsed_sig) = parsed.into_parts();
391 let (deserialized_invoice, _, deserialized_sig) = deserialized.into_parts();
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);
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 });
405 if ignore_unknown_fields {
406 parsed_hunks.retain(|h|
407 if let RawTaggedField::UnknownSemantics(_) = h { false } else { true });
409 assert_eq!(deserialized_hunks, parsed_hunks);
411 Bolt11Invoice::from_signed(serialized.parse::<SignedRawBolt11Invoice>().unwrap()).unwrap();
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)));