9
9
from typing import (
10
10
cast ,
11
11
Hashable ,
12
+ Iterable ,
12
13
NewType ,
13
14
Sequence ,
14
15
)
20
21
reduce ,
21
22
take ,
22
23
)
23
- from eth_hash . auto import (
24
- keccak ,
24
+ from eth . beacon . _utils . hash import (
25
+ hash_eth2 ,
25
26
)
26
27
from eth_typing import (
27
28
Hash32 ,
36
37
37
38
38
39
def get_root (tree : MerkleTree ) -> Hash32 :
39
- """Get the root hash of a Merkle tree."""
40
+ """
41
+ Get the root hash of a Merkle tree.
42
+ """
40
43
return tree [0 ][0 ]
41
44
42
45
43
- def get_branch_indices (node_index : int , depth : int ) -> Sequence [int ]:
44
- """Get the indices of all ancestors up until the root for a node with a given depth."""
46
+ def get_branch_indices (node_index : int , depth : int ) -> Iterable [int ]:
47
+ """
48
+ Get the indices of all ancestors up until the root for a node with a given depth.
49
+ """
45
50
return tuple (take (depth , iterate (lambda index : index // 2 , node_index )))
46
51
47
52
48
- def get_merkle_proof (tree : MerkleTree , item_index : int ) -> Sequence [Hash32 ]:
49
- """Read off the Merkle proof for an item from a Merkle tree."""
53
+ def get_merkle_proof (tree : MerkleTree , item_index : int ) -> Iterable [Hash32 ]:
54
+ """
55
+ Read off the Merkle proof for an item from a Merkle tree.
56
+ """
50
57
if item_index < 0 or item_index >= len (tree [- 1 ]):
51
58
raise ValidationError ("Item index out of range" )
52
59
@@ -64,16 +71,20 @@ def get_merkle_proof(tree: MerkleTree, item_index: int) -> Sequence[Hash32]:
64
71
65
72
66
73
def _calc_parent_hash (left_node : Hash32 , right_node : Hash32 ) -> Hash32 :
67
- """Calculate the parent hash of a node and its sibling."""
68
- return keccak (left_node + right_node )
74
+ """
75
+ Calculate the parent hash of a node and its sibling.
76
+ """
77
+ return hash_eth2 (left_node + right_node )
69
78
70
79
71
80
def verify_merkle_proof (root : Hash32 ,
72
81
item : Hashable ,
73
82
item_index : int ,
74
83
proof : MerkleProof ) -> bool :
75
- """Verify a Merkle proof against a root hash."""
76
- leaf = keccak (item )
84
+ """
85
+ Verify a Merkle proof against a root hash.
86
+ """
87
+ leaf = hash_eth2 (item )
77
88
branch_indices = get_branch_indices (item_index , len (proof ))
78
89
node_orderers = [
79
90
identity if branch_index % 2 == 0 else reversed
@@ -87,28 +98,56 @@ def verify_merkle_proof(root: Hash32,
87
98
return proof_root == root
88
99
89
100
90
- def _hash_layer (layer : Sequence [Hash32 ]) -> Sequence [Hash32 ]:
91
- """Calculate the layer on top of another one."""
92
- return tuple (_calc_parent_hash (left , right ) for left , right in partition (2 , layer ))
101
+ def _hash_layer (layer : Sequence [Hash32 ]) -> Iterable [Hash32 ]:
102
+ """
103
+ Calculate the layer on top of another one.
104
+ """
105
+ return tuple (
106
+ _calc_parent_hash (left , right )
107
+ for left , right in partition (2 , layer )
108
+ )
93
109
94
110
95
111
def calc_merkle_tree (items : Sequence [Hashable ]) -> MerkleTree :
96
- """Calculate the Merkle tree corresponding to a list of items."""
97
- if len (items ) == 0 :
98
- raise ValidationError ("No items given" )
99
- n_layers = math .log2 (len (items )) + 1
112
+ """
113
+ Calculate the Merkle tree corresponding to a list of items.
114
+ """
115
+ leaves = tuple (hash_eth2 (item ) for item in items )
116
+ return calc_merkle_tree_from_leaves (leaves )
117
+
118
+
119
+ def calc_merkle_root (items : Sequence [Hashable ]) -> Hash32 :
120
+ """
121
+ Calculate the Merkle root corresponding to a list of items.
122
+ """
123
+ return get_root (calc_merkle_tree (items ))
124
+
125
+
126
+ def calc_merkle_tree_from_leaves (leaves : Sequence [Hash32 ]) -> MerkleTree :
127
+ if len (leaves ) == 0 :
128
+ raise ValueError ("No leaves given" )
129
+ n_layers = math .log2 (len (leaves )) + 1
100
130
if not n_layers .is_integer ():
101
- raise ValidationError ( "Item number is not a power of two" )
131
+ raise ValueError ( "Number of leaves is not a power of two" )
102
132
n_layers = int (n_layers )
103
-
104
- leaves = tuple (keccak (item ) for item in items )
105
- tree = cast (MerkleTree , tuple (take (n_layers , iterate (_hash_layer , leaves )))[::- 1 ])
133
+ tree = cast (
134
+ MerkleTree ,
135
+ tuple (
136
+ take (
137
+ n_layers ,
138
+ iterate (_hash_layer , leaves ),
139
+ )
140
+ )[::- 1 ]
141
+ )
106
142
if len (tree [0 ]) != 1 :
107
143
raise Exception ("Invariant: There must only be one root" )
108
144
109
145
return tree
110
146
111
147
112
- def calc_merkle_root (items : Sequence [Hashable ]) -> Hash32 :
113
- """Calculate the Merkle root corresponding to a list of items."""
114
- return get_root (calc_merkle_tree (items ))
148
+ def get_merkle_root (leaves : Sequence [Hash32 ]) -> Hash32 :
149
+ """
150
+ Return the Merkle root of the given 32-byte hashes.
151
+ Note: it has to be a full tree, i.e., `len(values)` is an exact power of 2.
152
+ """
153
+ return get_root (calc_merkle_tree_from_leaves (leaves ))
0 commit comments