@@ -5,8 +5,6 @@ use bincode::enc::write::Writer;
55
66use super :: tag:: LeafTag ;
77use super :: tag:: Tag ;
8- use super :: transform:: ModifyResult ;
9- use super :: transform:: impl_modify_map_collect;
108use crate :: hash:: Hash ;
119use crate :: tree:: Tree ;
1210
@@ -77,6 +75,42 @@ pub enum MerkleProofLeaf {
7775 Read ( Vec < u8 > ) ,
7876}
7977
78+ enum NodeLeaf {
79+ Node ,
80+ Leaf ,
81+ }
82+
83+ /// [`struct@HashState`] is associated with the state of hashing a [`MerkleProof`].
84+ /// We record whether the node is a leaf or an internal node, the index of its parent(
85+ /// see [`MerkleProof::root_hash`] for more details) and the hashes of its children
86+ /// if it's a node and its own hash if its a leaf.
87+ struct HashState {
88+ node_leaf : NodeLeaf ,
89+ parent_index : usize ,
90+ hashes : Vec < Hash > ,
91+ }
92+
93+ impl HashState {
94+ fn new ( node_leaf : NodeLeaf , parent_index : usize , hashes : Vec < Hash > ) -> Self {
95+ Self {
96+ node_leaf,
97+ parent_index,
98+ hashes,
99+ }
100+ }
101+
102+ fn push ( & mut self , hash : Hash ) {
103+ self . hashes . push ( hash) ;
104+ }
105+
106+ fn hash ( & self ) -> Hash {
107+ match self . node_leaf {
108+ NodeLeaf :: Node => Hash :: combine_hashes ( & self . hashes ) ,
109+ NodeLeaf :: Leaf => self . hashes [ 0 ] ,
110+ }
111+ }
112+ }
113+
80114impl MerkleProof {
81115 /// Create a new Merkle proof as a read leaf.
82116 pub fn leaf_read ( data : Vec < u8 > ) -> Self {
@@ -90,18 +124,46 @@ impl MerkleProof {
90124
91125 /// Compute the root hash of the Merkle proof.
92126 pub fn root_hash ( & self ) -> Hash {
93- impl_modify_map_collect (
94- self ,
95- |subtree| match subtree {
96- Tree :: Node ( vec) => ModifyResult :: NodeContinue ( ( ) , vec. iter ( ) . collect ( ) ) ,
97- Tree :: Leaf ( data) => ModifyResult :: LeafStop ( data) ,
98- } ,
99- |leaf| match leaf {
100- MerkleProofLeaf :: Blind ( hash) => * hash,
101- MerkleProofLeaf :: Read ( data) => Hash :: hash_bytes ( data. as_slice ( ) ) ,
102- } ,
103- |( ) , leaves| Hash :: combine_hashes ( leaves) ,
104- )
127+ // The nodes is essentially used as a stack of pairs where the pair is made up
128+ // of a [`MerkleProof`] node and the index of its parent in hash_states.
129+ let mut nodes: Vec < ( & MerkleProof , usize ) > = vec ! [ ( self , 0 ) ] ;
130+ // hash_states contains the hashing state associated with a node.
131+ // See [`HashState`] for more details.
132+ let mut hash_states: Vec < HashState > = vec ! [ ] ;
133+
134+ // Going through all the nodes of the [`MerkleProof`] in a DFS fashion.
135+ while let Some ( ( node, parent_index) ) = nodes. pop ( ) {
136+ match node {
137+ Tree :: Leaf ( MerkleProofLeaf :: Blind ( hash) ) => {
138+ hash_states. push ( HashState :: new ( NodeLeaf :: Leaf , parent_index, vec ! [ * hash] ) ) ;
139+ }
140+ Tree :: Leaf ( MerkleProofLeaf :: Read ( data) ) => {
141+ hash_states. push ( HashState :: new (
142+ NodeLeaf :: Leaf ,
143+ parent_index,
144+ vec ! [ Hash :: hash_bytes( data. as_slice( ) ) ] ,
145+ ) ) ;
146+ }
147+ Tree :: Node ( children) => {
148+ hash_states. push ( HashState :: new ( NodeLeaf :: Node , parent_index, vec ! [ ] ) ) ;
149+ let new_parent_index = hash_states. len ( ) - 1 ;
150+ for child in children. iter ( ) {
151+ nodes. push ( ( child, new_parent_index) ) ;
152+ }
153+ }
154+ }
155+ }
156+
157+ // Pops the hash states and adds them to their parents.
158+ while let Some ( hash_state) = hash_states. pop ( ) {
159+ if hash_states. is_empty ( ) {
160+ // Returns the root hash
161+ return hash_state. hash ( ) ;
162+ }
163+ hash_states[ hash_state. parent_index ] . push ( hash_state. hash ( ) ) ;
164+ }
165+
166+ unreachable ! ( "hash_states can't be an empty vector" ) ;
105167 }
106168}
107169
0 commit comments