github.com/vay007/go-ethereum@v1.9.7/trie/hasher.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // 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/>. 16 17 package trie 18 19 import ( 20 "hash" 21 "sync" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/rlp" 25 "golang.org/x/crypto/sha3" 26 ) 27 28 type hasher struct { 29 tmp sliceBuffer 30 sha keccakState 31 onleaf LeafCallback 32 } 33 34 // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports 35 // Read to get a variable amount of data from the hash state. Read is faster than Sum 36 // because it doesn't copy the internal state, but also modifies the internal state. 37 type keccakState interface { 38 hash.Hash 39 Read([]byte) (int, error) 40 } 41 42 type sliceBuffer []byte 43 44 func (b *sliceBuffer) Write(data []byte) (n int, err error) { 45 *b = append(*b, data...) 46 return len(data), nil 47 } 48 49 func (b *sliceBuffer) Reset() { 50 *b = (*b)[:0] 51 } 52 53 // hashers live in a global db. 54 var hasherPool = sync.Pool{ 55 New: func() interface{} { 56 return &hasher{ 57 tmp: make(sliceBuffer, 0, 550), // cap is as large as a full fullNode. 58 sha: sha3.NewLegacyKeccak256().(keccakState), 59 } 60 }, 61 } 62 63 func newHasher(onleaf LeafCallback) *hasher { 64 h := hasherPool.Get().(*hasher) 65 h.onleaf = onleaf 66 return h 67 } 68 69 func returnHasherToPool(h *hasher) { 70 hasherPool.Put(h) 71 } 72 73 // hash collapses a node down into a hash node, also returning a copy of the 74 // original node initialized with the computed hash to replace the original one. 75 func (h *hasher) hash(n node, db *Database, force bool) (node, node, error) { 76 // If we're not storing the node, just hashing, use available cached data 77 if hash, dirty := n.cache(); hash != nil { 78 if db == nil { 79 return hash, n, nil 80 } 81 if !dirty { 82 switch n.(type) { 83 case *fullNode, *shortNode: 84 return hash, hash, nil 85 default: 86 return hash, n, nil 87 } 88 } 89 } 90 // Trie not processed yet or needs storage, walk the children 91 collapsed, cached, err := h.hashChildren(n, db) 92 if err != nil { 93 return hashNode{}, n, err 94 } 95 hashed, err := h.store(collapsed, db, force) 96 if err != nil { 97 return hashNode{}, n, err 98 } 99 // Cache the hash of the node for later reuse and remove 100 // the dirty flag in commit mode. It's fine to assign these values directly 101 // without copying the node first because hashChildren copies it. 102 cachedHash, _ := hashed.(hashNode) 103 switch cn := cached.(type) { 104 case *shortNode: 105 cn.flags.hash = cachedHash 106 if db != nil { 107 cn.flags.dirty = false 108 } 109 case *fullNode: 110 cn.flags.hash = cachedHash 111 if db != nil { 112 cn.flags.dirty = false 113 } 114 } 115 return hashed, cached, nil 116 } 117 118 // hashChildren replaces the children of a node with their hashes if the encoded 119 // size of the child is larger than a hash, returning the collapsed node as well 120 // as a replacement for the original node with the child hashes cached in. 121 func (h *hasher) hashChildren(original node, db *Database) (node, node, error) { 122 var err error 123 124 switch n := original.(type) { 125 case *shortNode: 126 // Hash the short node's child, caching the newly hashed subtree 127 collapsed, cached := n.copy(), n.copy() 128 collapsed.Key = hexToCompact(n.Key) 129 cached.Key = common.CopyBytes(n.Key) 130 131 if _, ok := n.Val.(valueNode); !ok { 132 collapsed.Val, cached.Val, err = h.hash(n.Val, db, false) 133 if err != nil { 134 return original, original, err 135 } 136 } 137 return collapsed, cached, nil 138 139 case *fullNode: 140 // Hash the full node's children, caching the newly hashed subtrees 141 collapsed, cached := n.copy(), n.copy() 142 143 for i := 0; i < 16; i++ { 144 if n.Children[i] != nil { 145 collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false) 146 if err != nil { 147 return original, original, err 148 } 149 } 150 } 151 cached.Children[16] = n.Children[16] 152 return collapsed, cached, nil 153 154 default: 155 // Value and hash nodes don't have children so they're left as were 156 return n, original, nil 157 } 158 } 159 160 // store hashes the node n and if we have a storage layer specified, it writes 161 // the key/value pair to it and tracks any node->child references as well as any 162 // node->external trie references. 163 func (h *hasher) store(n node, db *Database, force bool) (node, error) { 164 // Don't store hashes or empty nodes. 165 if _, isHash := n.(hashNode); n == nil || isHash { 166 return n, nil 167 } 168 // Generate the RLP encoding of the node 169 h.tmp.Reset() 170 if err := rlp.Encode(&h.tmp, n); err != nil { 171 panic("encode error: " + err.Error()) 172 } 173 if len(h.tmp) < 32 && !force { 174 return n, nil // Nodes smaller than 32 bytes are stored inside their parent 175 } 176 // Larger nodes are replaced by their hash and stored in the database. 177 hash, _ := n.cache() 178 if hash == nil { 179 hash = h.makeHashNode(h.tmp) 180 } 181 182 if db != nil { 183 // We are pooling the trie nodes into an intermediate memory cache 184 hash := common.BytesToHash(hash) 185 186 db.lock.Lock() 187 db.insert(hash, h.tmp, n) 188 db.lock.Unlock() 189 190 // Track external references from account->storage trie 191 if h.onleaf != nil { 192 switch n := n.(type) { 193 case *shortNode: 194 if child, ok := n.Val.(valueNode); ok { 195 h.onleaf(child, hash) 196 } 197 case *fullNode: 198 for i := 0; i < 16; i++ { 199 if child, ok := n.Children[i].(valueNode); ok { 200 h.onleaf(child, hash) 201 } 202 } 203 } 204 } 205 } 206 return hash, nil 207 } 208 209 func (h *hasher) makeHashNode(data []byte) hashNode { 210 n := make(hashNode, h.sha.Size()) 211 h.sha.Reset() 212 h.sha.Write(data) 213 h.sha.Read(n) 214 return n 215 }