1- // Copyright 2019 The go-ethereum Authors
2- // This file is part of The go-ethereum library.
1+ // Copyright 2016 The go-ethereum Authors
2+ // This file is part of the go-ethereum library.
33//
44// The go-ethereum library is free software: you can redistribute it and/or modify
55// it under the terms of the GNU Lesser General Public License as published by
1212// GNU Lesser General Public License for more details.
1313//
1414// You should have received a copy of the GNU Lesser General Public License
15- // along with The go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
15+ // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
1616
1717package trie
1818
1919import (
20+ "bytes"
21+ "fmt"
2022 "sync"
2123
2224 "github.com/CortexFoundation/CortexTheseus/crypto"
@@ -29,7 +31,7 @@ type hasher struct {
2931 sha crypto.KeccakState
3032 tmp []byte
3133 encbuf rlp.EncoderBuffer
32- parallel bool // Whether to use paralallel threads when hashing
34+ parallel bool // Whether to use parallel threads when hashing
3335}
3436
3537// hasherPool holds pureHashers
@@ -53,119 +55,119 @@ func returnHasherToPool(h *hasher) {
5355 hasherPool .Put (h )
5456}
5557
56- // hash collapses a node down into a hash node, also returning a copy of the
57- // original node initialized with the computed hash to replace the original one.
58- func (h * hasher ) hash (n node , force bool ) node {
58+ // hash collapses a node down into a hash node.
59+ func (h * hasher ) hash (n node , force bool ) []byte {
5960 // Return the cached hash if it's available
6061 if hash , _ := n .cache (); hash != nil {
6162 return hash
6263 }
6364 // Trie not processed yet, walk the children
6465 switch n := n .(type ) {
6566 case * shortNode :
66- collapsed := h .hashShortNodeChildren (n )
67- hashed := h .shortnodeToHash (collapsed , force )
68- // We need to retain the possibly _not_ hashed node, in case it was too
69- // small to be hashed
70- if hn , ok := hashed .(hashNode ); ok {
71- n .flags .hash = hn
72- } else {
73- n .flags .hash = nil
67+ enc := h .encodeShortNode (n )
68+ if len (enc ) < 32 && ! force {
69+ // Nodes smaller than 32 bytes are embedded directly in their parent.
70+ // In such cases, return the raw encoded blob instead of the node hash.
71+ // It's essential to deep-copy the node blob, as the underlying buffer
72+ // of enc will be reused later.
73+ buf := make ([]byte , len (enc ))
74+ copy (buf , enc )
75+ return buf
7476 }
75- return hashed
77+ hash := h .hashData (enc )
78+ n .flags .hash = hash
79+ return hash
80+
7681 case * fullNode :
77- collapsed := h .hashFullNodeChildren (n )
78- hashed := h .fullnodeToHash (collapsed , force )
79- if hn , ok := hashed .(hashNode ); ok {
80- n .flags .hash = hn
81- } else {
82- n .flags .hash = nil
82+ enc := h .encodeFullNode (n )
83+ if len (enc ) < 32 && ! force {
84+ // Nodes smaller than 32 bytes are embedded directly in their parent.
85+ // In such cases, return the raw encoded blob instead of the node hash.
86+ // It's essential to deep-copy the node blob, as the underlying buffer
87+ // of enc will be reused later.
88+ buf := make ([]byte , len (enc ))
89+ copy (buf , enc )
90+ return buf
8391 }
84- return hashed
85- default :
86- // Value and hash nodes don't have children, so they're left as were
92+ hash := h .hashData (enc )
93+ n .flags .hash = hash
94+ return hash
95+
96+ case hashNode :
97+ // hash nodes don't have children, so they're left as were
8798 return n
99+
100+ default :
101+ panic (fmt .Errorf ("unexpected node type, %T" , n ))
88102 }
89103}
90104
91- // hashShortNodeChildren collapses the short node. The returned collapsed node
92- // holds a live reference to the Key, and must not be modified.
93- func (h * hasher ) hashShortNodeChildren (n * shortNode ) * shortNode {
94- // Hash the short node's child, caching the newly hashed subtree
95- //collapsed, cached = n.copy(), n.copy()
96- var collapsed shortNode
97- // Previously, we did copy this one. We don't seem to need to actually
98- // do that, since we don't overwrite/reuse keys
99- // cached.Key = common.CopyBytes(n.Key)
100- collapsed .Key = hexToCompact (n .Key )
101- // Unless the child is a valuenode or hashnode, hash it
102- switch n .Val .(type ) {
103- case * fullNode , * shortNode :
104- collapsed .Val = h .hash (n .Val , false )
105- default :
106- collapsed .Val = n .Val
105+ // encodeShortNode encodes the provided shortNode into the bytes. Notably, the
106+ // return slice must be deep-copied explicitly, otherwise the underlying slice
107+ // will be reused later.
108+ func (h * hasher ) encodeShortNode (n * shortNode ) []byte {
109+ // Encode leaf node
110+ if hasTerm (n .Key ) {
111+ var ln leafNodeEncoder
112+ ln .Key = hexToCompact (n .Key )
113+ ln .Val = n .Val .(valueNode )
114+ ln .encode (h .encbuf )
115+ return h .encodedBytes ()
107116 }
108- return & collapsed
117+ // Encode extension node
118+ var en extNodeEncoder
119+ en .Key = hexToCompact (n .Key )
120+ en .Val = h .hash (n .Val , false )
121+ en .encode (h .encbuf )
122+ return h .encodedBytes ()
123+ }
124+
125+ // fnEncoderPool is the pool for storing shared fullNode encoder to mitigate
126+ // the significant memory allocation overhead.
127+ var fnEncoderPool = sync.Pool {
128+ New : func () interface {} {
129+ var enc fullnodeEncoder
130+ return & enc
131+ },
109132}
110133
111- func (h * hasher ) hashFullNodeChildren (n * fullNode ) * fullNode {
112- // Hash the full node's children, caching the newly hashed subtrees
113- var children [17 ]node
134+ // encodeFullNode encodes the provided fullNode into the bytes. Notably, the
135+ // return slice must be deep-copied explicitly, otherwise the underlying slice
136+ // will be reused later.
137+ func (h * hasher ) encodeFullNode (n * fullNode ) []byte {
138+ fn := fnEncoderPool .Get ().(* fullnodeEncoder )
139+ fn .reset ()
140+
114141 if h .parallel {
115142 var wg sync.WaitGroup
116143 for i := 0 ; i < 16 ; i ++ {
117- if child := n .Children [i ]; child != nil {
118- wg .Add (1 )
119- go func (i int ) {
120- hasher := newHasher (false )
121- children [i ] = hasher .hash (child , false )
122- returnHasherToPool (hasher )
123- wg .Done ()
124- }(i )
125- } else {
126- children [i ] = nilValueNode
144+ if n .Children [i ] == nil {
145+ continue
127146 }
147+ wg .Add (1 )
148+ go func (i int ) {
149+ defer wg .Done ()
150+
151+ h := newHasher (false )
152+ fn .Children [i ] = h .hash (n .Children [i ], false )
153+ returnHasherToPool (h )
154+ }(i )
128155 }
129156 wg .Wait ()
130157 } else {
131158 for i := 0 ; i < 16 ; i ++ {
132159 if child := n .Children [i ]; child != nil {
133- children [i ] = h .hash (child , false )
134- } else {
135- children [i ] = nilValueNode
160+ fn .Children [i ] = h .hash (child , false )
136161 }
137162 }
138163 }
139164 if n .Children [16 ] != nil {
140- children [16 ] = n .Children [16 ]
141- }
142- return & fullNode {flags : nodeFlag {}, Children : children }
143- }
144-
145- // shortnodeToHash creates a hashNode from a shortNode. The supplied shortnode
146- // should have hex-type Key, which will be converted (without modification)
147- // into compact form for RLP encoding.
148- // If the rlp data is smaller than 32 bytes, `nil` is returned.
149- func (h * hasher ) shortnodeToHash (n * shortNode , force bool ) node {
150- n .encode (h .encbuf )
151- enc := h .encodedBytes ()
152-
153- if len (enc ) < 32 && ! force {
154- return n // Nodes smaller than 32 bytes are stored inside their parent
165+ fn .Children [16 ] = n .Children [16 ].(valueNode )
155166 }
156- return h .hashData (enc )
157- }
158-
159- // fullnodeToHash is used to create a hashNode from a fullNode, (which
160- // may contain nil values)
161- func (h * hasher ) fullnodeToHash (n * fullNode , force bool ) node {
162- n .encode (h .encbuf )
163- enc := h .encodedBytes ()
167+ fn .encode (h .encbuf )
168+ fnEncoderPool .Put (fn )
164169
165- if len (enc ) < 32 && ! force {
166- return n // Nodes smaller than 32 bytes are stored inside their parent
167- }
168- return h .hashData (enc )
170+ return h .encodedBytes ()
169171}
170172
171173// encodedBytes returns the result of the last encoding operation on h.encbuf.
@@ -184,9 +186,10 @@ func (h *hasher) encodedBytes() []byte {
184186 return h .tmp
185187}
186188
187- // hashData hashes the provided data
188- func (h * hasher ) hashData (data []byte ) hashNode {
189- n := make (hashNode , 32 )
189+ // hashData hashes the provided data. It is safe to modify the returned slice after
190+ // the function returns.
191+ func (h * hasher ) hashData (data []byte ) []byte {
192+ n := make ([]byte , 32 )
190193 h .sha .Reset ()
191194 h .sha .Write (data )
192195 h .sha .Read (n )
@@ -201,20 +204,17 @@ func (h *hasher) hashDataTo(dst, data []byte) {
201204 h .sha .Read (dst )
202205}
203206
204- // proofHash is used to construct trie proofs, and returns the 'collapsed'
205- // node (for later RLP encoding) aswell as the hashed node -- unless the
206- // node is smaller than 32 bytes, in which case it will be returned as is.
207- // This method does not do anything on value- or hash-nodes .
208- func (h * hasher ) proofHash (original node ) ( collapsed , hashed node ) {
207+ // proofHash is used to construct trie proofs, returning the rlp-encoded node blobs.
208+ // Note, only resolved node (shortNode or fullNode) is expected for proofing.
209+ //
210+ // It is safe to modify the returned slice after the function returns .
211+ func (h * hasher ) proofHash (original node ) [] byte {
209212 switch n := original .(type ) {
210213 case * shortNode :
211- sn := h .hashShortNodeChildren (n )
212- return sn , h .shortnodeToHash (sn , false )
214+ return bytes .Clone (h .encodeShortNode (n ))
213215 case * fullNode :
214- fn := h .hashFullNodeChildren (n )
215- return fn , h .fullnodeToHash (fn , false )
216+ return bytes .Clone (h .encodeFullNode (n ))
216217 default :
217- // Value and hash nodes don't have children, so they're left as were
218- return n , n
218+ panic (fmt .Errorf ("unexpected node type, %T" , original ))
219219 }
220220}
0 commit comments