base58check_encode/
lib.rs1use std::error::Error;
9use sha2::{Digest, Sha256};
10
11mod base58check_config;
12use base58check_config::Base58CheckConfig;
13
14#[cfg(test)]
15mod tests;
16
17
18pub fn encode_b58c_plain(source: Vec<u8>) -> Result<String, Box<dyn Error>> {
20
21 let b_config = Base58CheckConfig::default();
22
23 if source.len() <= 0 { return Ok("".to_string()); }
24
25 let mut zeroes: usize = 0;
26 let mut length: usize = 0;
27 let mut pbegin: usize = 0;
28
29 let pend = source.len();
30
31 while pbegin != source.len() && source[pbegin] == 0 {
32 pbegin += 1;
33 zeroes += 1;
34 }
35
36 let size = ((pend as f64 - pbegin as f64) * b_config.i_factor + 1.0) as u64 >> 0;
37
38 let mut b58: Vec<u8> = vec![0; size as usize]; while pbegin != pend {
40 let mut carry = source[pbegin] as u64;
41
42 let mut it1 = (size - 1) as i64;
43 let mut i = 0 as usize;
44
45 while (carry != 0 || i < length) && it1 != -1 {
46
47 carry += (256.0 * b58[it1 as usize] as f64) as u64 >> 0;
48 let carry_mod_base = (carry as f64 % b_config.base as f64) as u64 >> 0;
49 b58[it1 as usize] = carry_mod_base as u8;
50 carry = ((&carry / b_config.base) as f64) as u64 >> 0;
51
52 it1 = &it1 - 1;
53 i = &i + 1;
54 }
55
56 if carry != 0 {
57 panic!("carry is non-zero: c{} b{} i{} l{} b{} e{}", &carry, b58[it1 as usize], &i, &length, &pbegin, &pend);
58 }
59 length = i.to_owned();
60 pbegin += 1;
61 }
62
63 let mut it2 = (size as u64) - (length as u64);
64
65
66 while it2 != size && b58[it2 as usize] == 0 {
67 it2 += 1;
68 }
69 let mut str_leader = (format!("{}", b_config.leader)).as_str().repeat(zeroes);
70
71 while it2 < size {
72 it2 += 1;
73
74 let str_slice = format!("{}", b_config.alphabet_vec[b58[it2 as usize - 1 as usize] as usize]);
75
76 str_leader = format!("{}{}", &str_leader, &str_slice);
77 }
78
79 Ok(str_leader)
80}
81
82fn double_sha256(payload: &[u8]) -> Vec<u8> {
83 let hasher = Sha256::new().chain_update(&payload);
84 let output: Vec<_> = hasher.finalize().into_iter().collect();
85
86 let hasher = Sha256::new().chain_update(&output);
87 hasher.finalize().into_iter().collect()
88}
89
90pub fn encode(payload: Vec<u8>) -> Result<String, Box<dyn Error>> {
92 let payload_u8a: &[u8] = &*payload;
93 let checksum = double_sha256(payload_u8a);
94
95 let mut the_buffer: Vec<u8> = vec![0; payload.len() + 4];
96
97 let xx = payload_u8a.len();
98
99
100
101 let ii = 0;
102 for i in ii..xx {
103 the_buffer[i] = payload_u8a[i];
104 }
105
106 the_buffer[ xx + 0] = checksum[0];
107 the_buffer[ xx + 1] = checksum[1];
108 the_buffer[ xx + 2] = checksum[2];
109 the_buffer[ xx + 3] = checksum[3];
110
111 encode_b58c_plain(the_buffer)
112}
113
114