@@ -24,31 +24,22 @@ import (
2424 "golang.org/x/crypto/sha3"
2525)
2626
27- type sliceBuffer []byte
28-
29- func (b * sliceBuffer ) Write (data []byte ) (n int , err error ) {
30- * b = append (* b , data ... )
31- return len (data ), nil
32- }
33-
34- func (b * sliceBuffer ) Reset () {
35- * b = (* b )[:0 ]
36- }
37-
3827// hasher is a type used for the trie Hash operation. A hasher has some
3928// internal preallocated temp space
4029type hasher struct {
4130 sha crypto.KeccakState
42- tmp sliceBuffer
31+ tmp []byte
32+ encbuf rlp.EncoderBuffer
4333 parallel bool // Whether to use paralallel threads when hashing
4434}
4535
4636// hasherPool holds pureHashers
4737var hasherPool = sync.Pool {
4838 New : func () interface {} {
4939 return & hasher {
50- tmp : make (sliceBuffer , 0 , 550 ), // cap is as large as a full FullNode.
51- sha : sha3 .NewLegacyKeccak256 ().(crypto.KeccakState ),
40+ tmp : make ([]byte , 0 , 550 ), // cap is as large as a full fullNode.
41+ sha : sha3 .NewLegacyKeccak256 ().(crypto.KeccakState ),
42+ encbuf : rlp .NewEncoderBuffer (nil ),
5243 }
5344 },
5445}
@@ -153,30 +144,41 @@ func (h *hasher) hashFullNodeChildren(n *fullNode) (collapsed *fullNode, cached
153144// into compact form for RLP encoding.
154145// If the rlp data is smaller than 32 bytes, `nil` is returned.
155146func (h * hasher ) shortnodeToHash (n * shortNode , force bool ) node {
156- h .tmp .Reset ()
157- if err := rlp .Encode (& h .tmp , n ); err != nil {
158- panic ("encode error: " + err .Error ())
159- }
147+ n .encode (h .encbuf )
148+ enc := h .encodedBytes ()
160149
161- if len (h . tmp ) < 32 && ! force {
150+ if len (enc ) < 32 && ! force {
162151 return n // Nodes smaller than 32 bytes are stored inside their parent
163152 }
164- return h .hashData (h . tmp )
153+ return h .hashData (enc )
165154}
166155
167156// shortnodeToHash is used to creates a HashNode from a set of hashNodes, (which
168157// may contain nil values)
169158func (h * hasher ) fullnodeToHash (n * fullNode , force bool ) node {
170- h .tmp .Reset ()
171- // Generate the RLP encoding of the Node
172- if err := n .EncodeRLP (& h .tmp ); err != nil {
173- panic ("encode error: " + err .Error ())
174- }
159+ n .encode (h .encbuf )
160+ enc := h .encodedBytes ()
175161
176- if len (h . tmp ) < 32 && ! force {
162+ if len (enc ) < 32 && ! force {
177163 return n // Nodes smaller than 32 bytes are stored inside their parent
178164 }
179- return h .hashData (h .tmp )
165+ return h .hashData (enc )
166+ }
167+
168+ // encodedBytes returns the result of the last encoding operation on h.encbuf.
169+ // This also resets the encoder buffer.
170+ //
171+ // All node encoding must be done like this:
172+ //
173+ // node.encode(h.encbuf)
174+ // enc := h.encodedBytes()
175+ //
176+ // This convention exists because node.encode can only be inlined/escape-analyzed when
177+ // called on a concrete receiver type.
178+ func (h * hasher ) encodedBytes () []byte {
179+ h .tmp = h .encbuf .AppendToBytes (h .tmp [:0 ])
180+ h .encbuf .Reset (nil )
181+ return h .tmp
180182}
181183
182184// hashData hashes the provided data
0 commit comments