github.com/amazechain/amc@v0.1.3/common/hash/hash.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package hash
    18  
    19  import (
    20  	"bytes"
    21  	"github.com/amazechain/amc/common/crypto"
    22  	"github.com/amazechain/amc/common/types"
    23  	"github.com/amazechain/amc/internal/avm/rlp"
    24  	"sync"
    25  
    26  	"golang.org/x/crypto/sha3"
    27  )
    28  
    29  // hasherPool holds LegacyKeccak256 hashers for rlpHash.
    30  var HasherPool = sync.Pool{
    31  	New: func() interface{} { return sha3.NewLegacyKeccak256() },
    32  }
    33  
    34  // encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding.
    35  var encodeBufferPool = sync.Pool{
    36  	New: func() interface{} { return new(bytes.Buffer) },
    37  }
    38  
    39  // DerivableList is the input to DeriveSha.
    40  // It is implemented by the 'Transactions' and 'Receipts' types.
    41  // This is internal, do not use these methods.
    42  type DerivableList interface {
    43  	Len() int
    44  	EncodeIndex(int, *bytes.Buffer)
    45  }
    46  
    47  func encodeForDerive(list DerivableList, i int, buf *bytes.Buffer) []byte {
    48  	buf.Reset()
    49  	list.EncodeIndex(i, buf)
    50  	// It's really unfortunate that we need to do perform this copy.
    51  	// StackTrie holds onto the values until Hash is called, so the values
    52  	// written to it must not alias.
    53  	return types.CopyBytes(buf.Bytes())
    54  }
    55  
    56  // DeriveSha creates the tree hashes of transactions and receipts in a block header.
    57  func DeriveSha(list DerivableList) (h types.Hash) {
    58  
    59  	sha := HasherPool.Get().(crypto.KeccakState)
    60  	defer HasherPool.Put(sha)
    61  	sha.Reset()
    62  
    63  	valueBuf := encodeBufferPool.Get().(*bytes.Buffer)
    64  	defer encodeBufferPool.Put(valueBuf)
    65  
    66  	for i := 0; i < list.Len(); i++ {
    67  		value := encodeForDerive(list, i, valueBuf)
    68  		sha.Write(value)
    69  	}
    70  	sha.Read(h[:])
    71  	return h
    72  }
    73  
    74  var (
    75  	// NilHash sum(nil)
    76  	NilHash = types.HexToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
    77  	// EmptyUncleHash rlpHash([]*Header(nil))
    78  	EmptyUncleHash = types.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")
    79  )
    80  
    81  func RlpHash(x interface{}) (h types.Hash) {
    82  	sha := HasherPool.Get().(crypto.KeccakState)
    83  	defer HasherPool.Put(sha)
    84  	sha.Reset()
    85  	rlp.Encode(sha, x)
    86  	sha.Read(h[:])
    87  	return h
    88  }
    89  
    90  // PrefixedRlpHash writes the prefix into the hasher before rlp-encoding x.
    91  // It's used for typed transactions.
    92  func PrefixedRlpHash(prefix byte, x interface{}) (h types.Hash) {
    93  	sha := HasherPool.Get().(crypto.KeccakState)
    94  	defer HasherPool.Put(sha)
    95  	sha.Reset()
    96  	sha.Write([]byte{prefix})
    97  	rlp.Encode(sha, x)
    98  	sha.Read(h[:])
    99  	return h
   100  }
   101  
   102  // Hash defines a function that returns the sha256 checksum of the data passed in.
   103  // https://github.com/ethereum/consensus-specs/blob/v0.9.3/specs/core/0_beacon-chain.md#hash
   104  func Hash(data []byte) [32]byte {
   105  	h, _ := HasherPool.Get().(crypto.KeccakState)
   106  	defer HasherPool.Put(h)
   107  	h.Reset()
   108  
   109  	var b [32]byte
   110  
   111  	// The hash interface never returns an error, for that reason
   112  	// we are not handling the error below. For reference, it is
   113  	// stated here https://golang.org/pkg/hash/#Hash
   114  
   115  	// #nosec G104
   116  	h.Write(data)
   117  	h.Read(b[:])
   118  
   119  	return b
   120  }