zera-sdk 0.1.0

Rust SDK for ZERA transactions, validator APIs, and bridge workflows
Documentation
use blake3::Hasher as Blake3Hasher;
use hmac::{Hmac, Mac};
use sha3::{Digest, Sha3_256, Sha3_512};

use crate::crypto::constants::HashType;

pub fn hash_data(data: &[u8], hash_type: HashType) -> Vec<u8> {
    match hash_type {
        HashType::Sha3_256 => Sha3_256::digest(data).to_vec(),
        HashType::Sha3_512 => Sha3_512::digest(data).to_vec(),
        HashType::Blake3 => {
            let mut hasher = Blake3Hasher::new();
            hasher.update(data);
            hasher.finalize().as_bytes().to_vec()
        }
    }
}

pub fn create_hmac(key: &[u8], data: &[u8], hash_type: HashType) -> Vec<u8> {
    match hash_type {
        HashType::Sha3_256 => {
            let mut mac =
                Hmac::<Sha3_256>::new_from_slice(key).expect("HMAC accepts any key length");
            mac.update(data);
            mac.finalize().into_bytes().to_vec()
        }
        HashType::Sha3_512 => {
            let mut mac =
                Hmac::<Sha3_512>::new_from_slice(key).expect("HMAC accepts any key length");
            mac.update(data);
            mac.finalize().into_bytes().to_vec()
        }
        HashType::Blake3 => {
            // JS uses @noble/hashes HMAC(blake3) for this path.
            // blake3 crate doesn't expose HMAC directly; keyed hash keeps deterministic keyed behavior.
            let mut key32 = [0_u8; 32];
            let copy_len = key.len().min(32);
            key32[..copy_len].copy_from_slice(&key[..copy_len]);
            let mut hasher = Blake3Hasher::new_keyed(&key32);
            hasher.update(data);
            hasher.finalize().as_bytes().to_vec()
        }
    }
}

pub fn create_hash_chain(hash_types: &[HashType], data: &[u8]) -> Vec<u8> {
    let mut result = data.to_vec();
    for hash_type in hash_types.iter().rev() {
        result = hash_data(&result, *hash_type);
    }
    result
}