libzeropool_rs/
address.rs

1use 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}