ep_core/
bs58_verify.rs

1// Copyright (c) 2019 Alain Brenzikofer
2// This file is part of Encointer
3//
4// Encointer is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Encointer is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Encointer.  If not, see <http://www.gnu.org/licenses/>.
16
17use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
18use scale_info::TypeInfo;
19use sp_core::RuntimeDebug;
20
21#[cfg(feature = "serde_derive")]
22use serde::{Deserialize, Serialize};
23
24/// Simple Bs58 verification adapted from https://github.com/mycorrhiza/bs58-rs
25pub struct Bs58verify {}
26
27impl Bs58verify {
28	/// Obtained with:
29	/// ```rust
30	///     const BITCOIN_ALPHABET: &'static [u8] =
31	///         b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
32	///
33	///     const BITCOIN_DECODE_MAP: fn() -> [u8; 128] = || -> [u8; 128] {
34	///         let mut decode = [0xFF; 128];
35	///
36	///        let mut i = 0;
37	///         while i < BITCOIN_ALPHABET.len() {
38	///             decode[BITCOIN_ALPHABET[i] as usize] = i as u8;
39	///             i += 1;
40	///         }
41	///         return decode;
42	///     };
43	/// ```
44	const BITCOIN_DECODE_MAP: [u8; 128] = [
45		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
46		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
47		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
48		0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xFF, 0xFF,
49		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0xFF, 0x11,
50		0x12, 0x13, 0x14, 0x15, 0xFF, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
51		0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
52		0x29, 0x2A, 0x2B, 0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
53		0x37, 0x38, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
54	];
55
56	pub fn verify(bytes: &[u8]) -> Result<(), Bs58Error> {
57		for (i, c) in bytes.iter().enumerate() {
58			if *c > 127 {
59				return Err(Bs58Error::NonAsciiCharacter(i as u8));
60			}
61
62			if Self::BITCOIN_DECODE_MAP[*c as usize] as usize == 0xFF {
63				return Err(Bs58Error::NonBs58Character(i as u8));
64			}
65		}
66		Ok(())
67	}
68}
69
70#[derive(
71	Encode,
72	Decode,
73	DecodeWithMemTracking,
74	Clone,
75	PartialEq,
76	Eq,
77	RuntimeDebug,
78	TypeInfo,
79	MaxEncodedLen,
80)]
81#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
82pub enum Bs58Error {
83	/// Non ascii character at index
84	NonAsciiCharacter(u8),
85	/// Non bs58 character at index
86	NonBs58Character(u8),
87}