use cosmwasm_std::{HexBinary, StdError, StdResult};
const PREFIX: &str = "\x19Ethereum Signed Message:\n";
pub fn keccak256_hash(bz: &[u8]) -> HexBinary {
use sha3::{Digest, Keccak256};
let mut hasher = Keccak256::new();
hasher.update(bz);
let hash = hasher.finalize().to_vec();
hash.into()
}
pub fn eth_hash(message: HexBinary) -> StdResult<HexBinary> {
let mut eth_message = format!("{PREFIX}{}", message.len()).into_bytes();
eth_message.extend_from_slice(&message);
let message_hash = keccak256_hash(ð_message);
Ok(message_hash)
}
pub fn eth_addr(pubkey: HexBinary) -> StdResult<HexBinary> {
let hash = keccak256_hash(&pubkey.as_slice()[1..]);
let mut bytes = [0u8; 20];
bytes.copy_from_slice(&hash.as_slice()[12..]);
let addr = HexBinary::from(bytes.to_vec());
Ok(addr.to_vec().into())
}
pub fn sha256_digest(bz: impl AsRef<[u8]>) -> StdResult<[u8; 32]> {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(bz);
hasher
.finalize()
.as_slice()
.try_into()
.map_err(|_| StdError::generic_err("wrong length"))
}
pub fn ripemd160_digest(bz: impl AsRef<[u8]>) -> StdResult<[u8; 20]> {
use ripemd::{Digest, Ripemd160};
let mut hasher = Ripemd160::new();
hasher.update(bz);
hasher
.finalize()
.as_slice()
.try_into()
.map_err(|_| StdError::generic_err("wrong length"))
}
pub fn pub_to_addr(pub_key: HexBinary) -> StdResult<HexBinary> {
let sha_hash = sha256_digest(pub_key)?;
let rip_hash = ripemd160_digest(sha_hash)?;
Ok(rip_hash.to_vec().into())
}