erigon-pulse/cl/merkle_tree/merkle_root.go

59 lines
1.5 KiB
Go

package merkle_tree
import (
"errors"
"fmt"
"github.com/ledgerwatch/erigon/cl/utils"
"github.com/prysmaticlabs/gohashtree"
)
// merkleizeTrieLeaves returns intermediate roots of given leaves.
func merkleizeTrieLeaves(leaves [][32]byte) ([32]byte, error) {
for len(leaves) > 1 {
if !utils.IsPowerOf2(uint64(len(leaves))) {
return [32]byte{}, fmt.Errorf("hash layer is a non power of 2: %d", len(leaves))
}
layer := make([][32]byte, len(leaves)/2)
if err := gohashtree.Hash(layer, leaves); err != nil {
return [32]byte{}, err
}
leaves = layer
}
return leaves[0], nil
}
func MerkleRootFromLeaves(leaves [][32]byte) ([32]byte, error) {
if len(leaves) == 0 {
return [32]byte{}, errors.New("zero leaves provided")
}
if len(leaves) == 1 {
return leaves[0], nil
}
hashLayer := leaves
return merkleizeTrieLeaves(hashLayer)
}
// getDepth returns the depth of a merkle tree with a given number of nodes.
// The depth is defined as the number of levels in the tree, with the root
// node at level 0 and each child node at a level one greater than its parent.
// If the number of nodes is less than or equal to 1, the depth is 0.
func getDepth(v uint64) uint8 {
// If there are 0 or 1 nodes, the depth is 0.
if v <= 1 {
return 0
}
// Initialize the depth to 0.
depth := uint8(0)
// Divide the number of nodes by 2 until it is less than or equal to 1.
// The number of iterations is the depth of the tree.
for v > 1 {
v >>= 1
depth++
}
return depth
}