github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/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/intfoundation/intchain/common"
    24  	"github.com/intfoundation/intchain/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  }