1- //! Hashing utilities.
1+ //! Hashing utilities using SHA-256.
2+ //!
3+ //! Provides standard cryptographic hashing functions and Merkle tree
4+ //! computation for transaction batches.
25
36use sha2:: { Digest , Sha256 } ;
47
5- /// Hash a block header .
6- pub fn hash_block ( data : & [ u8 ] ) -> [ u8 ; 32 ] {
8+ /// Hash arbitrary data using SHA-256 .
9+ pub fn hash ( data : & [ u8 ] ) -> [ u8 ; 32 ] {
710 let mut hasher = Sha256 :: new ( ) ;
811 hasher. update ( data) ;
912 hasher. finalize ( ) . into ( )
1013}
1114
15+ /// Hash a block header.
16+ pub fn hash_block ( data : & [ u8 ] ) -> [ u8 ; 32 ] {
17+ hash ( data)
18+ }
19+
1220/// Hash a transaction.
1321pub fn hash_tx ( data : & [ u8 ] ) -> [ u8 ; 32 ] {
14- let mut hasher = Sha256 :: new ( ) ;
15- hasher. update ( data) ;
16- hasher. finalize ( ) . into ( )
22+ hash ( data)
1723}
1824
19- /// Compute Merkle root of transaction hashes.
25+ /// Compute Merkle root of transaction hashes using binary tree.
26+ ///
27+ /// Implementation follows Bitcoin's Merkle tree algorithm:
28+ /// - If empty, returns zero hash
29+ /// - If single hash, returns that hash
30+ /// - Otherwise, recursively combines pairs of hashes
31+ /// - If odd number of hashes, duplicates the last one
2032pub fn merkle_root ( hashes : & [ [ u8 ; 32 ] ] ) -> [ u8 ; 32 ] {
2133 if hashes. is_empty ( ) {
2234 return [ 0u8 ; 32 ] ;
@@ -25,14 +37,50 @@ pub fn merkle_root(hashes: &[[u8; 32]]) -> [u8; 32] {
2537 return hashes[ 0 ] ;
2638 }
2739
28- // Simplified Merkle tree (not production-ready)
29- let mut hasher = Sha256 :: new ( ) ;
30- for hash in hashes {
31- hasher. update ( hash) ;
40+ // Recursively build merkle tree
41+ merkle_root_recursive ( hashes)
42+ }
43+
44+ /// Internal recursive merkle tree builder.
45+ fn merkle_root_recursive ( hashes : & [ [ u8 ; 32 ] ] ) -> [ u8 ; 32 ] {
46+ if hashes. len ( ) == 1 {
47+ return hashes[ 0 ] ;
3248 }
49+
50+ let mut next_level = Vec :: new ( ) ;
51+
52+ // Process pairs of hashes
53+ for chunk in hashes. chunks ( 2 ) {
54+ let combined = if chunk. len ( ) == 2 {
55+ // Hash the concatenation of two hashes
56+ hash_pair ( & chunk[ 0 ] , & chunk[ 1 ] )
57+ } else {
58+ // Odd number: duplicate the last hash
59+ hash_pair ( & chunk[ 0 ] , & chunk[ 0 ] )
60+ } ;
61+ next_level. push ( combined) ;
62+ }
63+
64+ merkle_root_recursive ( & next_level)
65+ }
66+
67+ /// Hash a pair of hashes together.
68+ fn hash_pair ( left : & [ u8 ; 32 ] , right : & [ u8 ; 32 ] ) -> [ u8 ; 32 ] {
69+ let mut hasher = Sha256 :: new ( ) ;
70+ hasher. update ( left) ;
71+ hasher. update ( right) ;
3372 hasher. finalize ( ) . into ( )
3473}
3574
75+ /// Compute merkle root from raw transaction data.
76+ ///
77+ /// This is a convenience function that hashes transactions first,
78+ /// then computes the merkle root.
79+ pub fn merkle_root_from_txs ( transactions : & [ & [ u8 ] ] ) -> [ u8 ; 32 ] {
80+ let tx_hashes: Vec < [ u8 ; 32 ] > = transactions. iter ( ) . map ( |tx| hash_tx ( tx) ) . collect ( ) ;
81+ merkle_root ( & tx_hashes)
82+ }
83+
3684#[ cfg( test) ]
3785mod tests {
3886 use super :: * ;
@@ -44,4 +92,103 @@ mod tests {
4492 let hash2 = hash_tx ( data) ;
4593 assert_eq ! ( hash1, hash2) ;
4694 }
95+
96+ #[ test]
97+ fn test_merkle_root_empty ( ) {
98+ let hashes = [ ] ;
99+ let root = merkle_root ( & hashes) ;
100+ assert_eq ! ( root, [ 0u8 ; 32 ] ) ;
101+ }
102+
103+ #[ test]
104+ fn test_merkle_root_single ( ) {
105+ let hash = [ 1u8 ; 32 ] ;
106+ let root = merkle_root ( & [ hash] ) ;
107+ assert_eq ! ( root, hash) ;
108+ }
109+
110+ #[ test]
111+ fn test_merkle_root_two ( ) {
112+ let hash1 = [ 1u8 ; 32 ] ;
113+ let hash2 = [ 2u8 ; 32 ] ;
114+ let root = merkle_root ( & [ hash1, hash2] ) ;
115+
116+ // Should be hash of concatenation
117+ let expected = hash_pair ( & hash1, & hash2) ;
118+ assert_eq ! ( root, expected) ;
119+ }
120+
121+ #[ test]
122+ fn test_merkle_root_four ( ) {
123+ let hashes = [
124+ [ 1u8 ; 32 ] ,
125+ [ 2u8 ; 32 ] ,
126+ [ 3u8 ; 32 ] ,
127+ [ 4u8 ; 32 ] ,
128+ ] ;
129+ let root = merkle_root ( & hashes) ;
130+
131+ // Manually compute expected root
132+ let h12 = hash_pair ( & hashes[ 0 ] , & hashes[ 1 ] ) ;
133+ let h34 = hash_pair ( & hashes[ 2 ] , & hashes[ 3 ] ) ;
134+ let expected = hash_pair ( & h12, & h34) ;
135+
136+ assert_eq ! ( root, expected) ;
137+ }
138+
139+ #[ test]
140+ fn test_merkle_root_odd ( ) {
141+ let hashes = [
142+ [ 1u8 ; 32 ] ,
143+ [ 2u8 ; 32 ] ,
144+ [ 3u8 ; 32 ] ,
145+ ] ;
146+ let root = merkle_root ( & hashes) ;
147+
148+ // Third hash should be duplicated
149+ let h12 = hash_pair ( & hashes[ 0 ] , & hashes[ 1 ] ) ;
150+ let h33 = hash_pair ( & hashes[ 2 ] , & hashes[ 2 ] ) ;
151+ let expected = hash_pair ( & h12, & h33) ;
152+
153+ assert_eq ! ( root, expected) ;
154+ }
155+
156+ #[ test]
157+ fn test_merkle_root_deterministic ( ) {
158+ let hashes = [
159+ [ 1u8 ; 32 ] ,
160+ [ 2u8 ; 32 ] ,
161+ [ 3u8 ; 32 ] ,
162+ [ 4u8 ; 32 ] ,
163+ ] ;
164+
165+ let root1 = merkle_root ( & hashes) ;
166+ let root2 = merkle_root ( & hashes) ;
167+
168+ assert_eq ! ( root1, root2) ;
169+ }
170+
171+ #[ test]
172+ fn test_merkle_root_from_txs ( ) {
173+ let txs = vec ! [ b"tx1" . as_slice( ) , b"tx2" . as_slice( ) , b"tx3" . as_slice( ) ] ;
174+ let root = merkle_root_from_txs ( & txs) ;
175+
176+ // Should match manual calculation
177+ let tx_hashes: Vec < [ u8 ; 32 ] > = txs. iter ( ) . map ( |tx| hash_tx ( tx) ) . collect ( ) ;
178+ let expected = merkle_root ( & tx_hashes) ;
179+
180+ assert_eq ! ( root, expected) ;
181+ }
182+
183+ #[ test]
184+ fn test_different_order_different_root ( ) {
185+ let hashes1 = [ [ 1u8 ; 32 ] , [ 2u8 ; 32 ] ] ;
186+ let hashes2 = [ [ 2u8 ; 32 ] , [ 1u8 ; 32 ] ] ;
187+
188+ let root1 = merkle_root ( & hashes1) ;
189+ let root2 = merkle_root ( & hashes2) ;
190+
191+ // Order matters
192+ assert_ne ! ( root1, root2) ;
193+ }
47194}
0 commit comments