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