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
use ex3_crypto::{keccak256, secp256k1::Pubkey};
pub struct EthAddressParser;

impl EthAddressParser {
    pub fn to_address<T: AsRef<[u8]>>(pub_key: T) -> super::Result<String> {
        let original_pub_key: Pubkey = Pubkey::from_slice(pub_key.as_ref())?;
        let uncompressed: Vec<u8> = original_pub_key.serialize(false);

        let pub_key = &uncompressed.as_slice()[1..];
        let hash = keccak256(pub_key);
        let mut address = vec![0u8; 20];
        address.copy_from_slice(&hash[12..]);
        Ok(hex::encode(address))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ex3_crypto::secp256k1::Pubkey;
    use k256::ecdsa::VerifyingKey;
    use k256::elliptic_curve::sec1::ToEncodedPoint;
    use std::ops::Deref;

    #[test]
    fn test_eth_address_generation() {
        let private_str = "aab62dc0f7ecef14d37206898b7afb7bc00a508664e1b44607a3697873f79cc9";
        let pub_key = get_pub_key_from_private_key(private_str);

        let address_1 = "7a29794050c805140e840a04ca8a51f25ac181b7";
        let address_2 = EthAddressParser::to_address(pub_key.deref()).unwrap();
        assert_eq!(address_1, address_2)
    }

    #[test]
    fn test_eth_address_generation_2() {
        let private_str = "DC38EE117CAE37750EB1ECC5CFD3DE8E85963B481B93E732C5D0CB66EE6B0C9D";
        let pub_key = get_pub_key_from_private_key(private_str);
        let address_1 = "c5ed5d9b9c957be2baa01c16310aa4d1f8bc8e6f";
        let address_2 = EthAddressParser::to_address(*pub_key).unwrap();
        assert_eq!(address_1, address_2)
    }

    pub fn get_pub_key_from_private_key(private_str: &str) -> Pubkey {
        let secret_key = k256::SecretKey::from_slice(&hex::decode(private_str).unwrap()).unwrap();
        let pub_key = k256::PublicKey::from_secret_scalar(&secret_key.into());
        VerifyingKey::from_encoded_point(&pub_key.to_encoded_point(false))
            .unwrap()
            .into()
    }
}