use purecrypto::hash::{Blake3, keccak256, ripemd160, sha256};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HashFn {
Sha256,
Ripemd160,
Keccak256,
Blake3,
EtherHash,
}
impl HashFn {
fn apply(self, data: &[u8]) -> Vec<u8> {
match self {
HashFn::Sha256 => sha256(data).to_vec(),
HashFn::Ripemd160 => ripemd160(data).to_vec(),
HashFn::Keccak256 => keccak256(data).to_vec(),
HashFn::Blake3 => Blake3::hash(data).to_vec(),
HashFn::EtherHash => ether_hash(data).to_vec(),
}
}
}
pub fn hash_chain(data: &[u8], fns: &[HashFn]) -> Vec<u8> {
let mut cur = data.to_vec();
for f in fns {
cur = f.apply(&cur);
}
cur
}
pub fn sha256_once(data: &[u8]) -> [u8; 32] {
sha256(data)
}
pub fn dsha256(data: &[u8]) -> [u8; 32] {
sha256(&sha256(data))
}
pub fn hash160(data: &[u8]) -> [u8; 20] {
ripemd160(&sha256(data))
}
pub fn keccak256_once(data: &[u8]) -> [u8; 32] {
keccak256(data)
}
pub fn blake3_256(data: &[u8]) -> [u8; 32] {
Blake3::hash(data)
}
pub fn ether_hash(uncompressed_pubkey: &[u8]) -> [u8; 20] {
let body = if uncompressed_pubkey.is_empty() {
uncompressed_pubkey
} else {
&uncompressed_pubkey[1..]
};
let h = keccak256(body);
let mut out = [0u8; 20];
out.copy_from_slice(&h[12..]);
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash160() {
let h = hash160(b"");
assert_eq!(hex::encode(h), "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb");
}
#[test]
fn test_dsha256() {
let h = dsha256(b"hello");
assert_eq!(
hex::encode(h),
"9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50"
);
}
#[test]
fn test_hash_chain_matches_helpers() {
let data = b"the quick brown fox";
assert_eq!(
hash_chain(data, &[HashFn::Sha256, HashFn::Sha256]),
dsha256(data).to_vec()
);
assert_eq!(
hash_chain(data, &[HashFn::Sha256, HashFn::Ripemd160]),
hash160(data).to_vec()
);
}
}