github.com/protolambda/zssz@v0.1.5/htr/hash_tree_root.go (about)

     1  package htr
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"encoding/binary"
     6  	"unsafe"
     7  )
     8  
     9  type MerkleFn interface {
    10  	Combi(a [32]byte, b [32]byte) [32]byte
    11  	MixIn(a [32]byte, i uint64) [32]byte
    12  }
    13  
    14  type HashTreeRootFn func(mfn MerkleFn, pointer unsafe.Pointer) [32]byte
    15  
    16  // Warning, it implements a MerkleFn, but it is preferable to use a cached (Scratchpad) version of the merkle fn.
    17  type HashFn func(input []byte) [32]byte
    18  
    19  // Excluding the full zero bytes32 itself
    20  const zeroHashesLevels = 64
    21  
    22  var ZeroHashes [][32]byte
    23  
    24  // initialize the zero-hashes pre-computed data with the given hash-function.
    25  func InitZeroHashes(hFn HashFn) {
    26  	ZeroHashes = make([][32]byte, zeroHashesLevels+1)
    27  	v := [64]byte{}
    28  	for i := 0; i < zeroHashesLevels; i++ {
    29  		copy(v[:32], ZeroHashes[i][:])
    30  		copy(v[32:], ZeroHashes[i][:])
    31  		ZeroHashes[i+1] = hFn(v[:])
    32  	}
    33  }
    34  
    35  func init() {
    36  	InitZeroHashes(sha256.Sum256)
    37  }
    38  
    39  func (h HashFn) Combi(a [32]byte, b [32]byte) [32]byte {
    40  	v := [64]byte{}
    41  	copy(v[:32], a[:])
    42  	copy(v[32:], b[:])
    43  	return h(v[:])
    44  }
    45  
    46  func (h HashFn) MixIn(a [32]byte, i uint64) [32]byte {
    47  	v := [64]byte{}
    48  	copy(v[:32], a[:])
    49  	copy(v[32:], make([]byte, 32, 32))
    50  	binary.LittleEndian.PutUint64(v[32:], i)
    51  	return h(v[:])
    52  }