watcher/shared/src/core/hasher.rs
2025-09-08 21:18:42 +02:00

81 lines
1.9 KiB
Rust

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(&current_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()
}
}