@@ -23,7 +23,6 @@ import (
2323
2424 "github.com/ethereum/go-ethereum/common"
2525 "github.com/ethereum/go-ethereum/crypto"
26- "github.com/ethereum/go-ethereum/rlp"
2726 "golang.org/x/crypto/sha3"
2827)
2928
@@ -33,10 +32,9 @@ const leafChanSize = 200
3332
3433// leaf represents a trie leaf value
3534type leaf struct {
36- size int // size of the rlp data (estimate)
37- hash common.Hash // hash of rlp data
38- node node // the node to commit
39- vnodes bool // set to true if the node (possibly) contains a valueNode
35+ size int // size of the rlp data (estimate)
36+ hash common.Hash // hash of rlp data
37+ node node // the node to commit
4038}
4139
4240// committer is a type used for the trie Commit operation. A committer has some
@@ -74,26 +72,20 @@ func returnCommitterToPool(h *committer) {
7472 committerPool .Put (h )
7573}
7674
77- // commitNeeded returns 'false' if the given node is already in sync with db
78- func (c * committer ) commitNeeded (n node ) bool {
79- hash , dirty := n .cache ()
80- return hash == nil || dirty
81- }
82-
8375// commit collapses a node down into a hash node and inserts it into the database
8476func (c * committer ) Commit (n node , db * Database ) (hashNode , error ) {
8577 if db == nil {
8678 return nil , errors .New ("no db provided" )
8779 }
88- h , err := c .commit (n , db , true )
80+ h , err := c .commit (n , db )
8981 if err != nil {
9082 return nil , err
9183 }
9284 return h .(hashNode ), nil
9385}
9486
9587// commit collapses a node down into a hash node and inserts it into the database
96- func (c * committer ) commit (n node , db * Database , force bool ) (node , error ) {
88+ func (c * committer ) commit (n node , db * Database ) (node , error ) {
9789 // if this path is clean, use available cached data
9890 hash , dirty := n .cache ()
9991 if hash != nil && ! dirty {
@@ -104,87 +96,90 @@ func (c *committer) commit(n node, db *Database, force bool) (node, error) {
10496 case * shortNode :
10597 // Commit child
10698 collapsed := cn .copy ()
107- if _ , ok := cn .Val .(valueNode ); ! ok {
108- childV , err := c .commit (cn .Val , db , false )
99+
100+ // If the child is fullnode, recursively commit.
101+ // Otherwise it can only be hashNode or valueNode.
102+ if _ , ok := cn .Val .(* fullNode ); ok {
103+ childV , err := c .commit (cn .Val , db )
109104 if err != nil {
110105 return nil , err
111106 }
112107 collapsed .Val = childV
113108 }
114109 // The key needs to be copied, since we're delivering it to database
115110 collapsed .Key = hexToCompact (cn .Key )
116- hashedNode := c .store (collapsed , db , force , true )
111+ hashedNode := c .store (collapsed , db )
117112 if hn , ok := hashedNode .(hashNode ); ok {
118113 return hn , nil
119114 }
120115 return collapsed , nil
121116 case * fullNode :
122- hashedKids , hasVnodes , err := c .commitChildren (cn , db , force )
117+ hashedKids , err := c .commitChildren (cn , db )
123118 if err != nil {
124119 return nil , err
125120 }
126121 collapsed := cn .copy ()
127122 collapsed .Children = hashedKids
128123
129- hashedNode := c .store (collapsed , db , force , hasVnodes )
124+ hashedNode := c .store (collapsed , db )
130125 if hn , ok := hashedNode .(hashNode ); ok {
131126 return hn , nil
132127 }
133128 return collapsed , nil
134- case valueNode :
135- return c .store (cn , db , force , false ), nil
136- // hashnodes aren't stored
137129 case hashNode :
138130 return cn , nil
131+ default :
132+ // nil, valuenode shouldn't be committed
133+ panic (fmt .Sprintf ("%T: invalid node: %v" , n , n ))
139134 }
140- return hash , nil
141135}
142136
143137// commitChildren commits the children of the given fullnode
144- func (c * committer ) commitChildren (n * fullNode , db * Database , force bool ) ([17 ]node , bool , error ) {
138+ func (c * committer ) commitChildren (n * fullNode , db * Database ) ([17 ]node , error ) {
145139 var children [17 ]node
146- var hasValueNodeChildren = false
147- for i , child := range n .Children {
140+ for i := 0 ; i < 16 ; i ++ {
141+ child := n .Children [ i ]
148142 if child == nil {
149143 continue
150144 }
151- hnode , err := c .commit (child , db , false )
152- if err != nil {
153- return children , false , err
145+ // If it's the hashed child, save the hash value directly.
146+ // Note: it's impossible that the child in range [0, 15]
147+ // is a valuenode.
148+ if hn , ok := child .(hashNode ); ok {
149+ children [i ] = hn
150+ continue
154151 }
155- children [i ] = hnode
156- if _ , ok := hnode .(valueNode ); ok {
157- hasValueNodeChildren = true
152+ // Commit the child recursively and store the "hashed" value.
153+ // Note the returned node can be some embedded nodes, so it's
154+ // possible the type is not hashnode.
155+ hashed , err := c .commit (child , db )
156+ if err != nil {
157+ return children , err
158158 }
159+ children [i ] = hashed
159160 }
160- return children , hasValueNodeChildren , nil
161+ // For the 17th child, it's possible the type is valuenode.
162+ if n .Children [16 ] != nil {
163+ children [16 ] = n .Children [16 ]
164+ }
165+ return children , nil
161166}
162167
163168// store hashes the node n and if we have a storage layer specified, it writes
164169// the key/value pair to it and tracks any node->child references as well as any
165170// node->external trie references.
166- func (c * committer ) store (n node , db * Database , force bool , hasVnodeChildren bool ) node {
171+ func (c * committer ) store (n node , db * Database ) node {
167172 // Larger nodes are replaced by their hash and stored in the database.
168173 var (
169174 hash , _ = n .cache ()
170175 size int
171176 )
172177 if hash == nil {
173- if vn , ok := n .(valueNode ); ok {
174- c .tmp .Reset ()
175- if err := rlp .Encode (& c .tmp , vn ); err != nil {
176- panic ("encode error: " + err .Error ())
177- }
178- size = len (c .tmp )
179- if size < 32 && ! force {
180- return n // Nodes smaller than 32 bytes are stored inside their parent
181- }
182- hash = c .makeHashNode (c .tmp )
183- } else {
184- // This was not generated - must be a small node stored in the parent
185- // No need to do anything here
186- return n
187- }
178+ // This was not generated - must be a small node stored in the parent.
179+ // In theory we should apply the leafCall here if it's not nil(embedded
180+ // node usually contains value). But small value(less than 32bytes) is
181+ // not our target.
182+ return n
188183 } else {
189184 // We have the hash already, estimate the RLP encoding-size of the node.
190185 // The size is used for mem tracking, does not need to be exact
@@ -194,10 +189,9 @@ func (c *committer) store(n node, db *Database, force bool, hasVnodeChildren boo
194189 // The leaf channel will be active only when there an active leaf-callback
195190 if c .leafCh != nil {
196191 c .leafCh <- & leaf {
197- size : size ,
198- hash : common .BytesToHash (hash ),
199- node : n ,
200- vnodes : hasVnodeChildren ,
192+ size : size ,
193+ hash : common .BytesToHash (hash ),
194+ node : n ,
201195 }
202196 } else if db != nil {
203197 // No leaf-callback used, but there's still a database. Do serial
@@ -209,30 +203,30 @@ func (c *committer) store(n node, db *Database, force bool, hasVnodeChildren boo
209203 return hash
210204}
211205
212- // commitLoop does the actual insert + leaf callback for nodes
206+ // commitLoop does the actual insert + leaf callback for nodes.
213207func (c * committer ) commitLoop (db * Database ) {
214208 for item := range c .leafCh {
215209 var (
216- hash = item .hash
217- size = item .size
218- n = item .node
219- hasVnodes = item .vnodes
210+ hash = item .hash
211+ size = item .size
212+ n = item .node
220213 )
221214 // We are pooling the trie nodes into an intermediate memory cache
222215 db .lock .Lock ()
223216 db .insert (hash , size , n )
224217 db .lock .Unlock ()
225- if c .onleaf != nil && hasVnodes {
218+
219+ if c .onleaf != nil {
226220 switch n := n .(type ) {
227221 case * shortNode :
228222 if child , ok := n .Val .(valueNode ); ok {
229223 c .onleaf (nil , child , hash )
230224 }
231225 case * fullNode :
232- for i := 0 ; i < 16 ; i ++ {
233- if child , ok := n . Children [ i ].( valueNode ); ok {
234- c . onleaf ( nil , child , hash )
235- }
226+ // For children in range [0, 15], it's impossible
227+ // to contain valuenode. Only check the 17th child.
228+ if n . Children [ 16 ] != nil {
229+ c . onleaf ( nil , n . Children [ 16 ].( valueNode ), hash )
236230 }
237231 }
238232 }
0 commit comments