@@ -27,19 +27,28 @@ use {
27
27
//
28
28
// - https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack
29
29
// - https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
30
+ //
31
+ // NOTE: We use a NULL prefix for leaf nodes to distinguish them from the empty message (""), while
32
+ // there is no path that allows empty messages this is a safety measure to prevent future
33
+ // vulnerabilities being introduced.
30
34
const LEAF_PREFIX : & [ u8 ] = & [ 0 ] ;
31
35
const NODE_PREFIX : & [ u8 ] = & [ 1 ] ;
36
+ const NULL_PREFIX : & [ u8 ] = & [ 2 ] ;
32
37
33
- macro_rules! hash_leaf {
34
- { $x: ty, $d: expr} => {
35
- <$x as Hasher >:: hashv( & [ LEAF_PREFIX , $d] )
36
- }
38
+ fn hash_leaf < H : Hasher > ( leaf : & [ u8 ] ) -> H :: Hash {
39
+ H :: hashv ( & [ LEAF_PREFIX , leaf] )
37
40
}
38
41
39
- macro_rules! hash_node {
40
- { $x: ty, $l: expr, $r: expr} => {
41
- <$x as Hasher >:: hashv( & [ NODE_PREFIX , $l. as_ref( ) , $r. as_ref( ) ] )
42
- }
42
+ fn hash_node < H : Hasher > ( l : & H :: Hash , r : & H :: Hash ) -> H :: Hash {
43
+ H :: hashv ( & [
44
+ NODE_PREFIX ,
45
+ ( if l <= r { l } else { r } ) . as_ref ( ) ,
46
+ ( if l <= r { r } else { l } ) . as_ref ( ) ,
47
+ ] )
48
+ }
49
+
50
+ fn hash_null < H : Hasher > ( ) -> H :: Hash {
51
+ H :: hashv ( & [ NULL_PREFIX ] )
43
52
}
44
53
45
54
#[ derive( Clone , Default , Debug , PartialEq , Eq , Serialize ) ]
@@ -91,20 +100,20 @@ impl<'a, H: Hasher + 'a> Accumulator<'a> for MerkleAccumulator<H> {
91
100
type Proof = MerklePath < H > ;
92
101
93
102
fn from_set ( items : impl Iterator < Item = & ' a [ u8 ] > ) -> Option < Self > {
94
- let items: Vec < H :: Hash > = items. map ( |i| hash_leaf ! ( H , i) ) . collect ( ) ;
103
+ let items: Vec < H :: Hash > = items. map ( |i| hash_leaf :: < H > ( i) ) . collect ( ) ;
95
104
Self :: new ( & items)
96
105
}
97
106
98
107
fn prove ( & ' a self , item : & [ u8 ] ) -> Option < Self :: Proof > {
99
- let item = hash_leaf ! ( H , item) ;
108
+ let item = hash_leaf :: < H > ( item) ;
100
109
let index = self . nodes . iter ( ) . position ( |i| i == & item) ?;
101
110
Some ( self . find_path ( index) )
102
111
}
103
112
104
113
fn check ( & ' a self , proof : Self :: Proof , item : & [ u8 ] ) -> bool {
105
- let mut current = hash_leaf ! ( H , item) ;
106
- for h in proof. 0 {
107
- current = hash_node ! ( H , current, h ) ;
114
+ let mut current = hash_leaf :: < H > ( item) ;
115
+ for hash in proof. 0 {
116
+ current = hash_node :: < H > ( & current, & hash ) ;
108
117
}
109
118
current == self . root
110
119
}
@@ -123,9 +132,9 @@ impl<H: Hasher> MerkleAccumulator<H> {
123
132
// Filling the leaf hashes
124
133
for i in 0 ..( 1 << depth) {
125
134
if i < items. len ( ) {
126
- tree[ ( 1 << depth) + i] = hash_leaf ! ( H , items[ i] . as_ref( ) ) ;
135
+ tree[ ( 1 << depth) + i] = hash_leaf :: < H > ( items[ i] . as_ref ( ) ) ;
127
136
} else {
128
- tree[ ( 1 << depth) + i] = hash_leaf ! ( H , "" . as_ref ( ) ) ;
137
+ tree[ ( 1 << depth) + i] = hash_null :: < H > ( ) ;
129
138
}
130
139
}
131
140
@@ -135,7 +144,7 @@ impl<H: Hasher> MerkleAccumulator<H> {
135
144
let level_num_nodes = 1 << level;
136
145
for i in 0 ..level_num_nodes {
137
146
let id = ( 1 << level) + i;
138
- tree[ id] = hash_node ! ( H , & tree[ id * 2 ] , & tree[ id * 2 + 1 ] ) ;
147
+ tree[ id] = hash_node :: < H > ( & tree[ id * 2 ] , & tree[ id * 2 + 1 ] ) ;
139
148
}
140
149
}
141
150
0 commit comments