use sha2::Digest; use sha2::Sha256; use sha3::Keccak256; use super::{BlockHeader, ChainData}; pub struct Hasher {} impl Hasher { pub fn hash_chain_data(data: &ChainData) -> [u8; 32] { let mut hasher = Keccak256::new(); match data { ChainData::Transaction(tx) => { hasher.update(tx.to()); hasher.update(tx.from()); hasher.update(tx.value().to_be_bytes()); hasher.update(tx.data()); } } let res = hasher.finalize(); res.into() } pub fn calculate_next_level(level: &[[u8; 32]]) -> Vec<[u8; 32]> { let mut next_level = Vec::new(); for chunk in level.chunks(2) { let combined_hash = if chunk.len() == 2 { Self::hash_pair(&chunk[0], &chunk[1]) } else { Self::hash_pair(&chunk[0], &chunk[0]) }; next_level.push(combined_hash); } next_level } pub fn calculate_merkle_root(tx_hashes: &[[u8; 32]]) -> [u8; 32] { if tx_hashes.is_empty() { return Self::hash_data(b""); } if tx_hashes.len() == 1 { return tx_hashes[0].clone(); } let mut current_level = tx_hashes.to_vec(); while current_level.len() > 1 { current_level = Self::calculate_next_level(¤t_level); } return current_level[0].clone(); } fn hash_pair(left: &[u8], right: &[u8]) -> [u8; 32] { let mut combined = Vec::with_capacity(left.len() + right.len()); combined.copy_from_slice(left); combined.copy_from_slice(right); Self::hash_data(&combined) } fn hash_data(data: &[u8]) -> [u8; 32] { let mut hasher = Sha256::new(); hasher.update(data); hasher.finalize().into() } pub fn calculate_block_hash(head: &BlockHeader) -> [u8; 32] { let mut hasher = sha2::Sha256::new(); hasher.update(head.nonce().to_be_bytes()); hasher.update(head.previous_hash()); hasher.update(head.timestamp().to_be_bytes()); hasher.update(head.merkle_root()); let res = hasher.finalize(); res.into() } }