1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use libzeropool::{
constants,
fawkes_crypto::{
borsh::{BorshDeserialize, BorshSerialize},
ff_uint::Num,
},
native::{boundednum::BoundedNum, params::PoolParams},
};
use thiserror::Error;
use crate::utils::keccak256;
const ADDR_LEN: usize = 46;
#[derive(Error, Debug)]
pub enum AddressParseError {
#[error("Invalid checksum")]
InvalidChecksum,
#[error("Decode error: {0}")]
Base58DecodeError(#[from] bs58::decode::Error),
#[error("Deserialization error: {0}")]
DeserializationError(#[from] std::io::Error),
}
pub fn parse_address<P: PoolParams>(
address: &str,
) -> Result<
(
BoundedNum<P::Fr, { constants::DIVERSIFIER_SIZE_BITS }>,
Num<P::Fr>,
),
AddressParseError,
> {
let mut bytes = [0; ADDR_LEN];
bs58::decode(address).into(&mut bytes)?;
let checksum = &bytes[42..=45];
let hash = keccak256(&bytes[0..=41]);
if &hash[0..=3] != checksum {
return Err(AddressParseError::InvalidChecksum);
}
let d = BoundedNum::try_from_slice(&bytes[0..10])?;
let p_d = Num::try_from_slice(&bytes[10..42])?;
Ok((d, p_d))
}
pub fn format_address<P: PoolParams>(
d: BoundedNum<P::Fr, { constants::DIVERSIFIER_SIZE_BITS }>,
p_d: Num<P::Fr>,
) -> String {
let mut buf: [u8; ADDR_LEN] = [0; ADDR_LEN];
d.serialize(&mut &mut buf[0..10]).unwrap();
p_d.serialize(&mut &mut buf[10..42]).unwrap();
let hash = keccak256(&buf[0..42]);
buf[42..ADDR_LEN].clone_from_slice(&hash[0..4]);
bs58::encode(buf).into_string()
}