1use 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
24pub struct Bs58verify {}
26
27impl Bs58verify {
28 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 NonAsciiCharacter(u8),
85 NonBs58Character(u8),
87}