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  }