package ssz import ( "encoding/binary" "github.com/pkg/errors" "github.com/prysmaticlabs/gohashtree" "github.com/prysmaticlabs/prysm/v5/container/trie" "github.com/prysmaticlabs/prysm/v5/crypto/hash/htr" ) var errInvalidNilSlice = errors.New("invalid empty slice") const ( mask0 = ^uint64((1 << (1 << iota)) - 1) mask1 mask2 mask3 mask4 mask5 ) const ( bit0 = uint8(1 << iota) bit1 bit2 bit3 bit4 bit5 ) // Depth retrieves the appropriate depth for the provided trie size. func Depth(v uint64) (out uint8) { // bitmagic: binary search through a uint32, offset down by 1 to not round powers of 2 up. // Then adding 1 to it to not get the index of the first bit, but the length of the bits (depth of tree) // Zero is a special case, it has a 0 depth. // Example: // (in out): (0 0), (1 0), (2 1), (3 2), (4 2), (5 3), (6 3), (7 3), (8 3), (9 4) if v <= 1 { return 0 } v-- if v&mask5 != 0 { v >>= bit5 out |= bit5 } if v&mask4 != 0 { v >>= bit4 out |= bit4 } if v&mask3 != 0 { v >>= bit3 out |= bit3 } if v&mask2 != 0 { v >>= bit2 out |= bit2 } if v&mask1 != 0 { v >>= bit1 out |= bit1 } if v&mask0 != 0 { out |= bit0 } out++ return } // Merkleize with log(N) space allocation func Merkleize(hasher Hasher, count, limit uint64, leaf func(i uint64) []byte) (out [32]byte) { if count > limit { panic("merkleizing list that is too large, over limit") } if limit == 0 { return } if limit == 1 { if count == 1 { copy(out[:], leaf(0)) } return } depth := Depth(count) limitDepth := Depth(limit) tmp := make([][32]byte, limitDepth+1) j := uint8(0) var hArr [32]byte h := hArr[:] merge := func(i uint64) { // merge back up from bottom to top, as far as we can for j = 0; ; j++ { // stop merging when we are in the left side of the next combi if i&(uint64(1)<