github.com/codysnider/go-ethereum@v1.10.18-0.20220420071915-14f4ae99222a/trie/hasher.go (about)

     1  // Copyright 2019 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  	"sync"
    21  
    22  	"github.com/ethereum/go-ethereum/crypto"
    23  	"github.com/ethereum/go-ethereum/rlp"
    24  	"golang.org/x/crypto/sha3"
    25  )
    26  
    27  // hasher is a type used for the trie Hash operation. A hasher has some
    28  // internal preallocated temp space
    29  type hasher struct {
    30  	sha      crypto.KeccakState
    31  	tmp      []byte
    32  	encbuf   rlp.EncoderBuffer
    33  	parallel bool // Whether to use paralallel threads when hashing
    34  }
    35  
    36  // hasherPool holds pureHashers
    37  var hasherPool = sync.Pool{
    38  	New: func() interface{} {
    39  		return &hasher{
    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),
    43  		}
    44  	},
    45  }
    46  
    47  func newHasher(parallel bool) *hasher {
    48  	h := hasherPool.Get().(*hasher)
    49  	h.parallel = parallel
    50  	return h
    51  }
    52  
    53  func returnHasherToPool(h *hasher) {
    54  	hasherPool.Put(h)
    55  }
    56  
    57  // hash collapses a node down into a hash node, also returning a copy of the
    58  // original node initialized with the computed hash to replace the original one.
    59  func (h *hasher) hash(n node, force bool) (hashed node, cached node) {
    60  	// Return the cached hash if it's available
    61  	if hash, _ := n.cache(); hash != nil {
    62  		return hash, n
    63  	}
    64  	// Trie not processed yet, walk the children
    65  	switch n := n.(type) {
    66  	case *shortNode:
    67  		collapsed, cached := h.hashShortNodeChildren(n)
    68  		hashed := h.shortnodeToHash(collapsed, force)
    69  		// We need to retain the possibly _not_ hashed node, in case it was too
    70  		// small to be hashed
    71  		if hn, ok := hashed.(hashNode); ok {
    72  			cached.flags.hash = hn
    73  		} else {
    74  			cached.flags.hash = nil
    75  		}
    76  		return hashed, cached
    77  	case *fullNode:
    78  		collapsed, cached := h.hashFullNodeChildren(n)
    79  		hashed = h.fullnodeToHash(collapsed, force)
    80  		if hn, ok := hashed.(hashNode); ok {
    81  			cached.flags.hash = hn
    82  		} else {
    83  			cached.flags.hash = nil
    84  		}
    85  		return hashed, cached
    86  	default:
    87  		// Value and hash nodes don't have children so they're left as were
    88  		return n, n
    89  	}
    90  }
    91  
    92  // hashShortNodeChildren collapses the short node. The returned collapsed node
    93  // holds a live reference to the Key, and must not be modified.
    94  // The cached
    95  func (h *hasher) hashShortNodeChildren(n *shortNode) (collapsed, cached *shortNode) {
    96  	// Hash the short node's child, caching the newly hashed subtree
    97  	collapsed, cached = n.copy(), n.copy()
    98  	// Previously, we did copy this one. We don't seem to need to actually
    99  	// do that, since we don't overwrite/reuse keys
   100  	//cached.Key = common.CopyBytes(n.Key)
   101  	collapsed.Key = hexToCompact(n.Key)
   102  	// Unless the child is a valuenode or hashnode, hash it
   103  	switch n.Val.(type) {
   104  	case *fullNode, *shortNode:
   105  		collapsed.Val, cached.Val = h.hash(n.Val, false)
   106  	}
   107  	return collapsed, cached
   108  }
   109  
   110  func (h *hasher) hashFullNodeChildren(n *fullNode) (collapsed *fullNode, cached *fullNode) {
   111  	// Hash the full node's children, caching the newly hashed subtrees
   112  	cached = n.copy()
   113  	collapsed = n.copy()
   114  	if h.parallel {
   115  		var wg sync.WaitGroup
   116  		wg.Add(16)
   117  		for i := 0; i < 16; i++ {
   118  			go func(i int) {
   119  				hasher := newHasher(false)
   120  				if child := n.Children[i]; child != nil {
   121  					collapsed.Children[i], cached.Children[i] = hasher.hash(child, false)
   122  				} else {
   123  					collapsed.Children[i] = nilValueNode
   124  				}
   125  				returnHasherToPool(hasher)
   126  				wg.Done()
   127  			}(i)
   128  		}
   129  		wg.Wait()
   130  	} else {
   131  		for i := 0; i < 16; i++ {
   132  			if child := n.Children[i]; child != nil {
   133  				collapsed.Children[i], cached.Children[i] = h.hash(child, false)
   134  			} else {
   135  				collapsed.Children[i] = nilValueNode
   136  			}
   137  		}
   138  	}
   139  	return collapsed, cached
   140  }
   141  
   142  // shortnodeToHash creates a hashNode from a shortNode. The supplied shortnode
   143  // should have hex-type Key, which will be converted (without modification)
   144  // into compact form for RLP encoding.
   145  // If the rlp data is smaller than 32 bytes, `nil` is returned.
   146  func (h *hasher) shortnodeToHash(n *shortNode, force bool) node {
   147  	n.encode(h.encbuf)
   148  	enc := h.encodedBytes()
   149  
   150  	if len(enc) < 32 && !force {
   151  		return n // Nodes smaller than 32 bytes are stored inside their parent
   152  	}
   153  	return h.hashData(enc)
   154  }
   155  
   156  // shortnodeToHash is used to creates a hashNode from a set of hashNodes, (which
   157  // may contain nil values)
   158  func (h *hasher) fullnodeToHash(n *fullNode, force bool) node {
   159  	n.encode(h.encbuf)
   160  	enc := h.encodedBytes()
   161  
   162  	if len(enc) < 32 && !force {
   163  		return n // Nodes smaller than 32 bytes are stored inside their parent
   164  	}
   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
   182  }
   183  
   184  // hashData hashes the provided data
   185  func (h *hasher) hashData(data []byte) hashNode {
   186  	n := make(hashNode, 32)
   187  	h.sha.Reset()
   188  	h.sha.Write(data)
   189  	h.sha.Read(n)
   190  	return n
   191  }
   192  
   193  // proofHash is used to construct trie proofs, and returns the 'collapsed'
   194  // node (for later RLP encoding) aswell as the hashed node -- unless the
   195  // node is smaller than 32 bytes, in which case it will be returned as is.
   196  // This method does not do anything on value- or hash-nodes.
   197  func (h *hasher) proofHash(original node) (collapsed, hashed node) {
   198  	switch n := original.(type) {
   199  	case *shortNode:
   200  		sn, _ := h.hashShortNodeChildren(n)
   201  		return sn, h.shortnodeToHash(sn, false)
   202  	case *fullNode:
   203  		fn, _ := h.hashFullNodeChildren(n)
   204  		return fn, h.fullnodeToHash(fn, false)
   205  	default:
   206  		// Value and hash nodes don't have children so they're left as were
   207  		return n, n
   208  	}
   209  }