Skip to main content

hotmint_crypto/
hash.rs

1use hotmint_types::{Block, BlockHash};
2
3/// Compute the Blake3 hash of a block's content fields.
4///
5/// Hashes `height || parent_hash || view || proposer || app_hash || payload`,
6/// deliberately excluding `block.hash` to avoid circularity.
7pub fn compute_block_hash(block: &Block) -> BlockHash {
8    block.compute_hash()
9}
10
11#[cfg(test)]
12mod tests {
13    use super::*;
14    use hotmint_types::{Height, ValidatorId, ViewNumber};
15
16    #[test]
17    fn test_hash_deterministic() {
18        let block = Block {
19            height: Height(1),
20            parent_hash: BlockHash::GENESIS,
21            view: ViewNumber(1),
22            proposer: ValidatorId(0),
23            timestamp: 0,
24            payload: b"hello".to_vec(),
25            app_hash: BlockHash::GENESIS,
26            evidence: Vec::new(),
27            hash: BlockHash::GENESIS,
28        };
29        let h1 = compute_block_hash(&block);
30        let h2 = compute_block_hash(&block);
31        assert_eq!(h1, h2);
32        assert!(!h1.is_genesis());
33    }
34
35    #[test]
36    fn test_different_blocks_different_hashes() {
37        let b1 = Block {
38            height: Height(1),
39            parent_hash: BlockHash::GENESIS,
40            view: ViewNumber(1),
41            proposer: ValidatorId(0),
42            timestamp: 0,
43            payload: b"a".to_vec(),
44            app_hash: BlockHash::GENESIS,
45            evidence: Vec::new(),
46            hash: BlockHash::GENESIS,
47        };
48        let b2 = Block {
49            height: Height(1),
50            parent_hash: BlockHash::GENESIS,
51            view: ViewNumber(1),
52            proposer: ValidatorId(0),
53            timestamp: 0,
54            payload: b"b".to_vec(),
55            app_hash: BlockHash::GENESIS,
56            evidence: Vec::new(),
57            hash: BlockHash::GENESIS,
58        };
59        assert_ne!(compute_block_hash(&b1), compute_block_hash(&b2));
60    }
61
62    #[test]
63    fn test_block_compute_hash_matches() {
64        let block = Block {
65            height: Height(1),
66            parent_hash: BlockHash::GENESIS,
67            view: ViewNumber(1),
68            proposer: ValidatorId(0),
69            timestamp: 0,
70            payload: b"hello".to_vec(),
71            app_hash: BlockHash::GENESIS,
72            evidence: Vec::new(),
73            hash: BlockHash::GENESIS,
74        };
75        assert_eq!(compute_block_hash(&block), block.compute_hash());
76    }
77}