mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-05 03:24:14 -05:00
feat(primitives): add BuilderIndex SSZ type (#16169)
This pr adds primitives.BuilderIndex for builder registry indexing in Gloas
This commit is contained in:
3
changelog/builder-index.md
Normal file
3
changelog/builder-index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- `primitives.BuilderIndex`: SSZ `uint64` wrapper for builder registry indices.
|
||||
@@ -4,6 +4,7 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"basis_points.go",
|
||||
"builder_index.go",
|
||||
"committee_bits_mainnet.go",
|
||||
"committee_bits_minimal.go", # keep
|
||||
"committee_index.go",
|
||||
@@ -31,6 +32,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"builder_index_test.go",
|
||||
"committee_index_test.go",
|
||||
"domain_test.go",
|
||||
"epoch_test.go",
|
||||
|
||||
54
consensus-types/primitives/builder_index.go
Normal file
54
consensus-types/primitives/builder_index.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package primitives
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
fssz "github.com/prysmaticlabs/fastssz"
|
||||
)
|
||||
|
||||
var _ fssz.HashRoot = (BuilderIndex)(0)
|
||||
var _ fssz.Marshaler = (*BuilderIndex)(nil)
|
||||
var _ fssz.Unmarshaler = (*BuilderIndex)(nil)
|
||||
|
||||
// BuilderIndex is an index into the builder registry.
|
||||
type BuilderIndex uint64
|
||||
|
||||
// HashTreeRoot returns the SSZ hash tree root of the index.
|
||||
func (b BuilderIndex) HashTreeRoot() ([32]byte, error) {
|
||||
return fssz.HashWithDefaultHasher(b)
|
||||
}
|
||||
|
||||
// HashTreeRootWith appends the SSZ uint64 representation of the index to the given hasher.
|
||||
func (b BuilderIndex) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
hh.PutUint64(uint64(b))
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalSSZ decodes the SSZ-encoded uint64 index from buf.
|
||||
func (b *BuilderIndex) UnmarshalSSZ(buf []byte) error {
|
||||
if len(buf) != b.SizeSSZ() {
|
||||
return fmt.Errorf("expected buffer of length %d received %d", b.SizeSSZ(), len(buf))
|
||||
}
|
||||
*b = BuilderIndex(fssz.UnmarshallUint64(buf))
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalSSZTo appends the SSZ-encoded index to dst and returns the extended buffer.
|
||||
func (b *BuilderIndex) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
marshalled, err := b.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(dst, marshalled...), nil
|
||||
}
|
||||
|
||||
// MarshalSSZ encodes the index as an SSZ uint64.
|
||||
func (b *BuilderIndex) MarshalSSZ() ([]byte, error) {
|
||||
marshalled := fssz.MarshalUint64([]byte{}, uint64(*b))
|
||||
return marshalled, nil
|
||||
}
|
||||
|
||||
// SizeSSZ returns the size of the SSZ-encoded index in bytes.
|
||||
func (b *BuilderIndex) SizeSSZ() int {
|
||||
return 8
|
||||
}
|
||||
86
consensus-types/primitives/builder_index_test.go
Normal file
86
consensus-types/primitives/builder_index_test.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package primitives_test
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"slices"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/require"
|
||||
)
|
||||
|
||||
func TestBuilderIndex_SSZRoundTripAndHashRoot(t *testing.T) {
|
||||
cases := []uint64{
|
||||
0,
|
||||
1,
|
||||
42,
|
||||
(1 << 32) - 1,
|
||||
1 << 32,
|
||||
^uint64(0),
|
||||
}
|
||||
|
||||
for _, v := range cases {
|
||||
t.Run("v="+u64name(v), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val := primitives.BuilderIndex(v)
|
||||
require.Equal(t, 8, (&val).SizeSSZ())
|
||||
|
||||
enc, err := (&val).MarshalSSZ()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 8, len(enc))
|
||||
|
||||
wantEnc := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(wantEnc, v)
|
||||
require.DeepEqual(t, wantEnc, enc)
|
||||
|
||||
dstPrefix := []byte("prefix:")
|
||||
dst, err := (&val).MarshalSSZTo(slices.Clone(dstPrefix))
|
||||
require.NoError(t, err)
|
||||
wantDst := append(dstPrefix, wantEnc...)
|
||||
require.DeepEqual(t, wantDst, dst)
|
||||
|
||||
var decoded primitives.BuilderIndex
|
||||
require.NoError(t, (&decoded).UnmarshalSSZ(enc))
|
||||
require.Equal(t, val, decoded)
|
||||
|
||||
root, err := val.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
var wantRoot [32]byte
|
||||
binary.LittleEndian.PutUint64(wantRoot[:8], v)
|
||||
require.Equal(t, wantRoot, root)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderIndex_UnmarshalSSZRejectsWrongSize(t *testing.T) {
|
||||
for _, size := range []int{7, 9} {
|
||||
t.Run("size="+strconv.Itoa(size), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var v primitives.BuilderIndex
|
||||
err := (&v).UnmarshalSSZ(make([]byte, size))
|
||||
require.ErrorContains(t, "expected buffer of length 8", err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func u64name(v uint64) string {
|
||||
switch v {
|
||||
case 0:
|
||||
return "0"
|
||||
case 1:
|
||||
return "1"
|
||||
case 42:
|
||||
return "42"
|
||||
case (1 << 32) - 1:
|
||||
return "2^32-1"
|
||||
case 1 << 32:
|
||||
return "2^32"
|
||||
case ^uint64(0):
|
||||
return "max"
|
||||
default:
|
||||
return "custom"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user