81 lines
1.9 KiB
Rust
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(¤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()
|
|
}
|
|
}
|