rootchain_crypto/
hashing.rs1use blake3::Hasher;
2use rootchain_core::types::{BlockHeader, Hash, Transaction};
3
4pub fn hash_bytes(data: &[u8]) -> Hash {
5 Hash::from_bytes(blake3::hash(data).into())
6}
7
8pub fn hash_block_header(header: &BlockHeader) -> Hash {
9 let mut hasher = Hasher::new();
10 hasher.update(&header.height.to_le_bytes());
11 hasher.update(&header.prev_hash.0);
12 hasher.update(&header.merkle_root.0);
13 hasher.update(&header.state_root.0);
14 hasher.update(&header.proposer.0);
15 hasher.update(&header.timestamp.to_le_bytes());
16 Hash::from_bytes(hasher.finalize().into())
17}
18pub fn hash_transaction(tx: &Transaction) -> Hash {
19 let mut hasher = Hasher::new();
20 let tx_type_u8 = match tx.tx_type {
21 rootchain_core::types::TransactionType::Transfer => 0u8,
22 rootchain_core::types::TransactionType::Governance => 1u8,
23 rootchain_core::types::TransactionType::ContractDeploy => 2u8,
24 rootchain_core::types::TransactionType::ContractCall => 3u8,
25 rootchain_core::types::TransactionType::SubmitEquivocationProof => 4u8,
26 };
27 hasher.update(&[tx_type_u8]);
28 hasher.update(&tx.from.0);
29 hasher.update(&tx.to.0);
30 hasher.update(&tx.amount.to_le_bytes());
31 hasher.update(&tx.fee.to_le_bytes());
32 hasher.update(&tx.nonce.to_le_bytes());
33 hasher.update(&tx.payload);
34 Hash::from_bytes(hasher.finalize().into())
35}
36
37pub fn compute_merkle_root(tx_hashes: &[Hash]) -> Hash {
38 if tx_hashes.is_empty() {
39 return Hash::zero();
40 }
41
42 let mut current_level = tx_hashes.to_vec();
43 while current_level.len() > 1 {
44 let mut next_level = Vec::with_capacity(current_level.len().div_ceil(2));
45 for chunk in current_level.chunks(2) {
46 let mut hasher = Hasher::new();
47 if chunk.len() == 2 {
48 hasher.update(&chunk[0].0);
49 hasher.update(&chunk[1].0);
50 } else {
51 hasher.update(&chunk[0].0);
52 hasher.update(&chunk[0].0); }
54 next_level.push(Hash::from_bytes(hasher.finalize().into()));
55 }
56 current_level = next_level;
57 }
58 current_level[0]
59}