2 extern crate bitcoin_hashes;
3 extern crate lightning;
4 extern crate lightning_invoice;
5 extern crate secp256k1;
8 use bitcoin::address::WitnessVersion;
9 use bitcoin::{PubkeyHash, ScriptHash};
10 use bitcoin::hashes::hex::FromHex;
11 use bitcoin_hashes::{sha256, Hash};
12 use lightning::ln::PaymentSecret;
13 use lightning::routing::gossip::RoutingFees;
14 use lightning::routing::router::{RouteHint, RouteHintHop};
15 use lightning_invoice::*;
16 use secp256k1::PublicKey;
17 use secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
18 use std::collections::HashSet;
19 use std::time::Duration;
20 use std::str::FromStr;
22 fn get_test_tuples() -> Vec<(String, SignedRawBolt11Invoice, bool, bool)> {
25 "lnbc1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq9qrsgq357wnc5r2ueh7ck6q93dj32dlqnls087fxdwk8qakdyafkq3yap9us6v52vjjsrvywa6rt52cm9r9zqt8r2t7mlcwspyetp5h2tztugp9lfyql".to_owned(),
26 InvoiceBuilder::new(Currency::Bitcoin)
27 .duration_since_epoch(Duration::from_secs(1496314658))
28 .payment_secret(PaymentSecret([0x11; 32]))
29 .payment_hash(sha256::Hash::from_str(
30 "0001020304050607080900010203040506070809000102030405060708090102"
32 .description("Please consider supporting this project".to_owned())
36 RecoverableSignature::from_compact(
37 &<Vec<u8>>::from_hex("8d3ce9e28357337f62da0162d9454df827f83cfe499aeb1c1db349d4d81127425e434ca29929406c23bba1ae8ac6ca32880b38d4bf6ff874024cac34ba9625f1").unwrap(),
38 RecoveryId::from_i32(1).unwrap()
41 false, // Same features as set in InvoiceBuilder
42 false, // No unknown fields
45 "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpu9qrsgquk0rl77nj30yxdy8j9vdx85fkpmdla2087ne0xh8nhedh8w27kyke0lp53ut353s06fv3qfegext0eh0ymjpf39tuven09sam30g4vgpfna3rh".to_owned(),
46 InvoiceBuilder::new(Currency::Bitcoin)
47 .amount_milli_satoshis(250_000_000)
48 .duration_since_epoch(Duration::from_secs(1496314658))
49 .payment_secret(PaymentSecret([0x11; 32]))
50 .payment_hash(sha256::Hash::from_str(
51 "0001020304050607080900010203040506070809000102030405060708090102"
53 .description("1 cup coffee".to_owned())
54 .expiry_time(Duration::from_secs(60))
58 RecoverableSignature::from_compact(
59 &<Vec<u8>>::from_hex("e59e3ffbd3945e4334879158d31e89b076dff54f3fa7979ae79df2db9dcaf5896cbfe1a478b8d2307e92c88139464cb7e6ef26e414c4abe33337961ddc5e8ab1").unwrap(),
60 RecoveryId::from_i32(1).unwrap()
63 false, // Same features as set in InvoiceBuilder
64 false, // No unknown fields
67 "lnbc2500u1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpu9qrsgqhtjpauu9ur7fw2thcl4y9vfvh4m9wlfyz2gem29g5ghe2aak2pm3ps8fdhtceqsaagty2vph7utlgj48u0ged6a337aewvraedendscp573dxr".to_owned(),
68 InvoiceBuilder::new(Currency::Bitcoin)
69 .amount_milli_satoshis(250_000_000)
70 .duration_since_epoch(Duration::from_secs(1496314658))
71 .payment_secret(PaymentSecret([0x11; 32]))
72 .payment_hash(sha256::Hash::from_str(
73 "0001020304050607080900010203040506070809000102030405060708090102"
75 .description("ナンセンス 1杯".to_owned())
76 .expiry_time(Duration::from_secs(60))
80 RecoverableSignature::from_compact(
81 &<Vec<u8>>::from_hex("bae41ef385e0fc972977c7ea42b12cbd76577d2412919da8a8a22f9577b6507710c0e96dd78c821dea16453037f717f44aa7e3d196ebb18fbb97307dcb7336c3").unwrap(),
82 RecoveryId::from_i32(1).unwrap()
85 false, // Same features as set in InvoiceBuilder
86 false, // No unknown fields
89 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqs9qrsgq7ea976txfraylvgzuxs8kgcw23ezlrszfnh8r6qtfpr6cxga50aj6txm9rxrydzd06dfeawfk6swupvz4erwnyutnjq7x39ymw6j38gp7ynn44".to_owned(),
90 InvoiceBuilder::new(Currency::Bitcoin)
91 .amount_milli_satoshis(2_000_000_000)
92 .duration_since_epoch(Duration::from_secs(1496314658))
93 .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"))
94 .payment_secret(PaymentSecret([0x11; 32]))
95 .payment_hash(sha256::Hash::from_str(
96 "0001020304050607080900010203040506070809000102030405060708090102"
101 RecoverableSignature::from_compact(
102 &<Vec<u8>>::from_hex("f67a5f696648fa4fb102e1a07b230e54722f8e024cee71e80b4847ac191da3fb2d2cdb28cc32344d7e9a9cf5c9b6a0ee0582ae46e9938b9c81e344a4dbb5289d").unwrap(),
103 RecoveryId::from_i32(1).unwrap()
106 false, // Same features as set in InvoiceBuilder
107 false, // No unknown fields
110 "lntb20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfpp3x9et2e20v6pu37c5d9vax37wxq72un989qrsgqdj545axuxtnfemtpwkc45hx9d2ft7x04mt8q7y6t0k2dge9e7h8kpy9p34ytyslj3yu569aalz2xdk8xkd7ltxqld94u8h2esmsmacgpghe9k8".to_owned(),
111 InvoiceBuilder::new(Currency::BitcoinTestnet)
112 .amount_milli_satoshis(2_000_000_000)
113 .duration_since_epoch(Duration::from_secs(1496314658))
114 .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"))
115 .payment_secret(PaymentSecret([0x11; 32]))
116 .payment_hash(sha256::Hash::from_str(
117 "0001020304050607080900010203040506070809000102030405060708090102"
119 .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()))
123 RecoverableSignature::from_compact(
124 &<Vec<u8>>::from_hex("6ca95a74dc32e69ced6175b15a5cc56a92bf19f5dace0f134b7d94d464b9f5cf6090a18d48b243f289394d17bdf89466d8e6b37df5981f696bc3dd5986e1bee1").unwrap(),
125 RecoveryId::from_i32(1).unwrap()
128 false, // Same features as set in InvoiceBuilder
129 false, // No unknown fields
132 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq9qrsgqdfjcdk6w3ak5pca9hwfwfh63zrrz06wwfya0ydlzpgzxkn5xagsqz7x9j4jwe7yj7vaf2k9lqsdk45kts2fd0fkr28am0u4w95tt2nsq76cqw0".to_owned(),
133 InvoiceBuilder::new(Currency::Bitcoin)
134 .amount_milli_satoshis(2_000_000_000)
135 .duration_since_epoch(Duration::from_secs(1496314658))
136 .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"))
137 .payment_secret(PaymentSecret([0x11; 32]))
138 .payment_hash(sha256::Hash::from_str(
139 "0001020304050607080900010203040506070809000102030405060708090102"
141 .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()))
142 .private_route(RouteHint(vec![RouteHintHop {
143 src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
144 "029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"
145 ).unwrap()).unwrap(),
146 short_channel_id: (66051 << 40) | (263430 << 16) | 1800,
147 fees: RoutingFees { base_msat: 1, proportional_millionths: 20 },
148 cltv_expiry_delta: 3,
149 htlc_maximum_msat: None, htlc_minimum_msat: None,
151 src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
152 "039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"
153 ).unwrap()).unwrap(),
154 short_channel_id: (197637 << 40) | (395016 << 16) | 2314,
155 fees: RoutingFees { base_msat: 2, proportional_millionths: 30 },
156 cltv_expiry_delta: 4,
157 htlc_maximum_msat: None, htlc_minimum_msat: None,
162 RecoverableSignature::from_compact(
163 &<Vec<u8>>::from_hex("6a6586db4e8f6d40e3a5bb92e4df5110c627e9ce493af237e20a046b4e86ea200178c59564ecf892f33a9558bf041b6ad2cb8292d7a6c351fbb7f2ae2d16b54e").unwrap(),
164 RecoveryId::from_i32(0).unwrap()
167 false, // Same features as set in InvoiceBuilder
168 false, // No unknown fields
171 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppj3a24vwu6r8ejrss3axul8rxldph2q7z99qrsgqz6qsgww34xlatfj6e3sngrwfy3ytkt29d2qttr8qz2mnedfqysuqypgqex4haa2h8fx3wnypranf3pdwyluftwe680jjcfp438u82xqphf75ym".to_owned(),
172 InvoiceBuilder::new(Currency::Bitcoin)
173 .amount_milli_satoshis(2_000_000_000)
174 .duration_since_epoch(Duration::from_secs(1496314658))
175 .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"))
176 .payment_secret(PaymentSecret([0x11; 32]))
177 .payment_hash(sha256::Hash::from_str(
178 "0001020304050607080900010203040506070809000102030405060708090102"
180 .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()))
184 RecoverableSignature::from_compact(
185 &<Vec<u8>>::from_hex("16810439d1a9bfd5a65acc61340dc92448bb2d456a80b58ce012b73cb5202438020500c9ab7ef5573a4d174c811f669885ae27f895bb3a3be52c243589f87518").unwrap(),
186 RecoveryId::from_i32(1).unwrap()
189 false, // Same features as set in InvoiceBuilder
190 false, // No unknown fields
193 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfppqw508d6qejxtdg4y5r3zarvary0c5xw7k9qrsgqt29a0wturnys2hhxpner2e3plp6jyj8qx7548zr2z7ptgjjc7hljm98xhjym0dg52sdrvqamxdezkmqg4gdrvwwnf0kv2jdfnl4xatsqmrnsse".to_owned(),
194 InvoiceBuilder::new(Currency::Bitcoin)
195 .amount_milli_satoshis(2_000_000_000)
196 .duration_since_epoch(Duration::from_secs(1496314658))
197 .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"))
198 .payment_secret(PaymentSecret([0x11; 32]))
199 .payment_hash(sha256::Hash::from_str(
200 "0001020304050607080900010203040506070809000102030405060708090102"
202 .fallback(Fallback::SegWitProgram { version: WitnessVersion::V0,
203 program: vec![117, 30, 118, 232, 25, 145, 150, 212, 84, 148, 28, 69, 209, 179, 163, 35, 241, 67, 59, 214]
208 RecoverableSignature::from_compact(
209 &<Vec<u8>>::from_hex("5a8bd7b97c1cc9055ee60cf2356621f8752248e037a953886a1782b44a58f5ff2d94e6bc89b7b514541a3603bb33722b6c08aa1a3639d34becc549a99fea6eae").unwrap(),
210 RecoveryId::from_i32(0).unwrap()
213 false, // Same features as set in InvoiceBuilder
214 false, // No unknown fields
217 "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygshp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqfp4qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q9qrsgq9vlvyj8cqvq6ggvpwd53jncp9nwc47xlrsnenq2zp70fq83qlgesn4u3uyf4tesfkkwwfg3qs54qe426hp3tz7z6sweqdjg05axsrjqp9yrrwc".to_owned(),
218 InvoiceBuilder::new(Currency::Bitcoin)
219 .amount_milli_satoshis(2_000_000_000)
220 .duration_since_epoch(Duration::from_secs(1496314658))
221 .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"))
222 .payment_secret(PaymentSecret([0x11; 32]))
223 .payment_hash(sha256::Hash::from_str(
224 "0001020304050607080900010203040506070809000102030405060708090102"
226 .fallback(Fallback::SegWitProgram { version: WitnessVersion::V0,
227 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]
232 RecoverableSignature::from_compact(
233 &<Vec<u8>>::from_hex("2b3ec248f80301a421817369194f012cdd8af8df1c279981420f9e901e20fa3309d791e11355e609b59ce4a220852a0cd55ab862b1785a83b206c90fa74d01c8").unwrap(),
234 RecoveryId::from_i32(1).unwrap()
237 false, // Same features as set in InvoiceBuilder
238 false, // No unknown fields
241 "lnbc9678785340p1pwmna7lpp5gc3xfm08u9qy06djf8dfflhugl6p7lgza6dsjxq454gxhj9t7a0sd8dgfkx7cmtwd68yetpd5s9xar0wfjn5gpc8qhrsdfq24f5ggrxdaezqsnvda3kkum5wfjkzmfqf3jkgem9wgsyuctwdus9xgrcyqcjcgpzgfskx6eqf9hzqnteypzxz7fzypfhg6trddjhygrcyqezcgpzfysywmm5ypxxjemgw3hxjmn8yptk7untd9hxwg3q2d6xjcmtv4ezq7pqxgsxzmnyyqcjqmt0wfjjq6t5v4khxsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsxqyjw5qcqp2rzjq0gxwkzc8w6323m55m4jyxcjwmy7stt9hwkwe2qxmy8zpsgg7jcuwz87fcqqeuqqqyqqqqlgqqqqn3qq9q9qrsgqrvgkpnmps664wgkp43l22qsgdw4ve24aca4nymnxddlnp8vh9v2sdxlu5ywdxefsfvm0fq3sesf08uf6q9a2ke0hc9j6z6wlxg5z5kqpu2v9wz".to_owned(),
242 InvoiceBuilder::new(Currency::Bitcoin)
243 .amount_milli_satoshis(967878534)
244 .duration_since_epoch(Duration::from_secs(1572468703))
245 .payment_secret(PaymentSecret([0x11; 32]))
246 .payment_hash(sha256::Hash::from_str(
247 "462264ede7e14047e9b249da94fefc47f41f7d02ee9b091815a5506bc8abf75f"
249 .expiry_time(Duration::from_secs(604800))
250 .min_final_cltv_expiry_delta(10)
251 .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())
252 .private_route(RouteHint(vec![RouteHintHop {
253 src_node_id: PublicKey::from_slice(&<Vec<u8>>::from_hex(
254 "03d06758583bb5154774a6eb221b1276c9e82d65bbaceca806d90e20c108f4b1c7"
255 ).unwrap()).unwrap(),
256 short_channel_id: (589390 << 40) | (3312 << 16) | 1,
257 fees: RoutingFees { base_msat: 1000, proportional_millionths: 2500 },
258 cltv_expiry_delta: 40,
259 htlc_maximum_msat: None, htlc_minimum_msat: None,
264 RecoverableSignature::from_compact(
265 &<Vec<u8>>::from_hex("1b1160cf6186b55722c1ac7ea502086baaccaabdc76b326e666b7f309d972b15069bfca11cd365304b36f48230cc12f3f13a017aab65f7c165a169df32282a58").unwrap(),
266 RecoveryId::from_i32(1).unwrap()
269 false, // Same features as set in InvoiceBuilder
270 false, // No unknown fields
273 "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2a25dxl5hrntdtn6zvydt7d66hyzsyhqs4wdynavys42xgl6sgx9c4g7me86a27t07mdtfry458rtjr0v92cnmswpsjscgt2vcse3sgpz3uapa".to_owned(),
274 InvoiceBuilder::new(Currency::Bitcoin)
275 .amount_milli_satoshis(2_500_000_000)
276 .duration_since_epoch(Duration::from_secs(1496314658))
277 .payment_secret(PaymentSecret([0x11; 32]))
278 .payment_hash(sha256::Hash::from_str(
279 "0001020304050607080900010203040506070809000102030405060708090102"
281 .description("coffee beans".to_owned())
285 RecoverableSignature::from_compact(
286 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
287 RecoveryId::from_i32(1).unwrap()
290 true, // Different features than set in InvoiceBuilder
291 false, // No unknown fields
294 "LNBC25M1PVJLUEZPP5QQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQQQSYQCYQ5RQWZQFQYPQDQ5VDHKVEN9V5SXYETPDEESSP5ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYG3ZYGS9Q5SQQQQQQQQQQQQQQQQSGQ2A25DXL5HRNTDTN6ZVYDT7D66HYZSYHQS4WDYNAVYS42XGL6SGX9C4G7ME86A27T07MDTFRY458RTJR0V92CNMSWPSJSCGT2VCSE3SGPZ3UAPA".to_owned(),
295 InvoiceBuilder::new(Currency::Bitcoin)
296 .amount_milli_satoshis(2_500_000_000)
297 .duration_since_epoch(Duration::from_secs(1496314658))
298 .payment_secret(PaymentSecret([0x11; 32]))
299 .payment_hash(sha256::Hash::from_str(
300 "0001020304050607080900010203040506070809000102030405060708090102"
302 .description("coffee beans".to_owned())
306 RecoverableSignature::from_compact(
307 &<Vec<u8>>::from_hex("5755469bf4b8e6b6ae7a1308d5f9bad5c82812e0855cd24fac242aa323fa820c5c551ede4faeabcb7fb6d5a464ad0e35c86f615589ee0e0c250c216a662198c1").unwrap(),
308 RecoveryId::from_i32(1).unwrap()
311 true, // Different features than set in InvoiceBuilder
312 false, // No unknown fields
315 "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqqsgq2qrqqqfppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqppnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhpnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqhp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqspnqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsp4qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnp5qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnpkqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqz599y53s3ujmcfjp5xrdap68qxymkqphwsexhmhr8wdz5usdzkzrse33chw6dlp3jhuhge9ley7j2ayx36kawe7kmgg8sv5ugdyusdcqzn8z9x".to_owned(),
316 InvoiceBuilder::new(Currency::Bitcoin)
317 .amount_milli_satoshis(2_500_000_000)
318 .duration_since_epoch(Duration::from_secs(1496314658))
319 .payment_secret(PaymentSecret([0x11; 32]))
320 .payment_hash(sha256::Hash::from_str(
321 "0001020304050607080900010203040506070809000102030405060708090102"
323 .description("coffee beans".to_owned())
327 RecoverableSignature::from_compact(
328 &<Vec<u8>>::from_hex("150a5252308f25bc2641a186de87470189bb003774326beee33b9a2a720d1584386631c5dda6fc3195f97464bfc93d2574868eadd767d6da1078329c4349c837").unwrap(),
329 RecoveryId::from_i32(0).unwrap()
332 true, // Different features than set in InvoiceBuilder
333 true, // Some unknown fields
335 ( // Older version of the payment metadata test with a payment_pubkey set
336 "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqnp4q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66sp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgqy9gw6ymamd20jumvdgpfphkhp8fzhhdhycw36egcmla5vlrtrmhs9t7psfy3hkkdqzm9eq64fjg558znccds5nhsfmxveha5xe0dykgpspdha0".to_owned(),
337 InvoiceBuilder::new(Currency::Bitcoin)
338 .amount_milli_satoshis(1_000_000_000)
339 .duration_since_epoch(Duration::from_secs(1496314658))
340 .payment_hash(sha256::Hash::from_str(
341 "0001020304050607080900010203040506070809000102030405060708090102"
343 .description("payment metadata inside".to_owned())
344 .payment_metadata(<Vec<u8>>::from_hex("01fafaf0").unwrap())
345 .require_payment_metadata()
346 .payee_pub_key(PublicKey::from_slice(&<Vec<u8>>::from_hex(
347 "03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad"
348 ).unwrap()).unwrap())
349 .payment_secret(PaymentSecret([0x11; 32]))
353 RecoverableSignature::from_compact(
354 &<Vec<u8>>::from_hex("2150ed137ddb54f9736c6a0290ded709d22bddb7261d1d6518dffb467c6b1eef02afc182491bdacd00b65c83554c914a1c53c61b0a4ef04eccccdfb4365ed259").unwrap(),
355 RecoveryId::from_i32(1).unwrap()
358 false, // Different features than set in InvoiceBuilder
359 true, // Some unknown fields
362 "lnbc10m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdp9wpshjmt9de6zqmt9w3skgct5vysxjmnnd9jx2mq8q8a04uqsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q2gqqqqqqsgq7hf8he7ecf7n4ffphs6awl9t6676rrclv9ckg3d3ncn7fct63p6s365duk5wrk202cfy3aj5xnnp5gs3vrdvruverwwq7yzhkf5a3xqpd05wjc".to_owned(),
363 InvoiceBuilder::new(Currency::Bitcoin)
364 .amount_milli_satoshis(1_000_000_000)
365 .duration_since_epoch(Duration::from_secs(1496314658))
366 .payment_hash(sha256::Hash::from_str(
367 "0001020304050607080900010203040506070809000102030405060708090102"
369 .description("payment metadata inside".to_owned())
370 .payment_metadata(<Vec<u8>>::from_hex("01fafaf0").unwrap())
371 .require_payment_metadata()
372 .payment_secret(PaymentSecret([0x11; 32]))
376 RecoverableSignature::from_compact(
377 &<Vec<u8>>::from_hex("f5d27be7d9c27d3aa521bc35d77cabd6bda18f1f61716445b19e27e4e17a887508ea8de5a8e1d94f561248f65434e61a221160dac1f1991b9c0f1057b269d898").unwrap(),
378 RecoveryId::from_i32(1).unwrap()
381 false, // Different features than set in InvoiceBuilder
382 true, // Some unknown fields
389 fn invoice_deserialize() {
390 for (serialized, deserialized, ignore_feature_diff, ignore_unknown_fields) in get_test_tuples() {
391 eprintln!("Testing invoice {}...", serialized);
392 let parsed = serialized.parse::<SignedRawBolt11Invoice>().unwrap();
394 let (parsed_invoice, _, parsed_sig) = parsed.into_parts();
395 let (deserialized_invoice, _, deserialized_sig) = deserialized.into_parts();
397 assert_eq!(deserialized_sig, parsed_sig);
398 assert_eq!(deserialized_invoice.hrp, parsed_invoice.hrp);
399 assert_eq!(deserialized_invoice.data.timestamp, parsed_invoice.data.timestamp);
401 let mut deserialized_hunks: HashSet<_> = deserialized_invoice.data.tagged_fields.iter().collect();
402 let mut parsed_hunks: HashSet<_> = parsed_invoice.data.tagged_fields.iter().collect();
403 if ignore_feature_diff {
404 deserialized_hunks.retain(|h|
405 if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true });
406 parsed_hunks.retain(|h|
407 if let RawTaggedField::KnownSemantics(TaggedField::Features(_)) = h { false } else { true });
409 if ignore_unknown_fields {
410 parsed_hunks.retain(|h|
411 if let RawTaggedField::UnknownSemantics(_) = h { false } else { true });
413 assert_eq!(deserialized_hunks, parsed_hunks);
415 Bolt11Invoice::from_signed(serialized.parse::<SignedRawBolt11Invoice>().unwrap()).unwrap();
420 fn test_bolt_invalid_invoices() {
421 // Tests the BOLT 11 invalid invoice test vectors
422 assert_eq!(Bolt11Invoice::from_str(
423 "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q4psqqqqqqqqqqqqqqqqsgqtqyx5vggfcsll4wu246hz02kp85x4katwsk9639we5n5yngc3yhqkm35jnjw4len8vrnqnf5ejh0mzj9n3vz2px97evektfm2l6wqccp3y7372"
424 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::InvalidFeatures)));
425 assert_eq!(Bolt11Invoice::from_str(
426 "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrnt"
427 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::InvalidChecksum))));
428 assert_eq!(Bolt11Invoice::from_str(
429 "pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
430 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MissingSeparator))));
431 assert_eq!(Bolt11Invoice::from_str(
432 "LNBC2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny"
433 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::Bech32Error(bech32::Error::MixedCase))));
434 assert_eq!(Bolt11Invoice::from_str(
435 "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqwgt7mcn5yqw3yx0w94pswkpq6j9uh6xfqqqtsk4tnarugeektd4hg5975x9am52rz4qskukxdmjemg92vvqz8nvmsye63r5ykel43pgz7zq0g2"
436 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::InvalidSignature)));
437 assert_eq!(Bolt11Invoice::from_str(
438 "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6na6hlh"
439 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::TooShortDataPart)));
440 assert_eq!(Bolt11Invoice::from_str(
441 "lnbc2500x1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgqrrzc4cvfue4zp3hggxp47ag7xnrlr8vgcmkjxk3j5jqethnumgkpqp23z9jclu3v0a7e0aruz366e9wqdykw6dxhdzcjjhldxq0w6wgqcnu43j"
442 ), Err(ParseOrSemanticError::ParseError(Bolt11ParseError::UnknownSiPrefix)));
443 assert_eq!(Bolt11Invoice::from_str(
444 "lnbc2500000001p1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpusp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9qrsgq0lzc236j96a95uv0m3umg28gclm5lqxtqqwk32uuk4k6673k6n5kfvx3d2h8s295fad45fdhmusm8sjudfhlf6dcsxmfvkeywmjdkxcp99202x"
445 ), Err(ParseOrSemanticError::SemanticError(Bolt11SemanticError::ImpreciseAmount)));