Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ssz): More updates #1654

Merged
merged 12 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
bet
  • Loading branch information
itsdevbear committed Jun 29, 2024
commit 00e5c66fbd15b431fb51b9347aff179bcdea322f
89 changes: 53 additions & 36 deletions mod/primitives/pkg/ssz/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package ssz

import (
"github.com/berachain/beacon-kit/mod/primitives/pkg/common"
"github.com/berachain/beacon-kit/mod/primitives/pkg/constants"
"github.com/berachain/beacon-kit/mod/primitives/pkg/ssz/merkleizer"
"github.com/berachain/beacon-kit/mod/primitives/pkg/ssz/serializer"
)
Expand All @@ -31,73 +32,84 @@ import (
/* -------------------------------------------------------------------------- */

// ListBasic is a list of basic types.
type ListBasic[T Basic[T]] struct {
t []T
limit uint64
type ListBasic[B Basic[B]] struct {
elements []B
limit uint64
}

// ListBasicFromElements creates a new ListComposite from elements.
// TODO: Deprecate once off of Fastssz
func ListBasicFromElements[T Basic[T]](
func ListBasicFromElements[B Basic[B]](
limit uint64,
elements ...T,
) *ListBasic[T] {
return &ListBasic[T]{
t: elements,
limit: limit,
elements ...B,
) *ListBasic[B] {
return &ListBasic[B]{
elements: elements,
limit: limit,
}
}

// IsFixed returns true if the ListBasic is fixed size.
func (l ListBasic[B]) IsFixed() bool {
return false
}

// N returns the N value as defined in the SSZ specification
func (l ListBasic[B]) N() uint64 {
return l.limit
}

// ChunkCount returns the number of chunks in the ListBasic.
func (l ListBasic[B]) ChunkCount() uint64 {
var b B
return (l.N()*uint64(b.SizeSSZ()) + 31) / constants.RootLength
}

// SizeSSZ returns the size of the list in bytes.
func (l ListBasic[T]) SizeSSZ() int {
func (l ListBasic[B]) SizeSSZ() int {
// The same for ListBasic as for VectorBasic.
return VectorBasic[T](l.t).SizeSSZ()
return VectorBasic[B](l.elements).SizeSSZ()
}

// HashTreeRootWith returns the Merkle root of the ListBasic
// with a given merkleizer.
func (l ListBasic[T]) HashTreeRootWith(
merkleizer BasicMerkleizer[[32]byte, T],
func (l ListBasic[B]) HashTreeRootWith(
merkleizer BasicMerkleizer[[32]byte, B],
) ([32]byte, error) {
return merkleizer.MerkleizeListBasic(l.t, l.limit)
return merkleizer.MerkleizeListBasic(l.elements, l.limit)
}

// HashTreeRoot returns the Merkle root of the ListBasic.
func (l ListBasic[T]) HashTreeRoot() ([32]byte, error) {
func (l ListBasic[B]) HashTreeRoot() ([32]byte, error) {
// Create a merkleizer
return l.HashTreeRootWith(merkleizer.New[[32]byte, T]())
return l.HashTreeRootWith(merkleizer.New[[32]byte, B]())
}

// MarshalSSZTo marshals the ListBasic into SSZ format.
func (l ListBasic[T]) MarshalSSZTo(out []byte) ([]byte, error) {
return VectorBasic[T](l.t).MarshalSSZTo(out)
func (l ListBasic[B]) MarshalSSZTo(out []byte) ([]byte, error) {
return VectorBasic[B](l.elements).MarshalSSZTo(out)
}

// MarshalSSZ marshals the ListBasic into SSZ format.
func (l ListBasic[T]) MarshalSSZ() ([]byte, error) {
func (l ListBasic[B]) MarshalSSZ() ([]byte, error) {
// The same for ListBasic as for VectorBasic.
return VectorBasic[T](l.t).MarshalSSZ()
return VectorBasic[B](l.elements).MarshalSSZ()
}

// NewFromSSZ creates a new ListBasic from SSZ format.
func (l ListBasic[T]) NewFromSSZ(buf []byte) (*ListBasic[T], error) {
func (l ListBasic[B]) NewFromSSZ(buf []byte) (*ListBasic[B], error) {
// The same for ListBasic as for VectorBasic
var (
t = make(VectorBasic[T], 0)
err error
elements = make(VectorBasic[B], 0)
err error
)

t, err = t.NewFromSSZ(buf)
return &ListBasic[T]{
t: t,
elements, err = elements.NewFromSSZ(buf)
return &ListBasic[B]{
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved
elements: elements,
Comment on lines +108 to +117
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SSZ Unmarshaling in NewFromSSZ

The method correctly uses the serializer to unmarshal the list from SSZ format. However, the comment suggests that this is similar to VectorBasic, indicating potential code duplication. Consider refactoring to avoid redundancy.

- func (l ListBasic[B]) NewFromSSZ(buf []byte) (*ListBasic[B], error) {
-   // The same for ListBasic as for VectorBasic
-   var (
-     elements = make(VectorBasic[B], 0)
-     err      error
-   )
-   elements, err = elements.NewFromSSZ(buf)
-   return &ListBasic[B]{
-     elements: elements,
-   }, err
+ func NewListBasicFromSSZ[B Basic[B]](buf []byte) (*ListBasic[B], error) {
+   elements, err := VectorBasic[B]{}.NewFromSSZ(buf)
+   if err != nil {
+     return nil, err
+   }
+   return &ListBasic[B]{
+     elements: elements,
+   }, nil
 }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (l ListBasic[B]) NewFromSSZ(buf []byte) (*ListBasic[B], error) {
// The same for ListBasic as for VectorBasic
var (
t = make(VectorBasic[T], 0)
err error
elements = make(VectorBasic[B], 0)
err error
)
t, err = t.NewFromSSZ(buf)
return &ListBasic[T]{
t: t,
elements, err = elements.NewFromSSZ(buf)
return &ListBasic[B]{
elements: elements,
func NewListBasicFromSSZ[B Basic[B]](buf []byte) (*ListBasic[B], error) {
elements, err := VectorBasic[B]{}.NewFromSSZ(buf)
if err != nil {
return nil, err
}
return &ListBasic[B]{
elements: elements,
}, nil
}

}, err
}

// IsFixed returns true if the ListBasic is fixed size.
func (l ListBasic[T]) IsFixed() bool {
return false
}

/* -------------------------------------------------------------------------- */
/* Composite */
/* -------------------------------------------------------------------------- */
Expand All @@ -119,6 +131,16 @@ func ListCompositeFromElements[T Composite[T]](
}
}

// IsFixed returns true if the ListBasic is fixed size.
func (l ListComposite[T]) IsFixed() bool {
return false
}

// N returns the N value as defined in the SSZ specification
func (l ListComposite[T]) N() uint64 {
return l.limit
}

// SizeSSZ returns the size of the list in bytes.
func (l ListComposite[T]) SizeSSZ() int {
// The same for ListComposite as for VectorComposite.
Expand Down Expand Up @@ -176,8 +198,3 @@ func (ListComposite[T]) NewFromSSZ(
limit: limit,
}, nil
}

// IsFixed returns true if the ListBasic is fixed size.
func (l ListComposite[T]) IsFixed() bool {
return false
}
58 changes: 34 additions & 24 deletions mod/primitives/pkg/ssz/vector.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package ssz

import (
"github.com/berachain/beacon-kit/mod/primitives/pkg/common"
"github.com/berachain/beacon-kit/mod/primitives/pkg/constants"
"github.com/berachain/beacon-kit/mod/primitives/pkg/ssz/merkleizer"
"github.com/berachain/beacon-kit/mod/primitives/pkg/ssz/serializer"
)
Expand All @@ -31,59 +32,63 @@ import (
/* -------------------------------------------------------------------------- */

// VectorBasic is a vector of basic types.
type VectorBasic[T Basic[T]] []T
type VectorBasic[B Basic[B]] []B

// VectorBasicFromElements creates a new ListComposite from elements.
// TODO: Deprecate once off of Fastssz
func VectorBasicFromElements[T Basic[T]](elements ...T) VectorBasic[T] {
func VectorBasicFromElements[B Basic[B]](elements ...B) VectorBasic[B] {
return elements
}

// SizeSSZ returns the size of the list in bytes.
func (l VectorBasic[T]) SizeSSZ() int {
var t T
return t.SizeSSZ() * len(l)
func (l VectorBasic[B]) SizeSSZ() int {
var b B
return b.SizeSSZ() * len(l)
}

// isFixed returns true if the VectorBasic is fixed size.
func (VectorBasic[T]) IsFixed() bool {
func (VectorBasic[B]) IsFixed() bool {
return true
}

// ChunkCount returns the number of chunks in the VectorBasic.
func (l VectorBasic[T]) ChunkCount() uint64 {
// We re-use the chunkcount function for lists, however
// we pass in the length of the vector as the max capacity.
return merkleizer.ChunkCountBasicList(l, uint64(len(l)))
func (l VectorBasic[B]) ChunkCount() uint64 {
var b B
return (l.N()*uint64(b.SizeSSZ()) + 31) / constants.RootLength
}

// N returns the N value as defined in the SSZ specification
func (l VectorBasic[B]) N() uint64 {
return uint64(len(l))
}

// HashTreeRootWith returns the Merkle root of the VectorBasic
// with a given merkleizer.
func (l VectorBasic[T]) HashTreeRootWith(
merkleizer BasicMerkleizer[[32]byte, T],
func (l VectorBasic[B]) HashTreeRootWith(
merkleizer BasicMerkleizer[[32]byte, B],
) ([32]byte, error) {
return merkleizer.MerkleizeVectorBasic(l)
}

// HashTreeRoot returns the Merkle root of the VectorBasic.
func (l VectorBasic[T]) HashTreeRoot() ([32]byte, error) {
func (l VectorBasic[B]) HashTreeRoot() ([32]byte, error) {
// Create a merkleizer
return l.HashTreeRootWith(merkleizer.New[[32]byte, T]())
return l.HashTreeRootWith(merkleizer.New[[32]byte, B]())
}

// MarshalSSZToBytes marshals the VectorBasic into SSZ format.
func (l VectorBasic[T]) MarshalSSZTo(out []byte) ([]byte, error) {
func (l VectorBasic[B]) MarshalSSZTo(out []byte) ([]byte, error) {
return serializer.MarshalVectorFixed(out, l)
}

// MarshalSSZ marshals the VectorBasic into SSZ format.
func (l VectorBasic[T]) MarshalSSZ() ([]byte, error) {
func (l VectorBasic[B]) MarshalSSZ() ([]byte, error) {
return l.MarshalSSZTo(make([]byte, 0, l.SizeSSZ()))
}

// NewFromSSZ creates a new VectorBasic from SSZ format.
func (VectorBasic[T]) NewFromSSZ(buf []byte) (VectorBasic[T], error) {
return serializer.UnmarshalVectorFixed[T](buf)
func (VectorBasic[B]) NewFromSSZ(buf []byte) (VectorBasic[B], error) {
return serializer.UnmarshalVectorFixed[B](buf)
}

/* -------------------------------------------------------------------------- */
Expand All @@ -101,6 +106,17 @@ func VectorCompositeFromElements[T Composite[T]](
return elements
}

// isFixed returns true if the VectorBasic is fixed size.
func (VectorComposite[T]) IsFixed() bool {
var t T
return t.IsFixed()
}

// N returns the N value as defined in the SSZ specification
func (l VectorComposite[T]) N() uint64 {
return uint64(len(l))
}

// SizeSSZ returns the size of the list in bytes.
func (l VectorComposite[T]) SizeSSZ() int {
var t T
Expand Down Expand Up @@ -147,9 +163,3 @@ func (VectorComposite[T]) NewFromSSZ(

return serializer.UnmarshalVectorFixed[T](buf)
}

// isFixed returns true if the VectorBasic is fixed size.
func (VectorComposite[T]) IsFixed() bool {
var t T
return t.IsFixed()
}
Loading