From 9f9401e61504f93dd300bbc80d47f8039a10915a Mon Sep 17 00:00:00 2001 From: Jun Song <87601811+syjn99@users.noreply.github.com> Date: Fri, 19 Sep 2025 22:58:56 +0900 Subject: [PATCH] SSZ-QL: Handle `Bitlist` and `Bitvector` (#15704) * Add bitvector field for FixedTestContainer * Handle Bitvector type using isBitfield flag * Add Bitvector case for Stringify * Add bitlist field for VariableTestContainer * Add bitlistInfo * Changelog * Add bitvectorInfo * Remove analyzeBit* functions and just inline them * Fix misleading comments * Add comments for bitlistInfo's Size * Apply reviews from Radek --- changelog/syjn99_ssz-ql-bitlist-bitvector.md | 3 + encoding/ssz/query/BUILD.bazel | 4 + encoding/ssz/query/analyzer.go | 62 ++++++- encoding/ssz/query/analyzer_test.go | 2 +- encoding/ssz/query/bitlist.go | 65 ++++++++ encoding/ssz/query/bitvector.go | 15 ++ encoding/ssz/query/query_test.go | 75 ++++++++- encoding/ssz/query/ssz_info.go | 41 ++++- encoding/ssz/query/tag_parser.go | 16 +- encoding/ssz/query/testutil/BUILD.bazel | 1 + encoding/ssz/query/testutil/util.go | 22 ++- proto/ssz_query/BUILD.bazel | 1 + proto/ssz_query/ssz_query.pb.go | 164 ++++++++++++------- proto/ssz_query/ssz_query.proto | 40 +++-- proto/ssz_query/ssz_query.ssz.go | 118 ++++++++++--- 15 files changed, 519 insertions(+), 110 deletions(-) create mode 100644 changelog/syjn99_ssz-ql-bitlist-bitvector.md create mode 100644 encoding/ssz/query/bitlist.go create mode 100644 encoding/ssz/query/bitvector.go diff --git a/changelog/syjn99_ssz-ql-bitlist-bitvector.md b/changelog/syjn99_ssz-ql-bitlist-bitvector.md new file mode 100644 index 0000000000..956e18b0cb --- /dev/null +++ b/changelog/syjn99_ssz-ql-bitlist-bitvector.md @@ -0,0 +1,3 @@ +### Added + +- SSZ-QL: Handle `Bitlist` and `Bitvector` types. diff --git a/encoding/ssz/query/BUILD.bazel b/encoding/ssz/query/BUILD.bazel index 9bf99e6552..93caf3b170 100644 --- a/encoding/ssz/query/BUILD.bazel +++ b/encoding/ssz/query/BUILD.bazel @@ -4,6 +4,8 @@ go_library( name = "go_default_library", srcs = [ "analyzer.go", + "bitlist.go", + "bitvector.go", "container.go", "list.go", "path.go", @@ -15,6 +17,7 @@ go_library( ], importpath = "github.com/OffchainLabs/prysm/v6/encoding/ssz/query", visibility = ["//visibility:public"], + deps = ["@com_github_prysmaticlabs_go_bitfield//:go_default_library"], ) go_test( @@ -30,5 +33,6 @@ go_test( "//encoding/ssz/query/testutil:go_default_library", "//proto/ssz_query:go_default_library", "//testing/require:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], ) diff --git a/encoding/ssz/query/analyzer.go b/encoding/ssz/query/analyzer.go index 2d983464d6..5bd882b802 100644 --- a/encoding/ssz/query/analyzer.go +++ b/encoding/ssz/query/analyzer.go @@ -67,6 +67,25 @@ func PopulateVariableLengthInfo(sszInfo *sszInfo, value any) error { } return nil + + // In Bitlist case, we have to set the actual length of the bitlist. + case Bitlist: + bitlistInfo, err := sszInfo.BitlistInfo() + if err != nil { + return fmt.Errorf("could not get bitlist info: %w", err) + } + + if bitlistInfo == nil { + return errors.New("bitlistInfo is nil") + } + + val := reflect.ValueOf(value) + if err := bitlistInfo.SetLengthFromBytes(val.Bytes()); err != nil { + return fmt.Errorf("could not set bitlist length from bytes: %w", err) + } + + return nil + // In Container case, we need to recursively populate variable-sized fields. case Container: containerInfo, err := sszInfo.ContainerInfo() @@ -194,7 +213,7 @@ func analyzeHomogeneousColType(typ reflect.Type, tag *reflect.StructTag) (*sszIn return nil, fmt.Errorf("could not get list limit: %w", err) } - return analyzeListType(typ, elementInfo, limit) + return analyzeListType(typ, elementInfo, limit, sszDimension.isBitfield) } // 2. Handle Vector/Bitvector type @@ -204,7 +223,7 @@ func analyzeHomogeneousColType(typ reflect.Type, tag *reflect.StructTag) (*sszIn return nil, fmt.Errorf("could not get vector length: %w", err) } - return analyzeVectorType(typ, elementInfo, length) + return analyzeVectorType(typ, elementInfo, length, sszDimension.isBitfield) } // Parsing ssz tag doesn't provide enough information to determine the collection type, @@ -212,8 +231,22 @@ func analyzeHomogeneousColType(typ reflect.Type, tag *reflect.StructTag) (*sszIn return nil, errors.New("could not determine collection type from tags") } -// analyzeListType analyzes SSZ List type and returns its SSZ info. -func analyzeListType(typ reflect.Type, elementInfo *sszInfo, limit uint64) (*sszInfo, error) { +// analyzeListType analyzes SSZ List/Bitlist type and returns its SSZ info. +func analyzeListType(typ reflect.Type, elementInfo *sszInfo, limit uint64, isBitfield bool) (*sszInfo, error) { + if isBitfield { + return &sszInfo{ + sszType: Bitlist, + typ: typ, + + fixedSize: offsetBytes, + isVariable: true, + + bitlistInfo: &bitlistInfo{ + limit: limit, + }, + }, nil + } + if elementInfo == nil { return nil, errors.New("element info is required for List") } @@ -232,10 +265,25 @@ func analyzeListType(typ reflect.Type, elementInfo *sszInfo, limit uint64) (*ssz }, nil } -// analyzeVectorType analyzes SSZ Vector type and returns its SSZ info. -func analyzeVectorType(typ reflect.Type, elementInfo *sszInfo, length uint64) (*sszInfo, error) { +// analyzeVectorType analyzes SSZ Vector/Bitvector type and returns its SSZ info. +func analyzeVectorType(typ reflect.Type, elementInfo *sszInfo, length uint64, isBitfield bool) (*sszInfo, error) { + if isBitfield { + return &sszInfo{ + sszType: Bitvector, + typ: typ, + + // Size in bytes + fixedSize: length, + isVariable: false, + + bitvectorInfo: &bitvectorInfo{ + length: length * 8, // length in bits + }, + }, nil + } + if elementInfo == nil { - return nil, errors.New("element info is required for Vector") + return nil, errors.New("element info is required for Vector/Bitvector") } // Validate the given length. diff --git a/encoding/ssz/query/analyzer_test.go b/encoding/ssz/query/analyzer_test.go index 089cf915ae..7c8d4666fa 100644 --- a/encoding/ssz/query/analyzer_test.go +++ b/encoding/ssz/query/analyzer_test.go @@ -13,5 +13,5 @@ func TestAnalyzeSSZInfo(t *testing.T) { require.NoError(t, err) require.NotNil(t, info, "Expected non-nil SSZ info") - require.Equal(t, uint64(493), info.FixedSize(), "Expected fixed size to be 333") + require.Equal(t, uint64(565), info.FixedSize()) } diff --git a/encoding/ssz/query/bitlist.go b/encoding/ssz/query/bitlist.go new file mode 100644 index 0000000000..91e39690c9 --- /dev/null +++ b/encoding/ssz/query/bitlist.go @@ -0,0 +1,65 @@ +package query + +import ( + "errors" + "fmt" + + "github.com/prysmaticlabs/go-bitfield" +) + +// bitlistInfo holds information about a SSZ Bitlist type. +// +// Same as listInfo, but limit/length are in bits, not elements. +type bitlistInfo struct { + // limit is the maximum number of bits in the bitlist. + limit uint64 + // length is the actual number of bits at runtime (0 if not set). + length uint64 +} + +func (l *bitlistInfo) Limit() uint64 { + if l == nil { + return 0 + } + return l.limit +} + +func (l *bitlistInfo) Length() uint64 { + if l == nil { + return 0 + } + return l.length +} + +func (l *bitlistInfo) SetLength(length uint64) error { + if l == nil { + return errors.New("bitlistInfo is nil") + } + + if length > l.limit { + return fmt.Errorf("length %d exceeds limit %d", length, l.limit) + } + + l.length = length + return nil +} + +// SetLengthFromBytes determines the actual bitlist length from SSZ-encoded bytes. +func (l *bitlistInfo) SetLengthFromBytes(rawBytes []byte) error { + // Wrap rawBytes in a Bitlist to use existing methods. + bl := bitfield.Bitlist(rawBytes) + return l.SetLength(bl.Len()) +} + +// Size returns the size in bytes for this bitlist. +// Note that while serializing, 1 bit is added for the delimiter bit, +// which results in ceil((length + 1) / 8) bytes. +// Note that `(length / 8) + 1` is equivalent to `ceil((length + 1) / 8)`. +// Example: length=0 -> size=1, length=7 -> size=1, length=8 -> size=2 +// Reference: https://github.com/ethereum/consensus-specs/blob/master/ssz/simple-serialize.md#bitlistn-progressivebitlist +func (l *bitlistInfo) Size() uint64 { + if l == nil { + return 0 + } + return (l.length / 8) + 1 +} diff --git a/encoding/ssz/query/bitvector.go b/encoding/ssz/query/bitvector.go new file mode 100644 index 0000000000..046189d232 --- /dev/null +++ b/encoding/ssz/query/bitvector.go @@ -0,0 +1,15 @@ +package query + +// bitvectorInfo holds information about a SSZ Bitvector type. +type bitvectorInfo struct { + // length is the fixed length of bits of the Bitvector. + length uint64 +} + +func (v *bitvectorInfo) Length() uint64 { + if v == nil { + return 0 + } + + return v.length +} diff --git a/encoding/ssz/query/query_test.go b/encoding/ssz/query/query_test.go index 90df5fd2da..3541274703 100644 --- a/encoding/ssz/query/query_test.go +++ b/encoding/ssz/query/query_test.go @@ -8,6 +8,7 @@ import ( "github.com/OffchainLabs/prysm/v6/encoding/ssz/query/testutil" sszquerypb "github.com/OffchainLabs/prysm/v6/proto/ssz_query" "github.com/OffchainLabs/prysm/v6/testing/require" + "github.com/prysmaticlabs/go-bitfield" ) func TestCalculateOffsetAndLength(t *testing.T) { @@ -80,11 +81,24 @@ func TestCalculateOffsetAndLength(t *testing.T) { expectedOffset: 277, expectedLength: 160, // 5 * 32 bytes }, + // Bitvector fields + { + name: "bitvector64_field", + path: ".bitvector64_field", + expectedOffset: 437, + expectedLength: 8, + }, + { + name: "bitvector512_field", + path: ".bitvector512_field", + expectedOffset: 445, + expectedLength: 64, + }, // Trailing field { name: "trailing_field", path: ".trailing_field", - expectedOffset: 437, + expectedOffset: 509, expectedLength: 56, }, } @@ -119,26 +133,26 @@ func TestCalculateOffsetAndLength(t *testing.T) { { name: "field_list_uint64", path: ".field_list_uint64", - expectedOffset: 104, // First part of variable-sized type. + expectedOffset: 108, // First part of variable-sized type. expectedLength: 40, // 5 elements * uint64 (8 bytes each) }, { name: "field_list_container", path: ".field_list_container", - expectedOffset: 144, // Second part of variable-sized type. + expectedOffset: 148, // Second part of variable-sized type. expectedLength: 120, // 3 elements * FixedNestedContainer (40 bytes each) }, { name: "field_list_bytes32", path: ".field_list_bytes32", - expectedOffset: 264, + expectedOffset: 268, expectedLength: 96, // 3 elements * 32 bytes each }, // Nested paths { name: "nested", path: ".nested", - expectedOffset: 360, + expectedOffset: 364, // Calculated with: // - Value1: 8 bytes // - field_list_uint64 offset: 4 bytes @@ -148,20 +162,27 @@ func TestCalculateOffsetAndLength(t *testing.T) { { name: "nested.value1", path: ".nested.value1", - expectedOffset: 360, + expectedOffset: 364, expectedLength: 8, }, { name: "nested.field_list_uint64", path: ".nested.field_list_uint64", - expectedOffset: 372, + expectedOffset: 376, expectedLength: 40, }, + // Bitlist field + { + name: "bitlist_field", + path: ".bitlist_field", + expectedOffset: 416, + expectedLength: 33, // 32 bytes + 1 byte for length delimiter + }, // Fixed trailing field { name: "trailing_field", path: ".trailing_field", - expectedOffset: 48, // After leading_field + 4 offset pointers + expectedOffset: 52, // After leading_field + 5 offset pointers expectedLength: 56, }, } @@ -208,6 +229,16 @@ func createFixedTestContainer() *sszquerypb.FixedTestContainer { nestedValue2[i] = byte(i + 56) } + bitvector64 := bitfield.NewBitvector64() + for i := range bitvector64 { + bitvector64[i] = 0x42 + } + + bitvector512 := bitfield.NewBitvector512() + for i := range bitvector512 { + bitvector512[i] = 0x24 + } + trailingField := make([]byte, 56) for i := range trailingField { trailingField[i] = byte(i + 88) @@ -240,6 +271,10 @@ func createFixedTestContainer() *sszquerypb.FixedTestContainer { make([]byte, 32), }, + // Bitvector fields + Bitvector64Field: bitvector64, + Bitvector512Field: bitvector512, + // Trailing field TrailingField: trailingField, } @@ -294,6 +329,15 @@ func getFixedTestContainerSpec() testutil.TestSpec { Path: ".two_dimension_bytes_field", Expected: testContainer.TwoDimensionBytesField, }, + // Bitvector fields + { + Path: ".bitvector64_field", + Expected: testContainer.Bitvector64Field, + }, + { + Path: ".bitvector512_field", + Expected: testContainer.Bitvector512Field, + }, // Trailing field { Path: ".trailing_field", @@ -326,6 +370,13 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer { } } + bitlistField := bitfield.NewBitlist(256) + bitlistField.SetBitAt(0, true) + bitlistField.SetBitAt(10, true) + bitlistField.SetBitAt(50, true) + bitlistField.SetBitAt(100, true) + bitlistField.SetBitAt(255, true) + return &sszquerypb.VariableTestContainer{ // Fixed leading field LeadingField: leadingField, @@ -345,6 +396,9 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer { FieldListUint64: []uint64{1, 2, 3, 4, 5}, }, + // Bitlist field + BitlistField: bitlistField, + // Fixed trailing field TrailingField: trailingField, } @@ -391,6 +445,11 @@ func getVariableTestContainerSpec() testutil.TestSpec { Path: ".nested.field_list_uint64", Expected: testContainer.Nested.FieldListUint64, }, + // Bitlist field + { + Path: ".bitlist_field", + Expected: testContainer.BitlistField, + }, // Fixed trailing field { Path: ".trailing_field", diff --git a/encoding/ssz/query/ssz_info.go b/encoding/ssz/query/ssz_info.go index 71f57d8965..ca0c7e466c 100644 --- a/encoding/ssz/query/ssz_info.go +++ b/encoding/ssz/query/ssz_info.go @@ -27,6 +27,12 @@ type sszInfo struct { // For Vector types. vectorInfo *vectorInfo + + // For Bitlist types. + bitlistInfo *bitlistInfo + + // For Bitvector types. + bitvectorInfo *bitvectorInfo } func (info *sszInfo) FixedSize() uint64 { @@ -53,6 +59,9 @@ func (info *sszInfo) Size() uint64 { return length * elementSize + case Bitlist: + return info.bitlistInfo.Size() + case Container: size := info.fixedSize for _, fieldInfo := range info.containerInfo.fields { @@ -65,7 +74,6 @@ func (info *sszInfo) Size() uint64 { return size default: - // NOTE: Handle other variable-sized types. return 0 } } @@ -110,6 +118,30 @@ func (info *sszInfo) VectorInfo() (*vectorInfo, error) { return info.vectorInfo, nil } +func (info *sszInfo) BitlistInfo() (*bitlistInfo, error) { + if info == nil { + return nil, errors.New("sszInfo is nil") + } + + if info.sszType != Bitlist { + return nil, fmt.Errorf("sszInfo is not a Bitlist type, got %s", info.sszType) + } + + return info.bitlistInfo, nil +} + +func (info *sszInfo) BitvectorInfo() (*bitvectorInfo, error) { + if info == nil { + return nil, errors.New("sszInfo is nil") + } + + if info.sszType != Bitvector { + return nil, fmt.Errorf("sszInfo is not a Bitvector type, got %s", info.sszType) + } + + return info.bitvectorInfo, nil +} + // String implements the Stringer interface for sszInfo. // This follows the notation used in the consensus specs. func (info *sszInfo) String() string { @@ -128,6 +160,10 @@ func (info *sszInfo) String() string { return fmt.Sprintf("Bytes%d", info.vectorInfo.length) } return fmt.Sprintf("Vector[%s, %d]", info.vectorInfo.element, info.vectorInfo.length) + case Bitlist: + return fmt.Sprintf("Bitlist[%d]", info.bitlistInfo.limit) + case Bitvector: + return fmt.Sprintf("Bitvector[%d]", info.bitvectorInfo.length) default: return info.typ.Name() } @@ -175,6 +211,9 @@ func printRecursive(info *sszInfo, builder *strings.Builder, prefix string) { case List: builder.WriteString(fmt.Sprintf("%s (%s / length: %d, size: %d)\n", info, sizeDesc, info.listInfo.length, info.Size())) + case Bitlist: + builder.WriteString(fmt.Sprintf("%s (%s / length (bit): %d, size: %d)\n", info, sizeDesc, info.bitlistInfo.length, info.Size())) + default: builder.WriteString(fmt.Sprintf("%s (%s / size: %d)\n", info, sizeDesc, info.Size())) } diff --git a/encoding/ssz/query/tag_parser.go b/encoding/ssz/query/tag_parser.go index 3ec848d1b5..0dd9e26735 100644 --- a/encoding/ssz/query/tag_parser.go +++ b/encoding/ssz/query/tag_parser.go @@ -15,6 +15,10 @@ const ( // sszSizeTag specifies the length of a fixed-sized collection, like an SSZ Vector. // A wildcard ('?') indicates that the dimension is variable-sized (a List). sszSizeTag = "ssz-size" + + // castTypeTag specifies special custom casting instructions. + // e.g., "github.com/prysmaticlabs/go-bitfield.Bitlist". + castTypeTag = "cast-type" ) // SSZDimension holds parsed SSZ tag information for current dimension. @@ -22,6 +26,9 @@ const ( type SSZDimension struct { vectorLength *uint64 listLimit *uint64 + + // isBitfield indicates if the dimension represents a bitfield type (Bitlist, Bitvector). + isBitfield bool } // ParseSSZTag parses SSZ-specific tags (like `ssz-max` and `ssz-size`) @@ -34,6 +41,11 @@ func ParseSSZTag(tag *reflect.StructTag) (*SSZDimension, *reflect.StructTag, err var newTagParts []string var sizeStr, maxStr string + var isBitfield bool + + if castType := tag.Get(castTypeTag); strings.Contains(castType, "go-bitfield") { + isBitfield = true + } // Parse ssz-size tag if sszSize := tag.Get(sszSizeTag); sszSize != "" { @@ -88,7 +100,7 @@ func ParseSSZTag(tag *reflect.StructTag) (*SSZDimension, *reflect.StructTag, err return nil, nil, errors.New("ssz-max must be greater than 0") } - return &SSZDimension{listLimit: &limit}, newTag, nil + return &SSZDimension{listLimit: &limit, isBitfield: isBitfield}, newTag, nil } // 2. If ssz-size is specified, it must be a vector. @@ -100,7 +112,7 @@ func ParseSSZTag(tag *reflect.StructTag) (*SSZDimension, *reflect.StructTag, err return nil, nil, errors.New("ssz-size must be greater than 0") } - return &SSZDimension{vectorLength: &length}, newTag, nil + return &SSZDimension{vectorLength: &length, isBitfield: isBitfield}, newTag, nil } // IsVector returns true if this dimension represents a vector. diff --git a/encoding/ssz/query/testutil/BUILD.bazel b/encoding/ssz/query/testutil/BUILD.bazel index d97421eaa9..8e66a56bb3 100644 --- a/encoding/ssz/query/testutil/BUILD.bazel +++ b/encoding/ssz/query/testutil/BUILD.bazel @@ -14,5 +14,6 @@ go_library( "//encoding/ssz/query:go_default_library", "//testing/require:go_default_library", "@com_github_prysmaticlabs_fastssz//:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", ], ) diff --git a/encoding/ssz/query/testutil/util.go b/encoding/ssz/query/testutil/util.go index 3f99357230..f9ec4bd34f 100644 --- a/encoding/ssz/query/testutil/util.go +++ b/encoding/ssz/query/testutil/util.go @@ -3,8 +3,10 @@ package testutil import ( "fmt" "reflect" + "strings" ssz "github.com/prysmaticlabs/fastssz" + "github.com/prysmaticlabs/go-bitfield" ) // marshalAny marshals any value into SSZ format. @@ -20,7 +22,25 @@ func marshalAny(value any) ([]byte, error) { } // Handle custom type aliases by checking if they're based on primitive types - if valueType.PkgPath() != "" { + if pkgPath := valueType.PkgPath(); pkgPath != "" { + // Special handling for bitfield types. + if strings.Contains(pkgPath, "go-bitfield") { + // Check if it's a Bitlist (variable-length) that needs SSZ encoding + if bl, ok := value.(bitfield.Bitlist); ok { + // The Bitlist type already contains the SSZ delimiter bit in its internal representation + // The raw []byte contains the delimiter as the most significant bit + // So we just return the raw bytes directly for SSZ encoding + return []byte(bl), nil + } + + // For other bitfield types (Bitvector), just return the bytes + if bitfield, ok := value.(bitfield.Bitfield); ok { + return bitfield.Bytes(), nil + } + + return nil, fmt.Errorf("expected bitfield type, got %T", value) + } + switch valueType.Kind() { case reflect.Uint64: return ssz.MarshalUint64(make([]byte, 0), reflect.ValueOf(value).Uint()), nil diff --git a/proto/ssz_query/BUILD.bazel b/proto/ssz_query/BUILD.bazel index 933689529d..16991bf95c 100644 --- a/proto/ssz_query/BUILD.bazel +++ b/proto/ssz_query/BUILD.bazel @@ -25,6 +25,7 @@ go_proto_library( visibility = ["//visibility:public"], deps = [ "//proto/eth/ext:go_default_library", + "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_golang_protobuf//proto:go_default_library", "@org_golang_google_protobuf//reflect/protoreflect:go_default_library", "@org_golang_google_protobuf//runtime/protoimpl:go_default_library", diff --git a/proto/ssz_query/ssz_query.pb.go b/proto/ssz_query/ssz_query.pb.go index 169444d04b..0c25240fec 100755 --- a/proto/ssz_query/ssz_query.pb.go +++ b/proto/ssz_query/ssz_query.pb.go @@ -11,6 +11,7 @@ import ( sync "sync" _ "github.com/OffchainLabs/prysm/v6/proto/eth/ext" + github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) @@ -82,14 +83,16 @@ type FixedTestContainer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - FieldUint32 uint32 `protobuf:"varint,3,opt,name=field_uint32,json=fieldUint32,proto3" json:"field_uint32,omitempty"` - FieldUint64 uint64 `protobuf:"varint,4,opt,name=field_uint64,json=fieldUint64,proto3" json:"field_uint64,omitempty"` - FieldBool bool `protobuf:"varint,5,opt,name=field_bool,json=fieldBool,proto3" json:"field_bool,omitempty"` - FieldBytes32 []byte `protobuf:"bytes,8,opt,name=field_bytes32,json=fieldBytes32,proto3" json:"field_bytes32,omitempty" ssz-size:"32"` - Nested *FixedNestedContainer `protobuf:"bytes,9,opt,name=nested,proto3" json:"nested,omitempty"` - VectorField []uint64 `protobuf:"varint,10,rep,packed,name=vector_field,json=vectorField,proto3" json:"vector_field,omitempty" ssz-size:"24"` - TwoDimensionBytesField [][]byte `protobuf:"bytes,11,rep,name=two_dimension_bytes_field,json=twoDimensionBytesField,proto3" json:"two_dimension_bytes_field,omitempty" ssz-size:"5,32"` - TrailingField []byte `protobuf:"bytes,12,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"` + FieldUint32 uint32 `protobuf:"varint,1,opt,name=field_uint32,json=fieldUint32,proto3" json:"field_uint32,omitempty"` + FieldUint64 uint64 `protobuf:"varint,2,opt,name=field_uint64,json=fieldUint64,proto3" json:"field_uint64,omitempty"` + FieldBool bool `protobuf:"varint,3,opt,name=field_bool,json=fieldBool,proto3" json:"field_bool,omitempty"` + FieldBytes32 []byte `protobuf:"bytes,4,opt,name=field_bytes32,json=fieldBytes32,proto3" json:"field_bytes32,omitempty" ssz-size:"32"` + Nested *FixedNestedContainer `protobuf:"bytes,5,opt,name=nested,proto3" json:"nested,omitempty"` + VectorField []uint64 `protobuf:"varint,6,rep,packed,name=vector_field,json=vectorField,proto3" json:"vector_field,omitempty" ssz-size:"24"` + TwoDimensionBytesField [][]byte `protobuf:"bytes,7,rep,name=two_dimension_bytes_field,json=twoDimensionBytesField,proto3" json:"two_dimension_bytes_field,omitempty" ssz-size:"5,32"` + Bitvector64Field github_com_prysmaticlabs_go_bitfield.Bitvector64 `protobuf:"bytes,8,opt,name=bitvector64_field,json=bitvector64Field,proto3" json:"bitvector64_field,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector64" ssz-size:"8"` + Bitvector512Field github_com_prysmaticlabs_go_bitfield.Bitvector512 `protobuf:"bytes,9,opt,name=bitvector512_field,json=bitvector512Field,proto3" json:"bitvector512_field,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitvector512" ssz-size:"64"` + TrailingField []byte `protobuf:"bytes,10,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"` } func (x *FixedTestContainer) Reset() { @@ -173,6 +176,20 @@ func (x *FixedTestContainer) GetTwoDimensionBytesField() [][]byte { return nil } +func (x *FixedTestContainer) GetBitvector64Field() github_com_prysmaticlabs_go_bitfield.Bitvector64 { + if x != nil { + return x.Bitvector64Field + } + return github_com_prysmaticlabs_go_bitfield.Bitvector64(nil) +} + +func (x *FixedTestContainer) GetBitvector512Field() github_com_prysmaticlabs_go_bitfield.Bitvector512 { + if x != nil { + return x.Bitvector512Field + } + return github_com_prysmaticlabs_go_bitfield.Bitvector512(nil) +} + func (x *FixedTestContainer) GetTrailingField() []byte { if x != nil { return x.TrailingField @@ -240,12 +257,13 @@ type VariableTestContainer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - LeadingField []byte `protobuf:"bytes,1,opt,name=leading_field,json=leadingField,proto3" json:"leading_field,omitempty" ssz-size:"32"` - FieldListUint64 []uint64 `protobuf:"varint,2,rep,packed,name=field_list_uint64,json=fieldListUint64,proto3" json:"field_list_uint64,omitempty" ssz-max:"2048"` - FieldListContainer []*FixedNestedContainer `protobuf:"bytes,3,rep,name=field_list_container,json=fieldListContainer,proto3" json:"field_list_container,omitempty" ssz-max:"128"` - FieldListBytes32 [][]byte `protobuf:"bytes,4,rep,name=field_list_bytes32,json=fieldListBytes32,proto3" json:"field_list_bytes32,omitempty" ssz-max:"100" ssz-size:"?,32"` - Nested *VariableNestedContainer `protobuf:"bytes,5,opt,name=nested,proto3" json:"nested,omitempty"` - TrailingField []byte `protobuf:"bytes,6,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"` + LeadingField []byte `protobuf:"bytes,1,opt,name=leading_field,json=leadingField,proto3" json:"leading_field,omitempty" ssz-size:"32"` + FieldListUint64 []uint64 `protobuf:"varint,2,rep,packed,name=field_list_uint64,json=fieldListUint64,proto3" json:"field_list_uint64,omitempty" ssz-max:"2048"` + FieldListContainer []*FixedNestedContainer `protobuf:"bytes,3,rep,name=field_list_container,json=fieldListContainer,proto3" json:"field_list_container,omitempty" ssz-max:"128"` + FieldListBytes32 [][]byte `protobuf:"bytes,4,rep,name=field_list_bytes32,json=fieldListBytes32,proto3" json:"field_list_bytes32,omitempty" ssz-max:"100" ssz-size:"?,32"` + Nested *VariableNestedContainer `protobuf:"bytes,5,opt,name=nested,proto3" json:"nested,omitempty"` + BitlistField github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,6,opt,name=bitlist_field,json=bitlistField,proto3" json:"bitlist_field,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"2048"` + TrailingField []byte `protobuf:"bytes,7,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"` } func (x *VariableTestContainer) Reset() { @@ -315,6 +333,13 @@ func (x *VariableTestContainer) GetNested() *VariableNestedContainer { return nil } +func (x *VariableTestContainer) GetBitlistField() github_com_prysmaticlabs_go_bitfield.Bitlist { + if x != nil { + return x.BitlistField + } + return github_com_prysmaticlabs_go_bitfield.Bitlist(nil) +} + func (x *VariableTestContainer) GetTrailingField() []byte { if x != nil { return x.TrailingField @@ -334,66 +359,85 @@ var file_proto_ssz_query_ssz_query_proto_rawDesc = []byte{ 0x72, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x12, 0x1e, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, - 0x32, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x22, 0xfe, 0x02, 0x0a, 0x12, 0x46, 0x69, + 0x32, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x32, 0x22, 0xd2, 0x04, 0x0a, 0x12, 0x46, 0x69, 0x78, 0x65, 0x64, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e, - 0x74, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x74, 0x36, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, - 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, + 0x62, 0x6f, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x6f, 0x6f, 0x6c, 0x12, 0x2b, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, + 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x33, 0x32, 0x12, 0x37, 0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x33, 0x32, 0x12, 0x37, 0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x0c, 0x76, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x0a, 0x20, 0x03, 0x28, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x04, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x32, 0x34, 0x52, 0x0b, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a, 0x19, 0x74, 0x77, 0x6f, 0x5f, 0x64, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x66, 0x69, - 0x65, 0x6c, 0x64, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x35, + 0x65, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x08, 0x8a, 0xb5, 0x18, 0x04, 0x35, 0x2c, 0x33, 0x32, 0x52, 0x16, 0x74, 0x77, 0x6f, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, - 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, - 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x66, 0x0a, 0x17, 0x56, 0x61, - 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x12, 0x33, 0x0a, + 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x66, 0x0a, 0x11, 0x62, + 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x39, 0x82, 0xb5, 0x18, 0x30, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x36, 0x34, 0x8a, 0xb5, 0x18, 0x01, + 0x38, 0x52, 0x10, 0x62, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x36, 0x34, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x12, 0x6a, 0x0a, 0x12, 0x62, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x35, 0x31, 0x32, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x42, + 0x3b, 0x82, 0xb5, 0x18, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, + 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x35, 0x31, 0x32, 0x8a, 0xb5, 0x18, 0x02, 0x36, 0x34, 0x52, 0x11, 0x62, 0x69, + 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x35, 0x31, 0x32, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, + 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, + 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x66, + 0x0a, 0x17, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x31, 0x12, 0x33, 0x0a, 0x11, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, + 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x07, 0x92, 0xb5, + 0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, + 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x22, 0xdf, 0x03, 0x0a, 0x15, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x12, 0x2b, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, + 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x34, 0x0a, 0x11, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x30, - 0x30, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x69, 0x6e, 0x74, - 0x36, 0x34, 0x22, 0x80, 0x03, 0x0a, 0x15, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x54, - 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x0d, - 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x6c, 0x65, 0x61, - 0x64, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x34, 0x0a, 0x11, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0f, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, - 0x5a, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4e, - 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x07, - 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x12, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x33, - 0x32, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0f, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x33, - 0x32, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x10, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, - 0x69, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x12, 0x3a, 0x0a, 0x06, 0x6e, 0x65, - 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x73, 0x7a, - 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, - 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x06, - 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, - 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, - 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x73, - 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, + 0x34, 0x38, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x69, 0x6e, + 0x74, 0x36, 0x34, 0x12, 0x5a, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, + 0x78, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x12, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x3d, 0x0a, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x33, 0x32, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0f, 0x8a, 0xb5, 0x18, + 0x04, 0x3f, 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x10, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x12, 0x3a, + 0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x5d, 0x0a, 0x0d, 0x62, 0x69, + 0x74, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x6c, + 0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0c, 0x62, 0x69, 0x74, + 0x6c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, + 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, + 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/ssz_query/ssz_query.proto b/proto/ssz_query/ssz_query.proto index fec55bc482..5902c2b120 100644 --- a/proto/ssz_query/ssz_query.proto +++ b/proto/ssz_query/ssz_query.proto @@ -20,29 +20,42 @@ message FixedNestedContainer { // FixedTestContainer - comprehensive fixed-size container for SSZ query testing // Tests: All basic fixed-size SSZ types, nested containers, vectors, offset/length calculations -// Total size: 493 bytes (4+8+1+32+40+192+160+56) +// Total size: 565 bytes (4+8+1+32+40+192+160+8+64+56) message FixedTestContainer { // Basic integer types - test different integer sizes and their SSZ serialization - uint32 field_uint32 = 3; // Test: uint32 basic type, offset: 0 - uint64 field_uint64 = 4; // Test: uint64 basic type, offset: 4 + uint32 field_uint32 = 1; // Test: uint32 basic type, offset: 0 + uint64 field_uint64 = 2; // Test: uint64 basic type, offset: 4 // Boolean type - test boolean serialization (1 byte in SSZ) - bool field_bool = 5; // Test: boolean basic type, offset: 12 + bool field_bool = 3; // Test: boolean basic type, offset: 12 // Fixed-size bytes - test byte array - bytes field_bytes32 = 8 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Test: 32-byte array, offset: 13 + bytes field_bytes32 = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; // Test: 32-byte array, offset: 13 // Nested container - test container nesting and field access - FixedNestedContainer nested = 9; // Test: nested container navigation (8+32=40 bytes), offset: 45 + FixedNestedContainer nested = 5; // Test: nested container navigation (8+32=40 bytes), offset: 45 // Vector type - test fixed-size array of basic elements - repeated uint64 vector_field = 10 [ (ethereum.eth.ext.ssz_size) = "24" ]; // Test: Vector[24] of uint64 (24*8=192 bytes), offset: 85 + repeated uint64 vector_field = 6 [ (ethereum.eth.ext.ssz_size) = "24" ]; // Test: Vector[24] of uint64 (24*8=192 bytes), offset: 85 // 2D bytes type - test 2-dimensional byte arrays, common in blockchain state roots (e.g., beacon_state.block_roots) - repeated bytes two_dimension_bytes_field = 11 [ (ethereum.eth.ext.ssz_size) = "5,32" ]; // Test: Vector[Bytes32, 5] (32*5=160 bytes), offset: 277 + repeated bytes two_dimension_bytes_field = 7 [ (ethereum.eth.ext.ssz_size) = "5,32" ]; // Test: Vector[Bytes32, 5] (32*5=160 bytes), offset: 277 + + // Bitvector types - test bitfield serialization + bytes bitvector64_field = 8 [ + (ethereum.eth.ext.ssz_size) = "8", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector64" + ]; // Test: Bitvector64 (8 bytes), offset: 437 + + bytes bitvector512_field = 9 [ + (ethereum.eth.ext.ssz_size) = "64", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitvector512" + ]; // Test: Bitvector512 (64 bytes), offset: 445 // Additional bytes field - test field ordering and offset calculation - bytes trailing_field = 12 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: trailing field after vector, offset: 437 + bytes trailing_field = 10 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: trailing field after vector, offset: 509 } // ===== VARIABLE-SIZE TEST CONTAINERS ===== @@ -76,7 +89,14 @@ message VariableTestContainer { // Variable nested container - test nested container access within variable container VariableNestedContainer nested = 5; + // Bitlist type - test bitlist serialization + bytes bitlist_field = 6 [ + (ethereum.eth.ext.ssz_max) = "2048", + (ethereum.eth.ext.cast_type) = + "github.com/prysmaticlabs/go-bitfield.Bitlist" + ]; + // Fixed-size trailing field - test fixed field after variable fields // Verifies correct offset calculation after variable-size fields - bytes trailing_field = 6 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 = 48 + bytes trailing_field = 7 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 + 4 = 52 } diff --git a/proto/ssz_query/ssz_query.ssz.go b/proto/ssz_query/ssz_query.ssz.go index 2cd9dbd77c..2f20bb8c59 100644 --- a/proto/ssz_query/ssz_query.ssz.go +++ b/proto/ssz_query/ssz_query.ssz.go @@ -131,7 +131,21 @@ func (f *FixedTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = append(dst, f.TwoDimensionBytesField[ii]...) } - // Field (7) 'TrailingField' + // Field (7) 'Bitvector64Field' + if size := len(f.Bitvector64Field); size != 8 { + err = ssz.ErrBytesLengthFn("--.Bitvector64Field", size, 8) + return + } + dst = append(dst, f.Bitvector64Field...) + + // Field (8) 'Bitvector512Field' + if size := len(f.Bitvector512Field); size != 64 { + err = ssz.ErrBytesLengthFn("--.Bitvector512Field", size, 64) + return + } + dst = append(dst, f.Bitvector512Field...) + + // Field (9) 'TrailingField' if size := len(f.TrailingField); size != 56 { err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56) return @@ -145,7 +159,7 @@ func (f *FixedTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) { func (f *FixedTestContainer) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size != 493 { + if size != 565 { return ssz.ErrSize } @@ -190,18 +204,30 @@ func (f *FixedTestContainer) UnmarshalSSZ(buf []byte) error { f.TwoDimensionBytesField[ii] = append(f.TwoDimensionBytesField[ii], buf[277:437][ii*32:(ii+1)*32]...) } - // Field (7) 'TrailingField' - if cap(f.TrailingField) == 0 { - f.TrailingField = make([]byte, 0, len(buf[437:493])) + // Field (7) 'Bitvector64Field' + if cap(f.Bitvector64Field) == 0 { + f.Bitvector64Field = make([]byte, 0, len(buf[437:445])) } - f.TrailingField = append(f.TrailingField, buf[437:493]...) + f.Bitvector64Field = append(f.Bitvector64Field, buf[437:445]...) + + // Field (8) 'Bitvector512Field' + if cap(f.Bitvector512Field) == 0 { + f.Bitvector512Field = make([]byte, 0, len(buf[445:509])) + } + f.Bitvector512Field = append(f.Bitvector512Field, buf[445:509]...) + + // Field (9) 'TrailingField' + if cap(f.TrailingField) == 0 { + f.TrailingField = make([]byte, 0, len(buf[509:565])) + } + f.TrailingField = append(f.TrailingField, buf[509:565]...) return err } // SizeSSZ returns the ssz encoded size in bytes for the FixedTestContainer object func (f *FixedTestContainer) SizeSSZ() (size int) { - size = 493 + size = 565 return } @@ -265,7 +291,21 @@ func (f *FixedTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.Merkleize(subIndx) } - // Field (7) 'TrailingField' + // Field (7) 'Bitvector64Field' + if size := len(f.Bitvector64Field); size != 8 { + err = ssz.ErrBytesLengthFn("--.Bitvector64Field", size, 8) + return + } + hh.PutBytes(f.Bitvector64Field) + + // Field (8) 'Bitvector512Field' + if size := len(f.Bitvector512Field); size != 64 { + err = ssz.ErrBytesLengthFn("--.Bitvector512Field", size, 64) + return + } + hh.PutBytes(f.Bitvector512Field) + + // Field (9) 'TrailingField' if size := len(f.TrailingField); size != 56 { err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56) return @@ -393,7 +433,7 @@ func (v *VariableTestContainer) MarshalSSZ() ([]byte, error) { // MarshalSSZTo ssz marshals the VariableTestContainer object to a target array func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(104) + offset := int(108) // Field (0) 'LeadingField' if size := len(v.LeadingField); size != 32 { @@ -421,7 +461,11 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) } offset += v.Nested.SizeSSZ() - // Field (5) 'TrailingField' + // Offset (5) 'BitlistField' + dst = ssz.WriteOffset(dst, offset) + offset += len(v.BitlistField) + + // Field (6) 'TrailingField' if size := len(v.TrailingField); size != 56 { err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56) return @@ -466,6 +510,13 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) return } + // Field (5) 'BitlistField' + if size := len(v.BitlistField); size > 2048 { + err = ssz.ErrBytesLengthFn("--.BitlistField", size, 2048) + return + } + dst = append(dst, v.BitlistField...) + return } @@ -473,12 +524,12 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 104 { + if size < 108 { return ssz.ErrSize } tail := buf - var o1, o2, o3, o4 uint64 + var o1, o2, o3, o4, o5 uint64 // Field (0) 'LeadingField' if cap(v.LeadingField) == 0 { @@ -491,7 +542,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o1 != 104 { + if o1 != 108 { return ssz.ErrInvalidVariableOffset } @@ -510,11 +561,16 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - // Field (5) 'TrailingField' - if cap(v.TrailingField) == 0 { - v.TrailingField = make([]byte, 0, len(buf[48:104])) + // Offset (5) 'BitlistField' + if o5 = ssz.ReadOffset(buf[48:52]); o5 > size || o4 > o5 { + return ssz.ErrOffset } - v.TrailingField = append(v.TrailingField, buf[48:104]...) + + // Field (6) 'TrailingField' + if cap(v.TrailingField) == 0 { + v.TrailingField = make([]byte, 0, len(buf[52:108])) + } + v.TrailingField = append(v.TrailingField, buf[52:108]...) // Field (1) 'FieldListUint64' { @@ -565,7 +621,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { // Field (4) 'Nested' { - buf = tail[o4:] + buf = tail[o4:o5] if v.Nested == nil { v.Nested = new(VariableNestedContainer) } @@ -573,12 +629,24 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { return err } } + + // Field (5) 'BitlistField' + { + buf = tail[o5:] + if err = ssz.ValidateBitlist(buf, 2048); err != nil { + return err + } + if cap(v.BitlistField) == 0 { + v.BitlistField = make([]byte, 0, len(buf)) + } + v.BitlistField = append(v.BitlistField, buf...) + } return err } // SizeSSZ returns the ssz encoded size in bytes for the VariableTestContainer object func (v *VariableTestContainer) SizeSSZ() (size int) { - size = 104 + size = 108 // Field (1) 'FieldListUint64' size += len(v.FieldListUint64) * 8 @@ -595,6 +663,9 @@ func (v *VariableTestContainer) SizeSSZ() (size int) { } size += v.Nested.SizeSSZ() + // Field (5) 'BitlistField' + size += len(v.BitlistField) + return } @@ -670,7 +741,14 @@ func (v *VariableTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } - // Field (5) 'TrailingField' + // Field (5) 'BitlistField' + if len(v.BitlistField) == 0 { + err = ssz.ErrEmptyBitlist + return + } + hh.PutBitlist(v.BitlistField, 2048) + + // Field (6) 'TrailingField' if size := len(v.TrailingField); size != 56 { err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56) return