Merge pull request #2024 from TheBlueMatt/2023-02-6conf-pub-hints
[rust-lightning] / lightning-invoice / src / de.rs
1 #[cfg(feature = "std")]
2 use std::error;
3 use core::fmt;
4 use core::fmt::{Display, Formatter};
5 use core::num::ParseIntError;
6 use core::str;
7 use core::str::FromStr;
8
9 use bech32::{u5, FromBase32};
10
11 use bitcoin_hashes::Hash;
12 use bitcoin_hashes::sha256;
13 use crate::prelude::*;
14 use lightning::ln::PaymentSecret;
15 use lightning::routing::gossip::RoutingFees;
16 use lightning::routing::router::{RouteHint, RouteHintHop};
17
18 use num_traits::{CheckedAdd, CheckedMul};
19
20 use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
21 use secp256k1::PublicKey;
22
23 use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiryDelta, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
24         SemanticError, PrivateRoute, ParseError, ParseOrSemanticError, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice,
25         constants, SignedRawInvoice, RawDataPart, InvoiceFeatures};
26
27 use self::hrp_sm::parse_hrp;
28
29 /// State machine to parse the hrp
30 mod hrp_sm {
31         use core::ops::Range;
32
33         #[derive(PartialEq, Eq, Debug)]
34         enum States {
35                 Start,
36                 ParseL,
37                 ParseN,
38                 ParseCurrencyPrefix,
39                 ParseAmountNumber,
40                 ParseAmountSiPrefix,
41         }
42
43         impl States {
44                 fn next_state(&self, read_symbol: char) -> Result<States, super::ParseError> {
45                         match *self {
46                                 States::Start => {
47                                         if read_symbol == 'l' {
48                                                 Ok(States::ParseL)
49                                         } else {
50                                                 Err(super::ParseError::MalformedHRP)
51                                         }
52                                 }
53                                 States::ParseL => {
54                                         if read_symbol == 'n' {
55                                                 Ok(States::ParseN)
56                                         } else {
57                                                 Err(super::ParseError::MalformedHRP)
58                                         }
59                                 },
60                                 States::ParseN => {
61                                         if !read_symbol.is_numeric() {
62                                                 Ok(States::ParseCurrencyPrefix)
63                                         } else {
64                                                 Ok(States::ParseAmountNumber)
65                                         }
66                                 },
67                                 States::ParseCurrencyPrefix => {
68                                         if !read_symbol.is_numeric() {
69                                                 Ok(States::ParseCurrencyPrefix)
70                                         } else {
71                                                 Ok(States::ParseAmountNumber)
72                                         }
73                                 },
74                                 States::ParseAmountNumber => {
75                                         if read_symbol.is_numeric() {
76                                                 Ok(States::ParseAmountNumber)
77                                         } else if ['m', 'u', 'n', 'p'].contains(&read_symbol) {
78                                                 Ok(States::ParseAmountSiPrefix)
79                                         } else {
80                                                 Err(super::ParseError::UnknownSiPrefix)
81                                         }
82                                 },
83                                 States::ParseAmountSiPrefix => Err(super::ParseError::MalformedHRP),
84                         }
85                 }
86
87                 fn is_final(&self) -> bool {
88                         !(*self == States::ParseL || *self == States::ParseN)
89                 }
90         }
91
92
93         struct StateMachine {
94                 state: States,
95                 position: usize,
96                 currency_prefix: Option<Range<usize>>,
97                 amount_number: Option<Range<usize>>,
98                 amount_si_prefix: Option<Range<usize>>,
99         }
100
101         impl StateMachine {
102                 fn new() -> StateMachine {
103                         StateMachine {
104                                 state: States::Start,
105                                 position: 0,
106                                 currency_prefix: None,
107                                 amount_number: None,
108                                 amount_si_prefix: None,
109                         }
110                 }
111
112                 fn update_range(range: &mut Option<Range<usize>>, position: usize) {
113                         let new_range = match *range {
114                                 None => Range {start: position, end: position + 1},
115                                 Some(ref r) => Range {start: r.start, end: r.end + 1},
116                         };
117                         *range = Some(new_range);
118                 }
119
120                 fn step(&mut self, c: char) -> Result<(), super::ParseError> {
121                         let next_state = self.state.next_state(c)?;
122                         match next_state {
123                                 States::ParseCurrencyPrefix => {
124                                         StateMachine::update_range(&mut self.currency_prefix, self.position)
125                                 }
126                                 States::ParseAmountNumber => {
127                                         StateMachine::update_range(&mut self.amount_number, self.position)
128                                 },
129                                 States::ParseAmountSiPrefix => {
130                                         StateMachine::update_range(&mut self.amount_si_prefix, self.position)
131                                 },
132                                 _ => {}
133                         }
134
135                         self.position += 1;
136                         self.state = next_state;
137                         Ok(())
138                 }
139
140                 fn is_final(&self) -> bool {
141                         self.state.is_final()
142                 }
143
144                 fn currency_prefix(&self) -> &Option<Range<usize>> {
145                         &self.currency_prefix
146                 }
147
148                 fn amount_number(&self) -> &Option<Range<usize>> {
149                         &self.amount_number
150                 }
151
152                 fn amount_si_prefix(&self) -> &Option<Range<usize>> {
153                         &self.amount_si_prefix
154                 }
155         }
156
157         pub fn parse_hrp(input: &str) -> Result<(&str, &str, &str), super::ParseError> {
158                 let mut sm = StateMachine::new();
159                 for c in input.chars() {
160                         sm.step(c)?;
161                 }
162
163                 if !sm.is_final() {
164                         return Err(super::ParseError::MalformedHRP);
165                 }
166
167                 let currency = sm.currency_prefix().clone()
168                         .map(|r| &input[r]).unwrap_or("");
169                 let amount = sm.amount_number().clone()
170                         .map(|r| &input[r]).unwrap_or("");
171                 let si = sm.amount_si_prefix().clone()
172                         .map(|r| &input[r]).unwrap_or("");
173
174                 Ok((currency, amount, si))
175         }
176 }
177
178
179 impl FromStr for super::Currency {
180         type Err = ParseError;
181
182         fn from_str(currency_prefix: &str) -> Result<Self, ParseError> {
183                 match currency_prefix {
184                         "bc" => Ok(Currency::Bitcoin),
185                         "tb" => Ok(Currency::BitcoinTestnet),
186                         "bcrt" => Ok(Currency::Regtest),
187                         "sb" => Ok(Currency::Simnet),
188                         "tbs" => Ok(Currency::Signet),
189                         _ => Err(ParseError::UnknownCurrency)
190                 }
191         }
192 }
193
194 impl FromStr for SiPrefix {
195         type Err = ParseError;
196
197         fn from_str(currency_prefix: &str) -> Result<Self, ParseError> {
198                 use crate::SiPrefix::*;
199                 match currency_prefix {
200                         "m" => Ok(Milli),
201                         "u" => Ok(Micro),
202                         "n" => Ok(Nano),
203                         "p" => Ok(Pico),
204                         _ => Err(ParseError::UnknownSiPrefix)
205                 }
206         }
207 }
208
209 /// ```
210 /// use lightning_invoice::Invoice;
211 ///
212 ///
213 /// let invoice = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
214 /// h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
215 /// 5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
216 /// h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
217 /// j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
218 /// ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
219 /// guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
220 /// ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
221 /// p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
222 /// 8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
223 /// j5r6drg6k6zcqj0fcwg";
224 ///
225 /// assert!(invoice.parse::<Invoice>().is_ok());
226 /// ```
227 impl FromStr for Invoice {
228         type Err = ParseOrSemanticError;
229
230         fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
231                 let signed = s.parse::<SignedRawInvoice>()?;
232                 Ok(Invoice::from_signed(signed)?)
233         }
234 }
235
236 /// ```
237 /// use lightning_invoice::*;
238 ///
239 /// let invoice = "lnbc100p1psj9jhxdqud3jxktt5w46x7unfv9kz6mn0v3jsnp4q0d3p2sfluzdx45tqcs\
240 /// h2pu5qc7lgq0xs578ngs6s0s68ua4h7cvspp5q6rmq35js88zp5dvwrv9m459tnk2zunwj5jalqtyxqulh0l\
241 /// 5gflssp5nf55ny5gcrfl30xuhzj3nphgj27rstekmr9fw3ny5989s300gyus9qyysgqcqpcrzjqw2sxwe993\
242 /// h5pcm4dxzpvttgza8zhkqxpgffcrf5v25nwpr3cmfg7z54kuqq8rgqqqqqqqq2qqqqq9qq9qrzjqd0ylaqcl\
243 /// j9424x9m8h2vcukcgnm6s56xfgu3j78zyqzhgs4hlpzvznlugqq9vsqqqqqqqlgqqqqqeqq9qrzjqwldmj9d\
244 /// ha74df76zhx6l9we0vjdquygcdt3kssupehe64g6yyp5yz5rhuqqwccqqyqqqqlgqqqqjcqq9qrzjqf9e58a\
245 /// guqr0rcun0ajlvmzq3ek63cw2w282gv3z5uupmuwvgjtq2z55qsqqg6qqqyqqqrtnqqqzq3cqygrzjqvphms\
246 /// ywntrrhqjcraumvc4y6r8v4z5v593trte429v4hredj7ms5z52usqq9ngqqqqqqqlgqqqqqqgq9qrzjq2v0v\
247 /// p62g49p7569ev48cmulecsxe59lvaw3wlxm7r982zxa9zzj7z5l0cqqxusqqyqqqqlgqqqqqzsqygarl9fh3\
248 /// 8s0gyuxjjgux34w75dnc6xp2l35j7es3jd4ugt3lu0xzre26yg5m7ke54n2d5sym4xcmxtl8238xxvw5h5h5\
249 /// j5r6drg6k6zcqj0fcwg";
250 ///
251 /// let parsed_1 = invoice.parse::<Invoice>();
252 ///
253 /// let parsed_2 = match invoice.parse::<SignedRawInvoice>() {
254 ///     Ok(signed) => match Invoice::from_signed(signed) {
255 ///             Ok(invoice) => Ok(invoice),
256 ///             Err(e) => Err(ParseOrSemanticError::SemanticError(e)),
257 ///     },
258 ///     Err(e) => Err(ParseOrSemanticError::ParseError(e)),
259 /// };
260 ///
261 /// assert!(parsed_1.is_ok());
262 /// assert_eq!(parsed_1, parsed_2);
263 /// ```
264 impl FromStr for SignedRawInvoice {
265         type Err = ParseError;
266
267         fn from_str(s: &str) -> Result<Self, Self::Err> {
268                 let (hrp, data, var) = bech32::decode(s)?;
269
270                 if var == bech32::Variant::Bech32m {
271                         // Consider Bech32m addresses to be "Invalid Checksum", since that is what we'd get if
272                         // we didn't support Bech32m (which lightning does not use).
273                         return Err(ParseError::Bech32Error(bech32::Error::InvalidChecksum));
274                 }
275
276                 if data.len() < 104 {
277                         return Err(ParseError::TooShortDataPart);
278                 }
279
280                 let raw_hrp: RawHrp = hrp.parse()?;
281                 let data_part = RawDataPart::from_base32(&data[..data.len()-104])?;
282
283                 Ok(SignedRawInvoice {
284                         raw_invoice: RawInvoice {
285                                 hrp: raw_hrp,
286                                 data: data_part,
287                         },
288                         hash: RawInvoice::hash_from_parts(
289                                 hrp.as_bytes(),
290                                 &data[..data.len()-104]
291                         ),
292                         signature: InvoiceSignature::from_base32(&data[data.len()-104..])?,
293                 })
294         }
295 }
296
297 impl FromStr for RawHrp {
298         type Err = ParseError;
299
300         fn from_str(hrp: &str) -> Result<Self, <Self as FromStr>::Err> {
301                 let parts = parse_hrp(hrp)?;
302
303                 let currency = parts.0.parse::<Currency>()?;
304
305                 let amount = if !parts.1.is_empty() {
306                         Some(parts.1.parse::<u64>()?)
307                 } else {
308                         None
309                 };
310
311                 let si_prefix: Option<SiPrefix> = if parts.2.is_empty() {
312                         None
313                 } else {
314                         let si: SiPrefix = parts.2.parse()?;
315                         if let Some(amt) = amount {
316                                 if amt.checked_mul(si.multiplier()).is_none() {
317                                         return Err(ParseError::IntegerOverflowError);
318                                 }
319                         }
320                         Some(si)
321                 };
322
323                 Ok(RawHrp {
324                         currency,
325                         raw_amount: amount,
326                         si_prefix,
327                 })
328         }
329 }
330
331 impl FromBase32 for RawDataPart {
332         type Err = ParseError;
333
334         fn from_base32(data: &[u5]) -> Result<Self, Self::Err> {
335                 if data.len() < 7 { // timestamp length
336                         return Err(ParseError::TooShortDataPart);
337                 }
338
339                 let timestamp = PositiveTimestamp::from_base32(&data[0..7])?;
340                 let tagged = parse_tagged_parts(&data[7..])?;
341
342                 Ok(RawDataPart {
343                         timestamp,
344                         tagged_fields: tagged,
345                 })
346         }
347 }
348
349 impl FromBase32 for PositiveTimestamp {
350         type Err = ParseError;
351
352         fn from_base32(b32: &[u5]) -> Result<Self, Self::Err> {
353                 if b32.len() != 7 {
354                         return Err(ParseError::InvalidSliceLength("PositiveTimestamp::from_base32()".into()));
355                 }
356                 let timestamp: u64 = parse_int_be(b32, 32)
357                         .expect("7*5bit < 64bit, no overflow possible");
358                 match PositiveTimestamp::from_unix_timestamp(timestamp) {
359                         Ok(t) => Ok(t),
360                         Err(_) => unreachable!(),
361                 }
362         }
363 }
364
365 impl FromBase32 for InvoiceSignature {
366         type Err = ParseError;
367         fn from_base32(signature: &[u5]) -> Result<Self, Self::Err> {
368                 if signature.len() != 104 {
369                         return Err(ParseError::InvalidSliceLength("InvoiceSignature::from_base32()".into()));
370                 }
371                 let recoverable_signature_bytes = Vec::<u8>::from_base32(signature)?;
372                 let signature = &recoverable_signature_bytes[0..64];
373                 let recovery_id = RecoveryId::from_i32(recoverable_signature_bytes[64] as i32)?;
374
375                 Ok(InvoiceSignature(RecoverableSignature::from_compact(
376                         signature,
377                         recovery_id
378                 )?))
379         }
380 }
381
382 pub(crate) fn parse_int_be<T, U>(digits: &[U], base: T) -> Option<T>
383         where T: CheckedAdd + CheckedMul + From<u8> + Default,
384               U: Into<u8> + Copy
385 {
386         digits.iter().fold(Some(Default::default()), |acc, b|
387                 acc
388                         .and_then(|x| x.checked_mul(&base))
389                         .and_then(|x| x.checked_add(&(Into::<u8>::into(*b)).into()))
390         )
391 }
392
393 fn parse_tagged_parts(data: &[u5]) -> Result<Vec<RawTaggedField>, ParseError> {
394         let mut parts = Vec::<RawTaggedField>::new();
395         let mut data = data;
396
397         while !data.is_empty() {
398                 if data.len() < 3 {
399                         return Err(ParseError::UnexpectedEndOfTaggedFields);
400                 }
401
402                 // Ignore tag at data[0], it will be handled in the TaggedField parsers and
403                 // parse the length to find the end of the tagged field's data
404                 let len = parse_int_be(&data[1..3], 32).expect("can't overflow");
405                 let last_element = 3 + len;
406
407                 if data.len() < last_element {
408                         return Err(ParseError::UnexpectedEndOfTaggedFields);
409                 }
410
411                 // Get the tagged field's data slice
412                 let field = &data[0..last_element];
413
414                 // Set data slice to remaining data
415                 data = &data[last_element..];
416
417                 match TaggedField::from_base32(field) {
418                         Ok(field) => {
419                                 parts.push(RawTaggedField::KnownSemantics(field))
420                         },
421                         Err(ParseError::Skip)|Err(ParseError::Bech32Error(bech32::Error::InvalidLength)) => {
422                                 parts.push(RawTaggedField::UnknownSemantics(field.into()))
423                         },
424                         Err(e) => {return Err(e)}
425                 }
426         }
427         Ok(parts)
428 }
429
430 impl FromBase32 for TaggedField {
431         type Err = ParseError;
432
433         fn from_base32(field: &[u5]) -> Result<TaggedField, ParseError> {
434                 if field.len() < 3 {
435                         return Err(ParseError::UnexpectedEndOfTaggedFields);
436                 }
437
438                 let tag = field[0];
439                 let field_data =  &field[3..];
440
441                 match tag.to_u8() {
442                         constants::TAG_PAYMENT_HASH =>
443                                 Ok(TaggedField::PaymentHash(Sha256::from_base32(field_data)?)),
444                         constants::TAG_DESCRIPTION =>
445                                 Ok(TaggedField::Description(Description::from_base32(field_data)?)),
446                         constants::TAG_PAYEE_PUB_KEY =>
447                                 Ok(TaggedField::PayeePubKey(PayeePubKey::from_base32(field_data)?)),
448                         constants::TAG_DESCRIPTION_HASH =>
449                                 Ok(TaggedField::DescriptionHash(Sha256::from_base32(field_data)?)),
450                         constants::TAG_EXPIRY_TIME =>
451                                 Ok(TaggedField::ExpiryTime(ExpiryTime::from_base32(field_data)?)),
452                         constants::TAG_MIN_FINAL_CLTV_EXPIRY_DELTA =>
453                                 Ok(TaggedField::MinFinalCltvExpiryDelta(MinFinalCltvExpiryDelta::from_base32(field_data)?)),
454                         constants::TAG_FALLBACK =>
455                                 Ok(TaggedField::Fallback(Fallback::from_base32(field_data)?)),
456                         constants::TAG_PRIVATE_ROUTE =>
457                                 Ok(TaggedField::PrivateRoute(PrivateRoute::from_base32(field_data)?)),
458                         constants::TAG_PAYMENT_SECRET =>
459                                 Ok(TaggedField::PaymentSecret(PaymentSecret::from_base32(field_data)?)),
460                         constants::TAG_FEATURES =>
461                                 Ok(TaggedField::Features(InvoiceFeatures::from_base32(field_data)?)),
462                         _ => {
463                                 // "A reader MUST skip over unknown fields"
464                                 Err(ParseError::Skip)
465                         }
466                 }
467         }
468 }
469
470 impl FromBase32 for Sha256 {
471         type Err = ParseError;
472
473         fn from_base32(field_data: &[u5]) -> Result<Sha256, ParseError> {
474                 if field_data.len() != 52 {
475                         // "A reader MUST skip over […] a p, [or] h […] field that does not have data_length 52 […]."
476                         Err(ParseError::Skip)
477                 } else {
478                         Ok(Sha256(sha256::Hash::from_slice(&Vec::<u8>::from_base32(field_data)?)
479                                 .expect("length was checked before (52 u5 -> 32 u8)")))
480                 }
481         }
482 }
483
484 impl FromBase32 for Description {
485         type Err = ParseError;
486
487         fn from_base32(field_data: &[u5]) -> Result<Description, ParseError> {
488                 let bytes = Vec::<u8>::from_base32(field_data)?;
489                 let description = String::from(str::from_utf8(&bytes)?);
490                 Ok(Description::new(description).expect(
491                         "Max len is 639=floor(1023*5/8) since the len field is only 10bits long"
492                 ))
493         }
494 }
495
496 impl FromBase32 for PayeePubKey {
497         type Err = ParseError;
498
499         fn from_base32(field_data: &[u5]) -> Result<PayeePubKey, ParseError> {
500                 if field_data.len() != 53 {
501                         // "A reader MUST skip over […] a n […] field that does not have data_length 53 […]."
502                         Err(ParseError::Skip)
503                 } else {
504                         let data_bytes = Vec::<u8>::from_base32(field_data)?;
505                         let pub_key = PublicKey::from_slice(&data_bytes)?;
506                         Ok(pub_key.into())
507                 }
508         }
509 }
510
511 impl FromBase32 for ExpiryTime {
512         type Err = ParseError;
513
514         fn from_base32(field_data: &[u5]) -> Result<ExpiryTime, ParseError> {
515                 match parse_int_be::<u64, u5>(field_data, 32)
516                         .map(ExpiryTime::from_seconds)
517                 {
518                         Some(t) => Ok(t),
519                         None => Err(ParseError::IntegerOverflowError),
520                 }
521         }
522 }
523
524 impl FromBase32 for MinFinalCltvExpiryDelta {
525         type Err = ParseError;
526
527         fn from_base32(field_data: &[u5]) -> Result<MinFinalCltvExpiryDelta, ParseError> {
528                 let expiry = parse_int_be::<u64, u5>(field_data, 32);
529                 if let Some(expiry) = expiry {
530                         Ok(MinFinalCltvExpiryDelta(expiry))
531                 } else {
532                         Err(ParseError::IntegerOverflowError)
533                 }
534         }
535 }
536
537 impl FromBase32 for Fallback {
538         type Err = ParseError;
539
540         fn from_base32(field_data: &[u5]) -> Result<Fallback, ParseError> {
541                 if field_data.is_empty() {
542                         return Err(ParseError::UnexpectedEndOfTaggedFields);
543                 }
544
545                 let version = field_data[0];
546                 let bytes = Vec::<u8>::from_base32(&field_data[1..])?;
547
548                 match version.to_u8() {
549                         0..=16 => {
550                                 if bytes.len() < 2 || bytes.len() > 40 {
551                                         return Err(ParseError::InvalidSegWitProgramLength);
552                                 }
553
554                                 Ok(Fallback::SegWitProgram {
555                                         version,
556                                         program: bytes
557                                 })
558                         },
559                         17 => {
560                                 if bytes.len() != 20 {
561                                         return Err(ParseError::InvalidPubKeyHashLength);
562                                 }
563                                 //TODO: refactor once const generics are available
564                                 let mut pkh = [0u8; 20];
565                                 pkh.copy_from_slice(&bytes);
566                                 Ok(Fallback::PubKeyHash(pkh))
567                         }
568                         18 => {
569                                 if bytes.len() != 20 {
570                                         return Err(ParseError::InvalidScriptHashLength);
571                                 }
572                                 let mut sh = [0u8; 20];
573                                 sh.copy_from_slice(&bytes);
574                                 Ok(Fallback::ScriptHash(sh))
575                         }
576                         _ => Err(ParseError::Skip)
577                 }
578         }
579 }
580
581 impl FromBase32 for PrivateRoute {
582         type Err = ParseError;
583
584         fn from_base32(field_data: &[u5]) -> Result<PrivateRoute, ParseError> {
585                 let bytes = Vec::<u8>::from_base32(field_data)?;
586
587                 if bytes.len() % 51 != 0 {
588                         return Err(ParseError::UnexpectedEndOfTaggedFields);
589                 }
590
591                 let mut route_hops = Vec::<RouteHintHop>::new();
592
593                 let mut bytes = bytes.as_slice();
594                 while !bytes.is_empty() {
595                         let hop_bytes = &bytes[0..51];
596                         bytes = &bytes[51..];
597
598                         let mut channel_id: [u8; 8] = Default::default();
599                         channel_id.copy_from_slice(&hop_bytes[33..41]);
600
601                         let hop = RouteHintHop {
602                                 src_node_id: PublicKey::from_slice(&hop_bytes[0..33])?,
603                                 short_channel_id: parse_int_be(&channel_id, 256).expect("short chan ID slice too big?"),
604                                 fees: RoutingFees {
605                                         base_msat: parse_int_be(&hop_bytes[41..45], 256).expect("slice too big?"),
606                                         proportional_millionths: parse_int_be(&hop_bytes[45..49], 256).expect("slice too big?"),
607                                 },
608                                 cltv_expiry_delta: parse_int_be(&hop_bytes[49..51], 256).expect("slice too big?"),
609                                 htlc_minimum_msat: None,
610                                 htlc_maximum_msat: None,
611                         };
612
613                         route_hops.push(hop);
614                 }
615
616                 Ok(PrivateRoute(RouteHint(route_hops)))
617         }
618 }
619
620 impl Display for ParseError {
621         fn fmt(&self, f: &mut Formatter) -> fmt::Result {
622                 match *self {
623                         // TODO: find a way to combine the first three arms (e as error::Error?)
624                         ParseError::Bech32Error(ref e) => {
625                                 write!(f, "Invalid bech32: {}", e)
626                         }
627                         ParseError::ParseAmountError(ref e) => {
628                                 write!(f, "Invalid amount in hrp ({})", e)
629                         }
630                         ParseError::MalformedSignature(ref e) => {
631                                 write!(f, "Invalid secp256k1 signature: {}", e)
632                         }
633                         ParseError::DescriptionDecodeError(ref e) => {
634                                 write!(f, "Description is not a valid utf-8 string: {}", e)
635                         }
636                         ParseError::InvalidSliceLength(ref function) => {
637                                 write!(f, "Slice in function {} had the wrong length", function)
638                         }
639                         ParseError::BadPrefix => f.write_str("did not begin with 'ln'"),
640                         ParseError::UnknownCurrency => f.write_str("currency code unknown"),
641                         ParseError::UnknownSiPrefix => f.write_str("unknown SI prefix"),
642                         ParseError::MalformedHRP => f.write_str("malformed human readable part"),
643                         ParseError::TooShortDataPart => {
644                                 f.write_str("data part too short (should be at least 111 bech32 chars long)")
645                         },
646                         ParseError::UnexpectedEndOfTaggedFields => {
647                                 f.write_str("tagged fields part ended unexpectedly")
648                         },
649                         ParseError::PaddingError => f.write_str("some data field had bad padding"),
650                         ParseError::IntegerOverflowError => {
651                                 f.write_str("parsed integer doesn't fit into receiving type")
652                         },
653                         ParseError::InvalidSegWitProgramLength => {
654                                 f.write_str("fallback SegWit program is too long or too short")
655                         },
656                         ParseError::InvalidPubKeyHashLength => {
657                                 f.write_str("fallback public key hash has a length unequal 20 bytes")
658                         },
659                         ParseError::InvalidScriptHashLength => {
660                                 f.write_str("fallback script hash has a length unequal 32 bytes")
661                         },
662                         ParseError::InvalidRecoveryId => {
663                                 f.write_str("recovery id is out of range (should be in [0,3])")
664                         },
665                         ParseError::Skip => {
666                                 f.write_str("the tagged field has to be skipped because of an unexpected, but allowed property")
667                         },
668                 }
669         }
670 }
671
672 impl Display for ParseOrSemanticError {
673         fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
674                 match self {
675                         ParseOrSemanticError::ParseError(err) => err.fmt(f),
676                         ParseOrSemanticError::SemanticError(err) => err.fmt(f),
677                 }
678         }
679 }
680
681 #[cfg(feature = "std")]
682 impl error::Error for ParseError {}
683
684 #[cfg(feature = "std")]
685 impl error::Error for ParseOrSemanticError {}
686
687 macro_rules! from_error {
688     ($my_error:expr, $extern_error:ty) => {
689         impl From<$extern_error> for ParseError {
690             fn from(e: $extern_error) -> Self {
691                 $my_error(e)
692             }
693         }
694     }
695 }
696
697 from_error!(ParseError::MalformedSignature, secp256k1::Error);
698 from_error!(ParseError::ParseAmountError, ParseIntError);
699 from_error!(ParseError::DescriptionDecodeError, str::Utf8Error);
700
701 impl From<bech32::Error> for ParseError {
702         fn from(e: bech32::Error) -> Self {
703                 match e {
704                         bech32::Error::InvalidPadding => ParseError::PaddingError,
705                         _ => ParseError::Bech32Error(e)
706                 }
707         }
708 }
709
710 impl From<ParseError> for ParseOrSemanticError {
711         fn from(e: ParseError) -> Self {
712                 ParseOrSemanticError::ParseError(e)
713         }
714 }
715
716 impl From<crate::SemanticError> for ParseOrSemanticError {
717         fn from(e: SemanticError) -> Self {
718                 ParseOrSemanticError::SemanticError(e)
719         }
720 }
721
722 #[cfg(test)]
723 mod test {
724         use crate::de::ParseError;
725         use secp256k1::PublicKey;
726         use bech32::u5;
727         use bitcoin_hashes::hex::FromHex;
728         use bitcoin_hashes::sha256;
729
730         const CHARSET_REV: [i8; 128] = [
731                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
732                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
733                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
734                 15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
735                 -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
736                 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
737                 -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
738                 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
739         ];
740
741         fn from_bech32(bytes_5b: &[u8]) -> Vec<u5> {
742                 bytes_5b
743                         .iter()
744                         .map(|c| u5::try_from_u8(CHARSET_REV[*c as usize] as u8).unwrap())
745                         .collect()
746         }
747
748         #[test]
749         fn test_parse_currency_prefix() {
750                 use crate::Currency;
751
752                 assert_eq!("bc".parse::<Currency>(), Ok(Currency::Bitcoin));
753                 assert_eq!("tb".parse::<Currency>(), Ok(Currency::BitcoinTestnet));
754                 assert_eq!("bcrt".parse::<Currency>(), Ok(Currency::Regtest));
755                 assert_eq!("sb".parse::<Currency>(), Ok(Currency::Simnet));
756                 assert_eq!("tbs".parse::<Currency>(), Ok(Currency::Signet));
757                 assert_eq!("something_else".parse::<Currency>(), Err(ParseError::UnknownCurrency))
758         }
759
760         #[test]
761         fn test_parse_int_from_bytes_be() {
762                 use crate::de::parse_int_be;
763
764                 assert_eq!(parse_int_be::<u32, u8>(&[1, 2, 3, 4], 256), Some(16909060));
765                 assert_eq!(parse_int_be::<u32, u8>(&[1, 3], 32), Some(35));
766                 assert_eq!(parse_int_be::<u32, u8>(&[255, 255, 255, 255], 256), Some(4294967295));
767                 assert_eq!(parse_int_be::<u32, u8>(&[1, 0, 0, 0, 0], 256), None);
768         }
769
770         #[test]
771         fn test_parse_sha256_hash() {
772                 use crate::Sha256;
773                 use bech32::FromBase32;
774
775                 let input = from_bech32(
776                         "qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq".as_bytes()
777                 );
778
779                 let hash = sha256::Hash::from_hex(
780                         "0001020304050607080900010203040506070809000102030405060708090102"
781                 ).unwrap();
782                 let expected = Ok(Sha256(hash));
783
784                 assert_eq!(Sha256::from_base32(&input), expected);
785
786                 // make sure hashes of unknown length get skipped
787                 let input_unexpected_length = from_bech32(
788                         "qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypyq".as_bytes()
789                 );
790                 assert_eq!(Sha256::from_base32(&input_unexpected_length), Err(ParseError::Skip));
791         }
792
793         #[test]
794         fn test_parse_description() {
795                 use crate::Description;
796                 use bech32::FromBase32;
797
798                 let input = from_bech32("xysxxatsyp3k7enxv4js".as_bytes());
799                 let expected = Ok(Description::new("1 cup coffee".to_owned()).unwrap());
800                 assert_eq!(Description::from_base32(&input), expected);
801         }
802
803         #[test]
804         fn test_parse_payee_pub_key() {
805                 use crate::PayeePubKey;
806                 use bech32::FromBase32;
807
808                 let input = from_bech32("q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhv66".as_bytes());
809                 let pk_bytes = [
810                         0x03, 0xe7, 0x15, 0x6a, 0xe3, 0x3b, 0x0a, 0x20, 0x8d, 0x07, 0x44, 0x19, 0x91, 0x63,
811                         0x17, 0x7e, 0x90, 0x9e, 0x80, 0x17, 0x6e, 0x55, 0xd9, 0x7a, 0x2f, 0x22, 0x1e, 0xde,
812                         0x0f, 0x93, 0x4d, 0xd9, 0xad
813                 ];
814                 let expected = Ok(PayeePubKey(
815                         PublicKey::from_slice(&pk_bytes[..]).unwrap()
816                 ));
817
818                 assert_eq!(PayeePubKey::from_base32(&input), expected);
819
820                 // expects 33 bytes
821                 let input_unexpected_length = from_bech32(
822                         "q0n326hr8v9zprg8gsvezcch06gfaqqhde2aj730yg0durunfhvq".as_bytes()
823                 );
824                 assert_eq!(PayeePubKey::from_base32(&input_unexpected_length), Err(ParseError::Skip));
825         }
826
827         #[test]
828         fn test_parse_expiry_time() {
829                 use crate::ExpiryTime;
830                 use bech32::FromBase32;
831
832                 let input = from_bech32("pu".as_bytes());
833                 let expected = Ok(ExpiryTime::from_seconds(60));
834                 assert_eq!(ExpiryTime::from_base32(&input), expected);
835
836                 let input_too_large = from_bech32("sqqqqqqqqqqqq".as_bytes());
837                 assert_eq!(ExpiryTime::from_base32(&input_too_large), Err(ParseError::IntegerOverflowError));
838         }
839
840         #[test]
841         fn test_parse_min_final_cltv_expiry_delta() {
842                 use crate::MinFinalCltvExpiryDelta;
843                 use bech32::FromBase32;
844
845                 let input = from_bech32("pr".as_bytes());
846                 let expected = Ok(MinFinalCltvExpiryDelta(35));
847
848                 assert_eq!(MinFinalCltvExpiryDelta::from_base32(&input), expected);
849         }
850
851         #[test]
852         fn test_parse_fallback() {
853                 use crate::Fallback;
854                 use bech32::FromBase32;
855
856                 let cases = vec![
857                         (
858                                 from_bech32("3x9et2e20v6pu37c5d9vax37wxq72un98".as_bytes()),
859                                 Ok(Fallback::PubKeyHash([
860                                         0x31, 0x72, 0xb5, 0x65, 0x4f, 0x66, 0x83, 0xc8, 0xfb, 0x14, 0x69, 0x59, 0xd3,
861                                         0x47, 0xce, 0x30, 0x3c, 0xae, 0x4c, 0xa7
862                                 ]))
863                         ),
864                         (
865                                 from_bech32("j3a24vwu6r8ejrss3axul8rxldph2q7z9".as_bytes()),
866                                 Ok(Fallback::ScriptHash([
867                                         0x8f, 0x55, 0x56, 0x3b, 0x9a, 0x19, 0xf3, 0x21, 0xc2, 0x11, 0xe9, 0xb9, 0xf3,
868                                         0x8c, 0xdf, 0x68, 0x6e, 0xa0, 0x78, 0x45
869                                 ]))
870                         ),
871                         (
872                                 from_bech32("qw508d6qejxtdg4y5r3zarvary0c5xw7k".as_bytes()),
873                                 Ok(Fallback::SegWitProgram {
874                                         version: u5::try_from_u8(0).unwrap(),
875                                         program: Vec::from(&[
876                                                 0x75u8, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c, 0x45,
877                                                 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6
878                                         ][..])
879                                 })
880                         ),
881                         (
882                                 vec![u5::try_from_u8(21).unwrap(); 41],
883                                 Err(ParseError::Skip)
884                         ),
885                         (
886                                 vec![],
887                                 Err(ParseError::UnexpectedEndOfTaggedFields)
888                         ),
889                         (
890                                 vec![u5::try_from_u8(1).unwrap(); 81],
891                                 Err(ParseError::InvalidSegWitProgramLength)
892                         ),
893                         (
894                                 vec![u5::try_from_u8(17).unwrap(); 1],
895                                 Err(ParseError::InvalidPubKeyHashLength)
896                         ),
897                         (
898                                 vec![u5::try_from_u8(18).unwrap(); 1],
899                                 Err(ParseError::InvalidScriptHashLength)
900                         )
901                 ];
902
903                 for (input, expected) in cases.into_iter() {
904                         assert_eq!(Fallback::from_base32(&input), expected);
905                 }
906         }
907
908         #[test]
909         fn test_parse_route() {
910                 use lightning::routing::gossip::RoutingFees;
911                 use lightning::routing::router::{RouteHint, RouteHintHop};
912                 use crate::PrivateRoute;
913                 use bech32::FromBase32;
914                 use crate::de::parse_int_be;
915
916                 let input = from_bech32(
917                         "q20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqa\
918                         fqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq".as_bytes()
919                 );
920
921                 let mut expected = Vec::<RouteHintHop>::new();
922                 expected.push(RouteHintHop {
923                         src_node_id: PublicKey::from_slice(
924                                 &[
925                                         0x02u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c,
926                                         0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3,
927                                         0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55
928                                 ][..]
929                         ).unwrap(),
930                         short_channel_id: parse_int_be(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08], 256).expect("short chan ID slice too big?"),
931                         fees: RoutingFees {
932                                 base_msat: 1,
933                                 proportional_millionths: 20,
934                         },
935                         cltv_expiry_delta: 3,
936                         htlc_minimum_msat: None,
937                         htlc_maximum_msat: None
938                 });
939                 expected.push(RouteHintHop {
940                         src_node_id: PublicKey::from_slice(
941                                 &[
942                                         0x03u8, 0x9e, 0x03, 0xa9, 0x01, 0xb8, 0x55, 0x34, 0xff, 0x1e, 0x92, 0xc4, 0x3c,
943                                         0x74, 0x43, 0x1f, 0x7c, 0xe7, 0x20, 0x46, 0x06, 0x0f, 0xcf, 0x7a, 0x95, 0xc3,
944                                         0x7e, 0x14, 0x8f, 0x78, 0xc7, 0x72, 0x55
945                                 ][..]
946                         ).unwrap(),
947                         short_channel_id: parse_int_be(&[0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a], 256).expect("short chan ID slice too big?"),
948                         fees: RoutingFees {
949                                 base_msat: 2,
950                                 proportional_millionths: 30,
951                         },
952                         cltv_expiry_delta: 4,
953                         htlc_minimum_msat: None,
954                         htlc_maximum_msat: None
955                 });
956
957                 assert_eq!(PrivateRoute::from_base32(&input), Ok(PrivateRoute(RouteHint(expected))));
958
959                 assert_eq!(
960                         PrivateRoute::from_base32(&[u5::try_from_u8(0).unwrap(); 40][..]),
961                         Err(ParseError::UnexpectedEndOfTaggedFields)
962                 );
963         }
964
965         #[test]
966         fn test_payment_secret_and_features_de_and_ser() {
967                 use lightning::ln::features::InvoiceFeatures;
968                 use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
969                 use crate::TaggedField::*;
970                 use crate::{SiPrefix, SignedRawInvoice, InvoiceSignature, RawInvoice, RawHrp, RawDataPart,
971                                  Currency, Sha256, PositiveTimestamp};
972
973                 // Feature bits 9, 15, and 99 are set.
974                 let expected_features = InvoiceFeatures::from_le_bytes(vec![0, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8]);
975                 let invoice_str = "lnbc25m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5vdhkven9v5sxyetpdeessp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9q5sqqqqqqqqqqqqqqqpqsq67gye39hfg3zd8rgc80k32tvy9xk2xunwm5lzexnvpx6fd77en8qaq424dxgt56cag2dpt359k3ssyhetktkpqh24jqnjyw6uqd08sgptq44qu";
976                 let invoice = SignedRawInvoice {
977                                         raw_invoice: RawInvoice {
978                                                 hrp: RawHrp {
979                                                         currency: Currency::Bitcoin,
980                                                         raw_amount: Some(25),
981                                                         si_prefix: Some(SiPrefix::Milli)
982                                                 },
983                                                 data: RawDataPart {
984                                                         timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
985                                                         tagged_fields: vec ! [
986                                                                 PaymentHash(Sha256(sha256::Hash::from_hex(
987                                                                         "0001020304050607080900010203040506070809000102030405060708090102"
988                                                                 ).unwrap())).into(),
989                                                                 Description(crate::Description::new("coffee beans".to_owned()).unwrap()).into(),
990                                                                 PaymentSecret(crate::PaymentSecret([17; 32])).into(),
991                                                                 Features(expected_features).into()]}
992                                                                 },
993                                         hash: [0xb1, 0x96, 0x46, 0xc3, 0xbc, 0x56, 0x76, 0x1d, 0x20, 0x65, 0x6e, 0x0e, 0x32,
994                                                                         0xec, 0xd2, 0x69, 0x27, 0xb7, 0x62, 0x6e, 0x2a, 0x8b, 0xe6, 0x97, 0x71, 0x9f,
995                                                                         0xf8, 0x7e, 0x44, 0x54, 0x55, 0xb9],
996                                         signature: InvoiceSignature(RecoverableSignature::from_compact(
997                                                                                 &[0xd7, 0x90, 0x4c, 0xc4, 0xb7, 0x4a, 0x22, 0x26, 0x9c, 0x68, 0xc1, 0xdf, 0x68,
998                                                                                         0xa9, 0x6c, 0x21, 0x4d, 0x65, 0x1b, 0x93, 0x76, 0xe9, 0xf1, 0x64, 0xd3, 0x60,
999                                                                                         0x4d, 0xa4, 0xb7, 0xde, 0xcc, 0xce, 0x0e, 0x82, 0xaa, 0xab, 0x4c, 0x85, 0xd3,
1000                                                                                         0x58, 0xea, 0x14, 0xd0, 0xae, 0x34, 0x2d, 0xa3, 0x08, 0x12, 0xf9, 0x5d, 0x97,
1001                                                                                         0x60, 0x82, 0xea, 0xac, 0x81, 0x39, 0x11, 0xda, 0xe0, 0x1a, 0xf3, 0xc1],
1002                                                                                 RecoveryId::from_i32(1).unwrap()
1003                                                                 ).unwrap()),
1004                         };
1005                 assert_eq!(invoice_str, invoice.to_string());
1006                 assert_eq!(
1007                         invoice_str.parse(),
1008                         Ok(invoice)
1009                 );
1010         }
1011
1012         #[test]
1013         fn test_raw_signed_invoice_deserialization() {
1014                 use crate::TaggedField::*;
1015                 use secp256k1::ecdsa::{RecoveryId, RecoverableSignature};
1016                 use crate::{SignedRawInvoice, InvoiceSignature, RawInvoice, RawHrp, RawDataPart, Currency, Sha256,
1017                          PositiveTimestamp};
1018
1019                 assert_eq!(
1020                         "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmw\
1021                         wd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9\
1022                         ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w".parse(),
1023                         Ok(SignedRawInvoice {
1024                                 raw_invoice: RawInvoice {
1025                                         hrp: RawHrp {
1026                                                 currency: Currency::Bitcoin,
1027                                                 raw_amount: None,
1028                                                 si_prefix: None,
1029                                         },
1030                                         data: RawDataPart {
1031                                         timestamp: PositiveTimestamp::from_unix_timestamp(1496314658).unwrap(),
1032                                         tagged_fields: vec ! [
1033                                                 PaymentHash(Sha256(sha256::Hash::from_hex(
1034                                                         "0001020304050607080900010203040506070809000102030405060708090102"
1035                                                 ).unwrap())).into(),
1036                                                 Description(
1037                                                         crate::Description::new(
1038                                                                 "Please consider supporting this project".to_owned()
1039                                                         ).unwrap()
1040                                                 ).into(),
1041                                         ],
1042                                         },
1043                                         },
1044                                 hash: [
1045                                         0xc3, 0xd4, 0xe8, 0x3f, 0x64, 0x6f, 0xa7, 0x9a, 0x39, 0x3d, 0x75, 0x27,
1046                                         0x7b, 0x1d, 0x85, 0x8d, 0xb1, 0xd1, 0xf7, 0xab, 0x71, 0x37, 0xdc, 0xb7,
1047                                         0x83, 0x5d, 0xb2, 0xec, 0xd5, 0x18, 0xe1, 0xc9
1048                                 ],
1049                                 signature: InvoiceSignature(RecoverableSignature::from_compact(
1050                                         & [
1051                                                 0x38u8, 0xec, 0x68, 0x91, 0x34, 0x5e, 0x20, 0x41, 0x45, 0xbe, 0x8a,
1052                                                 0x3a, 0x99, 0xde, 0x38, 0xe9, 0x8a, 0x39, 0xd6, 0xa5, 0x69, 0x43,
1053                                                 0x4e, 0x18, 0x45, 0xc8, 0xaf, 0x72, 0x05, 0xaf, 0xcf, 0xcc, 0x7f,
1054                                                 0x42, 0x5f, 0xcd, 0x14, 0x63, 0xe9, 0x3c, 0x32, 0x88, 0x1e, 0xad,
1055                                                 0x0d, 0x6e, 0x35, 0x6d, 0x46, 0x7e, 0xc8, 0xc0, 0x25, 0x53, 0xf9,
1056                                                 0xaa, 0xb1, 0x5e, 0x57, 0x38, 0xb1, 0x1f, 0x12, 0x7f
1057                                         ],
1058                                         RecoveryId::from_i32(0).unwrap()
1059                                 ).unwrap()),
1060                                 }
1061                         )
1062                 )
1063         }
1064 }