github.com/annchain/OG@v0.0.9/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 "github.com/annchain/OG/arefactor/og/types" 21 "hash" 22 "sync" 23 24 "github.com/annchain/OG/common" 25 "golang.org/x/crypto/sha3" 26 //log "github.com/sirupsen/logrus" 27 ) 28 29 type hasher struct { 30 tmp sliceBuffer 31 sha keccakState 32 cachegen uint16 33 cachelimit uint16 34 onleaf LeafCallback 35 } 36 37 // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports 38 // Read to get a variable amount of data from the hash state. Read is faster than Sum 39 // because it doesn't copy the internal state, but also modifies the internal state. 40 type keccakState interface { 41 hash.Hash 42 Read([]byte) (int, error) 43 } 44 45 type sliceBuffer []byte 46 47 func (b *sliceBuffer) Write(data []byte) (n int, err error) { 48 *b = append(*b, data...) 49 return len(data), nil 50 } 51 52 func (b *sliceBuffer) Reset() { 53 *b = (*b)[:0] 54 } 55 56 // hashers live in a global db. 57 var hasherPool = sync.Pool{ 58 New: func() interface{} { 59 return &hasher{ 60 tmp: make(sliceBuffer, 0, 550), // cap is as large as a full fullNode. 61 sha: sha3.NewLegacyKeccak256().(keccakState), 62 } 63 }, 64 } 65 66 func newHasher(cachegen, cachelimit uint16, onleaf LeafCallback) *hasher { 67 h := hasherPool.Get().(*hasher) 68 h.cachegen, h.cachelimit, h.onleaf = cachegen, cachelimit, onleaf 69 return h 70 } 71 72 func returnHasherToPool(h *hasher) { 73 hasherPool.Put(h) 74 } 75 76 // hash collapses a node down into a hash node, also returning a copy of the 77 // original node initialized with the computed hash to replace the original one. 78 func (h *hasher) hash(n Node, db *Database, force bool, preHash bool) (Node, Node, error) { 79 80 //log.Tracef("Panic debug, start hash node: %s", n.String()) 81 82 // If we're not storing the node, just hashing, use available cached data 83 if hash, dirty := n.cache(); hash != nil { 84 if db == nil { 85 return hash, n, nil 86 } 87 if n.canUnload(h.cachegen, h.cachelimit) { 88 // Unload the node from cache. All of its subnodes will have a lower or equal 89 // cache generation number. 90 cacheUnloadCounter.Inc(1) 91 return hash, hash, nil 92 } 93 if !dirty { 94 return hash, n, nil 95 } 96 } 97 // Trie not processed yet or needs storage, walk the children 98 collapsed, cached, err := h.hashChildren(n, db, preHash) 99 if err != nil { 100 return HashNode{}, n, err 101 } 102 hashed, err := h.store(collapsed, db, force, preHash) 103 if err != nil { 104 return HashNode{}, n, err 105 } 106 107 //log.Tracef("Panic debug, hashed the node: %s", hashed.String()) 108 109 // Cache the hash of the node for later reuse and remove 110 // the dirty flag in commit mode. It's fine to assign these values directly 111 // without copying the node first because hashChildren copies it. 112 cachedHash, _ := hashed.(HashNode) 113 switch cn := cached.(type) { 114 case *ShortNode: 115 cn.flags.hash = cachedHash 116 if db != nil { 117 cn.flags.dirty = false 118 } 119 case *FullNode: 120 cn.flags.hash = cachedHash 121 if db != nil { 122 cn.flags.dirty = false 123 } 124 } 125 return hashed, cached, nil 126 } 127 128 // hashChildren replaces the children of a node with their hashes if the encoded 129 // size of the child is larger than a hash, returning the collapsed node as well 130 // as a replacement for the original node with the child hashes cached in. 131 func (h *hasher) hashChildren(original Node, db *Database, preHash bool) (Node, Node, error) { 132 var err error 133 134 switch n := original.(type) { 135 case *ShortNode: 136 // Hash the short node's child, caching the newly hashed subtree 137 collapsed, cached := n.copy(), n.copy() 138 collapsed.Key = hexToCompact(n.Key) 139 cached.Key = common.CopyBytes(n.Key) 140 141 if _, ok := n.Val.(ValueNode); !ok { 142 collapsed.Val, cached.Val, err = h.hash(n.Val, db, false, preHash) 143 if err != nil { 144 return original, original, err 145 } 146 } 147 // OG version of trie use msgp encoding, and it can handle nil node. 148 // Comment these lines 149 // if collapsed.Val == nil { 150 // collapsed.Val = ValueNode(nil) // Ensure that nil children are encoded as empty strings. 151 // } 152 return collapsed, cached, nil 153 154 case *FullNode: 155 // Hash the full node's children, caching the newly hashed subtrees 156 collapsed, cached := n.copy(), n.copy() 157 158 for i := 0; i < 16; i++ { 159 if n.Children[i] != nil { 160 collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false, preHash) 161 if err != nil { 162 return original, original, err 163 } 164 } 165 // OG version of trie use msgp encoding, and it can handle nil node. 166 // Comment these lines 167 // else { 168 // collapsed.Children[i] = ValueNode(nil) // Ensure that nil children are encoded as empty strings. 169 // } 170 } 171 cached.Children[16] = n.Children[16] 172 if collapsed.Children[16] == nil { 173 // OG version of trie use msgp encoding, and it can handle nil node. 174 // Comment these lines 175 // collapsed.Children[16] = ValueNode(nil) 176 } 177 return collapsed, cached, nil 178 179 default: 180 // Value and hash nodes don't have children so they're left as were 181 return n, original, nil 182 } 183 } 184 185 // store hashes the node n and if we have a storage layer specified, it writes 186 // the key/value pair to it and tracks any node->child references as well as any 187 // node->external trie references. 188 func (h *hasher) store(n Node, db *Database, force bool, preHash bool) (Node, error) { 189 // Don't store hashes or empty nodes. 190 if _, isHash := n.(HashNode); n == nil || isHash { 191 return n, nil 192 } 193 // Generate the msgp encoding of the node 194 h.tmp.Reset() 195 data := n.encodeNode() 196 h.tmp = data 197 if len(h.tmp) < 32 && !force { 198 return n, nil // Nodes smaller than 32 bytes are stored inside their parent 199 } 200 // Larger nodes are replaced by their hash and stored in the database. 201 hash, _ := n.cache() 202 if hash == nil { 203 hash = h.makeHashNode(h.tmp) 204 } 205 206 if db != nil && !preHash { 207 // We are pooling the trie nodes into an intermediate memory cache 208 db.lock.Lock() 209 hash := types.BytesToHash(hash) 210 db.insert(hash, h.tmp) 211 // Track all direct parent->child node references 212 switch n := n.(type) { 213 case *ShortNode: 214 if child, ok := n.Val.(HashNode); ok { 215 db.reference(types.BytesToHash(child), hash) 216 } 217 case *FullNode: 218 for i := 0; i < 16; i++ { 219 if child, ok := n.Children[i].(HashNode); ok { 220 db.reference(types.BytesToHash(child), hash) 221 } 222 } 223 } 224 db.lock.Unlock() 225 226 // Track external references from account->storage trie 227 if h.onleaf != nil { 228 switch n := n.(type) { 229 case *ShortNode: 230 if child, ok := n.Val.(ValueNode); ok && child != nil { 231 h.onleaf(child, hash) 232 } 233 case *FullNode: 234 for i := 0; i < 16; i++ { 235 if child, ok := n.Children[i].(ValueNode); ok && child != nil { 236 h.onleaf(child, hash) 237 } 238 } 239 } 240 } 241 } 242 return hash, nil 243 } 244 245 func (h *hasher) makeHashNode(data []byte) HashNode { 246 n := make(HashNode, h.sha.Size()) 247 h.sha.Reset() 248 h.sha.Write(data) 249 h.sha.Read(n) 250 return n 251 }