Skip to content

Commit

Permalink
chore(ssz): Make generics a little less nasty
Browse files Browse the repository at this point in the history
  • Loading branch information
itsdevbear committed Jun 25, 2024
1 parent 4869f6e commit 35c6024
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 67 deletions.
11 changes: 5 additions & 6 deletions mod/da/pkg/blob/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,10 @@ func (f *SidecarFactory[BeaconBlockT, BeaconBlockBodyT]) BuildBlockBodyProof(
return nil, err
}

tree, err := merkle.NewTreeWithMaxLeaves[
[32]byte, [32]byte,
](membersRoots, body.Length()-1)
tree, err := merkle.NewTreeWithMaxLeaves[[32]byte](
membersRoots,
body.Length()-1,
)
if err != nil {
return nil, err
}
Expand All @@ -159,9 +160,7 @@ func (f *SidecarFactory[BeaconBlockT, BeaconBlockBodyT]) BuildCommitmentProof(
startTime := time.Now()
defer f.metrics.measureBuildCommitmentProofDuration(startTime)

bodyTree, err := merkle.NewTreeWithMaxLeaves[
[32]byte, [32]byte,
](
bodyTree, err := merkle.NewTreeWithMaxLeaves[[32]byte](
body.GetBlobKzgCommitments().Leafify(),
f.chainSpec.MaxBlobCommitmentsPerBlock(),
)
Expand Down
24 changes: 12 additions & 12 deletions mod/primitives/pkg/merkle/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ const (
)

// NewRootWithMaxLeaves constructs a Merkle tree root from a set of.
func NewRootWithMaxLeaves[U64T U64[U64T], LeafT, RootT ~[32]byte](
leaves []LeafT,
func NewRootWithMaxLeaves[U64T U64[U64T], RootT ~[32]byte](
leaves []RootT,
length uint64,
) (RootT, error) {
return NewRootWithDepth[LeafT, RootT](
return NewRootWithDepth[RootT](
leaves, math.U64(length).NextPowerOfTwo().ILog2Ceil(),
)
}

// NewRootWithDepth constructs a Merkle tree root from a set of leaves.
func NewRootWithDepth[LeafT, RootT ~[32]byte](
leaves []LeafT,
func NewRootWithDepth[RootT ~[32]byte](
leaves []RootT,
depth uint8,
) (RootT, error) {
// Return zerohash at depth
Expand All @@ -70,23 +70,23 @@ func NewRootWithDepth[LeafT, RootT ~[32]byte](
leaves = append(leaves, zerohash)
}
var err error
leaves, err = BuildParentTreeRoots[LeafT, LeafT](leaves)
leaves, err = BuildParentTreeRoots[RootT](leaves)
if err != nil {
return zero.Hashes[depth], err
}
}
if len(leaves) != 1 {
return zero.Hashes[depth], nil
}
return RootT(leaves[0]), nil
return leaves[0], nil
}

// BuildParentTreeRoots calls BuildParentTreeRootsWithNRoutines with the
// number of routines set to runtime.GOMAXPROCS(0)-1.
func BuildParentTreeRoots[LeafT, RootT ~[32]byte](
inputList []LeafT,
func BuildParentTreeRoots[RootT ~[32]byte](
inputList []RootT,
) ([]RootT, error) {
return BuildParentTreeRootsWithNRoutines[LeafT, RootT](
return BuildParentTreeRootsWithNRoutines[RootT](
inputList, runtime.GOMAXPROCS(0)-1,
)
}
Expand All @@ -95,8 +95,8 @@ func BuildParentTreeRoots[LeafT, RootT ~[32]byte](
// using CPU-specific vector instructions and parallel processing. This
// method adapts to the host machine's hardware for potential performance
// gains over sequential hashing.
func BuildParentTreeRootsWithNRoutines[LeafT, RootT ~[32]byte](
inputList []LeafT, n int,
func BuildParentTreeRootsWithNRoutines[RootT ~[32]byte](
inputList []RootT, n int,
) ([]RootT, error) {
// Validate input list length.
inputLength := len(inputList)
Expand Down
8 changes: 4 additions & 4 deletions mod/primitives/pkg/merkle/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ func Test_HashTreeRootEqualInputs(t *testing.T) {
go func() {
defer wg.Done()
var tempHash [][32]byte
tempHash, err = merkle.BuildParentTreeRoots[[32]byte, [32]byte](
tempHash, err = merkle.BuildParentTreeRoots[[32]byte](
largeSlice,
)
copy(hash1, tempHash)
}()
wg.Wait()
require.NoError(t, err)

hash2, err = merkle.BuildParentTreeRoots[[32]byte, [32]byte](
hash2, err = merkle.BuildParentTreeRoots[[32]byte](
secondLargeSlice,
)
require.NoError(t, err)
Expand Down Expand Up @@ -155,7 +155,7 @@ func TestBuildParentTreeRootsWithNRoutines_DivisionByZero(t *testing.T) {
// Attempt to call BuildParentTreeRootsWithNRoutines with n set to 0
// to test handling of division by zero.
inputList := make([][32]byte, 10) // Arbitrary size larger than 0
_, err := merkle.BuildParentTreeRootsWithNRoutines[[32]byte, [32]byte](
_, err := merkle.BuildParentTreeRootsWithNRoutines[[32]byte](
inputList,
0,
)
Expand Down Expand Up @@ -183,7 +183,7 @@ func requireGoHashTreeEquivalence(
go func() {
defer wg.Done()
var err error
output, err = merkle.BuildParentTreeRootsWithNRoutines[[32]byte, [32]byte](
output, err = merkle.BuildParentTreeRootsWithNRoutines[[32]byte](
inputList,
numRoutines,
)
Expand Down
50 changes: 25 additions & 25 deletions mod/primitives/pkg/merkle/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,48 +36,48 @@ const (
MaxTreeDepth = 62
)

// Tree[LeafT, RootT] implements a Merkle tree that has been optimized to
// Tree[RootT] implements a Merkle tree that has been optimized to
// handle leaves that are 32 bytes in size.
type Tree[LeafT, RootT ~[32]byte] struct {
type Tree[RootT ~[32]byte] struct {
depth uint8
branches [][]LeafT
leaves []LeafT
branches [][]RootT
leaves []RootT
}

// NewTreeFromLeaves constructs a Merkle tree, with the minimum
// depth required to support the number of leaves.
func NewTreeFromLeaves[LeafT, RootT ~[32]byte](
leaves []LeafT,
) (*Tree[LeafT, RootT], error) {
return NewTreeFromLeavesWithDepth[LeafT, RootT](
func NewTreeFromLeaves[RootT ~[32]byte](
leaves []RootT,
) (*Tree[RootT], error) {
return NewTreeFromLeavesWithDepth[RootT](
leaves,
math.U64(len(leaves)).NextPowerOfTwo().ILog2Ceil(),
)
}

// NewTreeWithMaxLeaves constructs a Merkle tree with a maximum number of
// leaves.
func NewTreeWithMaxLeaves[LeafT, RootT ~[32]byte](
leaves []LeafT,
func NewTreeWithMaxLeaves[RootT ~[32]byte](
leaves []RootT,
maxLeaves uint64,
) (*Tree[LeafT, RootT], error) {
return NewTreeFromLeavesWithDepth[LeafT, RootT](
) (*Tree[RootT], error) {
return NewTreeFromLeavesWithDepth[RootT](
leaves,
math.U64(maxLeaves).NextPowerOfTwo().ILog2Ceil(),
)
}

// NewTreeFromLeaves constructs a Merkle tree from a sequence of byte slices.
// It will fill the tree with zero hashes to create the required depth.
func NewTreeFromLeavesWithDepth[LeafT, RootT ~[32]byte](
leaves []LeafT,
func NewTreeFromLeavesWithDepth[RootT ~[32]byte](
leaves []RootT,
depth uint8,
) (*Tree[LeafT, RootT], error) {
) (*Tree[RootT], error) {
if err := verifySufficientDepth(len(leaves), depth); err != nil {
return &Tree[LeafT, RootT]{}, err
return &Tree[RootT]{}, err
}

layers := make([][]LeafT, depth+1)
layers := make([][]RootT, depth+1)
layers[0] = leaves

var err error
Expand All @@ -86,21 +86,21 @@ func NewTreeFromLeavesWithDepth[LeafT, RootT ~[32]byte](
if len(currentLayer)%2 == 1 {
currentLayer = append(currentLayer, zero.Hashes[d])
}
layers[d+1], err = BuildParentTreeRoots[LeafT, LeafT](currentLayer)
layers[d+1], err = BuildParentTreeRoots[RootT](currentLayer)
if err != nil {
return &Tree[LeafT, RootT]{}, err
return &Tree[RootT]{}, err
}
}

return &Tree[LeafT, RootT]{
return &Tree[RootT]{
branches: layers,
leaves: leaves,
depth: depth,
}, nil
}

// Insert an item into the tree.
func (m *Tree[LeafT, RootT]) Insert(item [32]byte, index int) error {
func (m *Tree[RootT]) Insert(item [32]byte, index int) error {
if index < 0 {
return errors.Wrap(ErrNegativeIndex, fmt.Sprintf("index: %d", index))
}
Expand Down Expand Up @@ -159,13 +159,13 @@ func (m *Tree[LeafT, RootT]) Insert(item [32]byte, index int) error {
}

// Root returns the root of the Merkle tree.
func (m *Tree[LeafT, RootT]) Root() [32]byte {
func (m *Tree[RootT]) Root() [32]byte {
return m.branches[len(m.branches)-1][0]
}

// HashTreeRoot returns the Root of the Merkle tree with the
// number of leaves mixed in.
func (m *Tree[LeafT, RootT]) HashTreeRoot() ([32]byte, error) {
func (m *Tree[RootT]) HashTreeRoot() ([32]byte, error) {
numItems := uint64(len(m.leaves))
if len(m.leaves) == 1 &&
m.leaves[0] == zero.Hashes[0] {
Expand All @@ -175,7 +175,7 @@ func (m *Tree[LeafT, RootT]) HashTreeRoot() ([32]byte, error) {
}

// MerkleProof computes a proof from a tree's branches using a Merkle index.
func (m *Tree[LeafT, RootT]) MerkleProof(leafIndex uint64) ([][32]byte, error) {
func (m *Tree[RootT]) MerkleProof(leafIndex uint64) ([][32]byte, error) {
numLeaves := uint64(len(m.branches[0]))
if leafIndex >= numLeaves {
return nil, errors.Newf(
Expand All @@ -198,7 +198,7 @@ func (m *Tree[LeafT, RootT]) MerkleProof(leafIndex uint64) ([][32]byte, error) {

// MerkleProofWithMixin computes a proof from a tree's branches using a Merkle
// index.
func (m *Tree[LeafT, RootT]) MerkleProofWithMixin(
func (m *Tree[RootT]) MerkleProofWithMixin(
index uint64,
) ([][32]byte, error) {
proof, err := m.MerkleProof(index)
Expand Down
2 changes: 1 addition & 1 deletion mod/primitives/pkg/merkle/tree_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func FuzzTree_IsValidMerkleBranch(f *testing.F) {
byteslib.ToBytes32([]byte("G")),
byteslib.ToBytes32([]byte("H")),
}
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
depth,
)
Expand Down
22 changes: 11 additions & 11 deletions mod/primitives/pkg/merkle/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const (
)

func TestNewTreeFromLeavesWithDepth_NoItemsProvided(t *testing.T) {
_, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
_, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
nil,
treeDepth,
)
Expand All @@ -52,7 +52,7 @@ func TestNewTreeFromLeavesWithDepth_DepthSupport(t *testing.T) {
byteslib.ToBytes32([]byte("GGGGGGG")),
}
// Supported depth
m1, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
m1, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
merkle.MaxTreeDepth,
)
Expand All @@ -61,7 +61,7 @@ func TestNewTreeFromLeavesWithDepth_DepthSupport(t *testing.T) {
require.NoError(t, err)
require.Len(t, proof, int(merkle.MaxTreeDepth)+1)
// Unsupported depth
_, err = merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
_, err = merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
merkle.MaxTreeDepth+1,
)
Expand All @@ -79,7 +79,7 @@ func TestMerkleTree_IsValidMerkleBranch(t *testing.T) {
byteslib.ToBytes32([]byte("G")),
byteslib.ToBytes32([]byte("H")),
}
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth,
)
Expand Down Expand Up @@ -131,7 +131,7 @@ func TestMerkleTree_VerifyProof(t *testing.T) {
byteslib.ToBytes32([]byte("H")),
}

m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth,
)
Expand Down Expand Up @@ -173,7 +173,7 @@ func TestMerkleTree_NegativeIndexes(t *testing.T) {
byteslib.ToBytes32([]byte("G")),
byteslib.ToBytes32([]byte("H")),
}
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth,
)
Expand All @@ -189,7 +189,7 @@ func TestMerkleTree_VerifyProof_TrieUpdated(t *testing.T) {
{3},
{4},
}
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth+1,
)
Expand Down Expand Up @@ -236,7 +236,7 @@ func BenchmarkNewTreeFromLeavesWithDepth(b *testing.B) {
byteslib.ToBytes32([]byte("GGGGGGG")),
}
for i := 0; i < b.N; i++ {
_, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
_, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth,
)
Expand All @@ -251,7 +251,7 @@ func BenchmarkInsertTrie_Optimized(b *testing.B) {
for i := range numDeposits {
items[i] = byteslib.ToBytes32([]byte(strconv.Itoa(i)))
}
tr, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
tr, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth,
)
Expand All @@ -275,7 +275,7 @@ func BenchmarkGenerateProof(b *testing.B) {
byteslib.ToBytes32([]byte("FFFFFF")),
byteslib.ToBytes32([]byte("GGGGGGG")),
}
goodTree, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
goodTree, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth,
)
Expand All @@ -299,7 +299,7 @@ func BenchmarkIsValidMerkleBranch(b *testing.B) {
byteslib.ToBytes32([]byte("FFFFFF")),
byteslib.ToBytes32([]byte("GGGGGGG")),
}
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte, [32]byte](
m, err := merkle.NewTreeFromLeavesWithDepth[[32]byte](
items,
treeDepth,
)
Expand Down
Loading

0 comments on commit 35c6024

Please sign in to comment.