@@ -2,25 +2,29 @@ use std_shims::vec::Vec;
2
2
3
3
use crate :: primitives:: keccak256;
4
4
5
- /// Calculates the merkel root of the given tree. Equivalent to `tree_hash` in monero-core.
6
- pub fn merkle_root ( leafs : & [ [ u8 ; 32 ] ] ) -> [ u8 ; 32 ] {
5
+ /// Calculates the Merkle root of the given tree. Equivalent to `tree_hash` in monero-core:
6
+ /// https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a
7
+ /// /src/crypto/tree-hash.c#L62
8
+ ///
9
+ /// # Panics
10
+ /// This function will panic if the tree is empty.
11
+ pub fn merkle_root ( mut leafs : Vec < [ u8 ; 32 ] > ) -> [ u8 ; 32 ] {
7
12
match leafs. len ( ) {
13
+ 0 => panic ! ( "Can't compute Merkle root for empty tree" ) ,
8
14
1 => leafs[ 0 ] ,
9
15
2 => keccak256 ( [ leafs[ 0 ] , leafs[ 1 ] ] . concat ( ) ) ,
10
16
_ => {
11
- let mut hashes = leafs. to_vec ( ) ;
12
-
13
17
// Monero preprocess this so the length is a power of 2
14
18
let mut high_pow_2 = 4 ; // 4 is the lowest value this can be
15
- while high_pow_2 < hashes . len ( ) {
19
+ while high_pow_2 < leafs . len ( ) {
16
20
high_pow_2 *= 2 ;
17
21
}
18
22
let low_pow_2 = high_pow_2 / 2 ;
19
23
20
24
// Merge right-most hashes until we're at the low_pow_2
21
25
{
22
- let overage = hashes . len ( ) - low_pow_2;
23
- let mut rightmost = hashes . drain ( ( low_pow_2 - overage) ..) ;
26
+ let overage = leafs . len ( ) - low_pow_2;
27
+ let mut rightmost = leafs . drain ( ( low_pow_2 - overage) ..) ;
24
28
// This is true since we took overage from beneath and above low_pow_2, taking twice as
25
29
// many elements as overage
26
30
debug_assert_eq ! ( rightmost. len( ) % 2 , 0 ) ;
@@ -32,23 +36,23 @@ pub fn merkle_root(leafs: &[[u8; 32]]) -> [u8; 32] {
32
36
}
33
37
drop ( rightmost) ;
34
38
35
- hashes . extend ( paired_hashes) ;
36
- assert_eq ! ( hashes . len( ) , low_pow_2) ;
39
+ leafs . extend ( paired_hashes) ;
40
+ assert_eq ! ( leafs . len( ) , low_pow_2) ;
37
41
}
38
42
39
43
// Do a traditional pairing off
40
- let mut new_hashes = Vec :: with_capacity ( hashes . len ( ) / 2 ) ;
41
- while hashes . len ( ) > 1 {
44
+ let mut new_hashes = Vec :: with_capacity ( leafs . len ( ) / 2 ) ;
45
+ while leafs . len ( ) > 1 {
42
46
let mut i = 0 ;
43
- while i < hashes . len ( ) {
44
- new_hashes. push ( keccak256 ( [ hashes [ i] , hashes [ i + 1 ] ] . concat ( ) ) ) ;
47
+ while i < leafs . len ( ) {
48
+ new_hashes. push ( keccak256 ( [ leafs [ i] , leafs [ i + 1 ] ] . concat ( ) ) ) ;
45
49
i += 2 ;
46
50
}
47
51
48
- hashes = new_hashes;
49
- new_hashes = Vec :: with_capacity ( hashes . len ( ) / 2 ) ;
52
+ leafs = new_hashes;
53
+ new_hashes = Vec :: with_capacity ( leafs . len ( ) / 2 ) ;
50
54
}
51
- hashes [ 0 ]
55
+ leafs [ 0 ]
52
56
}
53
57
}
54
58
}
0 commit comments