mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
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
This commit is contained in:
3
changelog/syjn99_ssz-ql-bitlist-bitvector.md
Normal file
3
changelog/syjn99_ssz-ql-bitlist-bitvector.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### Added
|
||||||
|
|
||||||
|
- SSZ-QL: Handle `Bitlist` and `Bitvector` types.
|
||||||
@@ -4,6 +4,8 @@ go_library(
|
|||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"analyzer.go",
|
"analyzer.go",
|
||||||
|
"bitlist.go",
|
||||||
|
"bitvector.go",
|
||||||
"container.go",
|
"container.go",
|
||||||
"list.go",
|
"list.go",
|
||||||
"path.go",
|
"path.go",
|
||||||
@@ -15,6 +17,7 @@ go_library(
|
|||||||
],
|
],
|
||||||
importpath = "github.com/OffchainLabs/prysm/v6/encoding/ssz/query",
|
importpath = "github.com/OffchainLabs/prysm/v6/encoding/ssz/query",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
deps = ["@com_github_prysmaticlabs_go_bitfield//:go_default_library"],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
@@ -30,5 +33,6 @@ go_test(
|
|||||||
"//encoding/ssz/query/testutil:go_default_library",
|
"//encoding/ssz/query/testutil:go_default_library",
|
||||||
"//proto/ssz_query:go_default_library",
|
"//proto/ssz_query:go_default_library",
|
||||||
"//testing/require:go_default_library",
|
"//testing/require:go_default_library",
|
||||||
|
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -67,6 +67,25 @@ func PopulateVariableLengthInfo(sszInfo *sszInfo, value any) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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.
|
// In Container case, we need to recursively populate variable-sized fields.
|
||||||
case Container:
|
case Container:
|
||||||
containerInfo, err := sszInfo.ContainerInfo()
|
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 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
|
// 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 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,
|
// 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")
|
return nil, errors.New("could not determine collection type from tags")
|
||||||
}
|
}
|
||||||
|
|
||||||
// analyzeListType analyzes SSZ List type and returns its SSZ info.
|
// analyzeListType analyzes SSZ List/Bitlist type and returns its SSZ info.
|
||||||
func analyzeListType(typ reflect.Type, elementInfo *sszInfo, limit uint64) (*sszInfo, error) {
|
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 {
|
if elementInfo == nil {
|
||||||
return nil, errors.New("element info is required for List")
|
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
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// analyzeVectorType analyzes SSZ Vector type and returns its SSZ info.
|
// analyzeVectorType analyzes SSZ Vector/Bitvector type and returns its SSZ info.
|
||||||
func analyzeVectorType(typ reflect.Type, elementInfo *sszInfo, length uint64) (*sszInfo, error) {
|
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 {
|
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.
|
// Validate the given length.
|
||||||
|
|||||||
@@ -13,5 +13,5 @@ func TestAnalyzeSSZInfo(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.NotNil(t, info, "Expected non-nil SSZ info")
|
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())
|
||||||
}
|
}
|
||||||
|
|||||||
65
encoding/ssz/query/bitlist.go
Normal file
65
encoding/ssz/query/bitlist.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
15
encoding/ssz/query/bitvector.go
Normal file
15
encoding/ssz/query/bitvector.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/OffchainLabs/prysm/v6/encoding/ssz/query/testutil"
|
"github.com/OffchainLabs/prysm/v6/encoding/ssz/query/testutil"
|
||||||
sszquerypb "github.com/OffchainLabs/prysm/v6/proto/ssz_query"
|
sszquerypb "github.com/OffchainLabs/prysm/v6/proto/ssz_query"
|
||||||
"github.com/OffchainLabs/prysm/v6/testing/require"
|
"github.com/OffchainLabs/prysm/v6/testing/require"
|
||||||
|
"github.com/prysmaticlabs/go-bitfield"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCalculateOffsetAndLength(t *testing.T) {
|
func TestCalculateOffsetAndLength(t *testing.T) {
|
||||||
@@ -80,11 +81,24 @@ func TestCalculateOffsetAndLength(t *testing.T) {
|
|||||||
expectedOffset: 277,
|
expectedOffset: 277,
|
||||||
expectedLength: 160, // 5 * 32 bytes
|
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
|
// Trailing field
|
||||||
{
|
{
|
||||||
name: "trailing_field",
|
name: "trailing_field",
|
||||||
path: ".trailing_field",
|
path: ".trailing_field",
|
||||||
expectedOffset: 437,
|
expectedOffset: 509,
|
||||||
expectedLength: 56,
|
expectedLength: 56,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -119,26 +133,26 @@ func TestCalculateOffsetAndLength(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "field_list_uint64",
|
name: "field_list_uint64",
|
||||||
path: ".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)
|
expectedLength: 40, // 5 elements * uint64 (8 bytes each)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "field_list_container",
|
name: "field_list_container",
|
||||||
path: ".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)
|
expectedLength: 120, // 3 elements * FixedNestedContainer (40 bytes each)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "field_list_bytes32",
|
name: "field_list_bytes32",
|
||||||
path: ".field_list_bytes32",
|
path: ".field_list_bytes32",
|
||||||
expectedOffset: 264,
|
expectedOffset: 268,
|
||||||
expectedLength: 96, // 3 elements * 32 bytes each
|
expectedLength: 96, // 3 elements * 32 bytes each
|
||||||
},
|
},
|
||||||
// Nested paths
|
// Nested paths
|
||||||
{
|
{
|
||||||
name: "nested",
|
name: "nested",
|
||||||
path: ".nested",
|
path: ".nested",
|
||||||
expectedOffset: 360,
|
expectedOffset: 364,
|
||||||
// Calculated with:
|
// Calculated with:
|
||||||
// - Value1: 8 bytes
|
// - Value1: 8 bytes
|
||||||
// - field_list_uint64 offset: 4 bytes
|
// - field_list_uint64 offset: 4 bytes
|
||||||
@@ -148,20 +162,27 @@ func TestCalculateOffsetAndLength(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "nested.value1",
|
name: "nested.value1",
|
||||||
path: ".nested.value1",
|
path: ".nested.value1",
|
||||||
expectedOffset: 360,
|
expectedOffset: 364,
|
||||||
expectedLength: 8,
|
expectedLength: 8,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nested.field_list_uint64",
|
name: "nested.field_list_uint64",
|
||||||
path: ".nested.field_list_uint64",
|
path: ".nested.field_list_uint64",
|
||||||
expectedOffset: 372,
|
expectedOffset: 376,
|
||||||
expectedLength: 40,
|
expectedLength: 40,
|
||||||
},
|
},
|
||||||
|
// Bitlist field
|
||||||
|
{
|
||||||
|
name: "bitlist_field",
|
||||||
|
path: ".bitlist_field",
|
||||||
|
expectedOffset: 416,
|
||||||
|
expectedLength: 33, // 32 bytes + 1 byte for length delimiter
|
||||||
|
},
|
||||||
// Fixed trailing field
|
// Fixed trailing field
|
||||||
{
|
{
|
||||||
name: "trailing_field",
|
name: "trailing_field",
|
||||||
path: ".trailing_field",
|
path: ".trailing_field",
|
||||||
expectedOffset: 48, // After leading_field + 4 offset pointers
|
expectedOffset: 52, // After leading_field + 5 offset pointers
|
||||||
expectedLength: 56,
|
expectedLength: 56,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -208,6 +229,16 @@ func createFixedTestContainer() *sszquerypb.FixedTestContainer {
|
|||||||
nestedValue2[i] = byte(i + 56)
|
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)
|
trailingField := make([]byte, 56)
|
||||||
for i := range trailingField {
|
for i := range trailingField {
|
||||||
trailingField[i] = byte(i + 88)
|
trailingField[i] = byte(i + 88)
|
||||||
@@ -240,6 +271,10 @@ func createFixedTestContainer() *sszquerypb.FixedTestContainer {
|
|||||||
make([]byte, 32),
|
make([]byte, 32),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Bitvector fields
|
||||||
|
Bitvector64Field: bitvector64,
|
||||||
|
Bitvector512Field: bitvector512,
|
||||||
|
|
||||||
// Trailing field
|
// Trailing field
|
||||||
TrailingField: trailingField,
|
TrailingField: trailingField,
|
||||||
}
|
}
|
||||||
@@ -294,6 +329,15 @@ func getFixedTestContainerSpec() testutil.TestSpec {
|
|||||||
Path: ".two_dimension_bytes_field",
|
Path: ".two_dimension_bytes_field",
|
||||||
Expected: testContainer.TwoDimensionBytesField,
|
Expected: testContainer.TwoDimensionBytesField,
|
||||||
},
|
},
|
||||||
|
// Bitvector fields
|
||||||
|
{
|
||||||
|
Path: ".bitvector64_field",
|
||||||
|
Expected: testContainer.Bitvector64Field,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: ".bitvector512_field",
|
||||||
|
Expected: testContainer.Bitvector512Field,
|
||||||
|
},
|
||||||
// Trailing field
|
// Trailing field
|
||||||
{
|
{
|
||||||
Path: ".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{
|
return &sszquerypb.VariableTestContainer{
|
||||||
// Fixed leading field
|
// Fixed leading field
|
||||||
LeadingField: leadingField,
|
LeadingField: leadingField,
|
||||||
@@ -345,6 +396,9 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer {
|
|||||||
FieldListUint64: []uint64{1, 2, 3, 4, 5},
|
FieldListUint64: []uint64{1, 2, 3, 4, 5},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Bitlist field
|
||||||
|
BitlistField: bitlistField,
|
||||||
|
|
||||||
// Fixed trailing field
|
// Fixed trailing field
|
||||||
TrailingField: trailingField,
|
TrailingField: trailingField,
|
||||||
}
|
}
|
||||||
@@ -391,6 +445,11 @@ func getVariableTestContainerSpec() testutil.TestSpec {
|
|||||||
Path: ".nested.field_list_uint64",
|
Path: ".nested.field_list_uint64",
|
||||||
Expected: testContainer.Nested.FieldListUint64,
|
Expected: testContainer.Nested.FieldListUint64,
|
||||||
},
|
},
|
||||||
|
// Bitlist field
|
||||||
|
{
|
||||||
|
Path: ".bitlist_field",
|
||||||
|
Expected: testContainer.BitlistField,
|
||||||
|
},
|
||||||
// Fixed trailing field
|
// Fixed trailing field
|
||||||
{
|
{
|
||||||
Path: ".trailing_field",
|
Path: ".trailing_field",
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ type sszInfo struct {
|
|||||||
|
|
||||||
// For Vector types.
|
// For Vector types.
|
||||||
vectorInfo *vectorInfo
|
vectorInfo *vectorInfo
|
||||||
|
|
||||||
|
// For Bitlist types.
|
||||||
|
bitlistInfo *bitlistInfo
|
||||||
|
|
||||||
|
// For Bitvector types.
|
||||||
|
bitvectorInfo *bitvectorInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (info *sszInfo) FixedSize() uint64 {
|
func (info *sszInfo) FixedSize() uint64 {
|
||||||
@@ -53,6 +59,9 @@ func (info *sszInfo) Size() uint64 {
|
|||||||
|
|
||||||
return length * elementSize
|
return length * elementSize
|
||||||
|
|
||||||
|
case Bitlist:
|
||||||
|
return info.bitlistInfo.Size()
|
||||||
|
|
||||||
case Container:
|
case Container:
|
||||||
size := info.fixedSize
|
size := info.fixedSize
|
||||||
for _, fieldInfo := range info.containerInfo.fields {
|
for _, fieldInfo := range info.containerInfo.fields {
|
||||||
@@ -65,7 +74,6 @@ func (info *sszInfo) Size() uint64 {
|
|||||||
return size
|
return size
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// NOTE: Handle other variable-sized types.
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,6 +118,30 @@ func (info *sszInfo) VectorInfo() (*vectorInfo, error) {
|
|||||||
return info.vectorInfo, nil
|
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.
|
// String implements the Stringer interface for sszInfo.
|
||||||
// This follows the notation used in the consensus specs.
|
// This follows the notation used in the consensus specs.
|
||||||
func (info *sszInfo) String() string {
|
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("Bytes%d", info.vectorInfo.length)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("Vector[%s, %d]", info.vectorInfo.element, 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:
|
default:
|
||||||
return info.typ.Name()
|
return info.typ.Name()
|
||||||
}
|
}
|
||||||
@@ -175,6 +211,9 @@ func printRecursive(info *sszInfo, builder *strings.Builder, prefix string) {
|
|||||||
case List:
|
case List:
|
||||||
builder.WriteString(fmt.Sprintf("%s (%s / length: %d, size: %d)\n", info, sizeDesc, info.listInfo.length, info.Size()))
|
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:
|
default:
|
||||||
builder.WriteString(fmt.Sprintf("%s (%s / size: %d)\n", info, sizeDesc, info.Size()))
|
builder.WriteString(fmt.Sprintf("%s (%s / size: %d)\n", info, sizeDesc, info.Size()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ const (
|
|||||||
// sszSizeTag specifies the length of a fixed-sized collection, like an SSZ Vector.
|
// sszSizeTag specifies the length of a fixed-sized collection, like an SSZ Vector.
|
||||||
// A wildcard ('?') indicates that the dimension is variable-sized (a List).
|
// A wildcard ('?') indicates that the dimension is variable-sized (a List).
|
||||||
sszSizeTag = "ssz-size"
|
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.
|
// SSZDimension holds parsed SSZ tag information for current dimension.
|
||||||
@@ -22,6 +26,9 @@ const (
|
|||||||
type SSZDimension struct {
|
type SSZDimension struct {
|
||||||
vectorLength *uint64
|
vectorLength *uint64
|
||||||
listLimit *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`)
|
// 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 newTagParts []string
|
||||||
var sizeStr, maxStr string
|
var sizeStr, maxStr string
|
||||||
|
var isBitfield bool
|
||||||
|
|
||||||
|
if castType := tag.Get(castTypeTag); strings.Contains(castType, "go-bitfield") {
|
||||||
|
isBitfield = true
|
||||||
|
}
|
||||||
|
|
||||||
// Parse ssz-size tag
|
// Parse ssz-size tag
|
||||||
if sszSize := tag.Get(sszSizeTag); sszSize != "" {
|
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 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.
|
// 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 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.
|
// IsVector returns true if this dimension represents a vector.
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ go_library(
|
|||||||
"//encoding/ssz/query:go_default_library",
|
"//encoding/ssz/query:go_default_library",
|
||||||
"//testing/require:go_default_library",
|
"//testing/require:go_default_library",
|
||||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||||
|
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package testutil
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
ssz "github.com/prysmaticlabs/fastssz"
|
ssz "github.com/prysmaticlabs/fastssz"
|
||||||
|
"github.com/prysmaticlabs/go-bitfield"
|
||||||
)
|
)
|
||||||
|
|
||||||
// marshalAny marshals any value into SSZ format.
|
// 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
|
// 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() {
|
switch valueType.Kind() {
|
||||||
case reflect.Uint64:
|
case reflect.Uint64:
|
||||||
return ssz.MarshalUint64(make([]byte, 0), reflect.ValueOf(value).Uint()), nil
|
return ssz.MarshalUint64(make([]byte, 0), reflect.ValueOf(value).Uint()), nil
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ go_proto_library(
|
|||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//proto/eth/ext:go_default_library",
|
"//proto/eth/ext:go_default_library",
|
||||||
|
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||||
"@com_github_golang_protobuf//proto:go_default_library",
|
"@com_github_golang_protobuf//proto:go_default_library",
|
||||||
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
|
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
|
||||||
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
|
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
|
||||||
|
|||||||
164
proto/ssz_query/ssz_query.pb.go
generated
164
proto/ssz_query/ssz_query.pb.go
generated
@@ -11,6 +11,7 @@ import (
|
|||||||
sync "sync"
|
sync "sync"
|
||||||
|
|
||||||
_ "github.com/OffchainLabs/prysm/v6/proto/eth/ext"
|
_ "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"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
)
|
)
|
||||||
@@ -82,14 +83,16 @@ type FixedTestContainer struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
FieldUint32 uint32 `protobuf:"varint,3,opt,name=field_uint32,json=fieldUint32,proto3" json:"field_uint32,omitempty"`
|
FieldUint32 uint32 `protobuf:"varint,1,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"`
|
FieldUint64 uint64 `protobuf:"varint,2,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"`
|
FieldBool bool `protobuf:"varint,3,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"`
|
FieldBytes32 []byte `protobuf:"bytes,4,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"`
|
Nested *FixedNestedContainer `protobuf:"bytes,5,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"`
|
VectorField []uint64 `protobuf:"varint,6,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"`
|
TwoDimensionBytesField [][]byte `protobuf:"bytes,7,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"`
|
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() {
|
func (x *FixedTestContainer) Reset() {
|
||||||
@@ -173,6 +176,20 @@ func (x *FixedTestContainer) GetTwoDimensionBytesField() [][]byte {
|
|||||||
return nil
|
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 {
|
func (x *FixedTestContainer) GetTrailingField() []byte {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.TrailingField
|
return x.TrailingField
|
||||||
@@ -240,12 +257,13 @@ type VariableTestContainer struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
LeadingField []byte `protobuf:"bytes,1,opt,name=leading_field,json=leadingField,proto3" json:"leading_field,omitempty" ssz-size:"32"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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"`
|
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() {
|
func (x *VariableTestContainer) Reset() {
|
||||||
@@ -315,6 +333,13 @@ func (x *VariableTestContainer) GetNested() *VariableNestedContainer {
|
|||||||
return nil
|
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 {
|
func (x *VariableTestContainer) GetTrailingField() []byte {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.TrailingField
|
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,
|
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,
|
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,
|
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,
|
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,
|
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, 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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x66, 0x0a, 0x11, 0x62,
|
||||||
0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x0c, 0x20,
|
0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x36, 0x34, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64,
|
||||||
0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61,
|
0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x39, 0x82, 0xb5, 0x18, 0x30, 0x67, 0x69, 0x74, 0x68,
|
||||||
0x69, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x66, 0x0a, 0x17, 0x56, 0x61,
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63,
|
||||||
0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74,
|
0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64,
|
||||||
0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x18,
|
0x2e, 0x42, 0x69, 0x74, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x36, 0x34, 0x8a, 0xb5, 0x18, 0x01,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x31, 0x12, 0x33, 0x0a,
|
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,
|
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,
|
0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30,
|
||||||
0x30, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x69, 0x6e, 0x74,
|
0x34, 0x38, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x69, 0x6e,
|
||||||
0x36, 0x34, 0x22, 0x80, 0x03, 0x0a, 0x15, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x54,
|
0x74, 0x36, 0x34, 0x12, 0x5a, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73,
|
||||||
0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x0d,
|
0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28,
|
||||||
0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20,
|
0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69,
|
||||||
0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x6c, 0x65, 0x61,
|
0x78, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||||
0x64, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x34, 0x0a, 0x11, 0x66, 0x69, 0x65,
|
0x65, 0x72, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x12, 0x66, 0x69, 0x65,
|
||||||
0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02,
|
0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12,
|
||||||
0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0f,
|
0x3d, 0x0a, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x62, 0x79,
|
||||||
0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12,
|
0x74, 0x65, 0x73, 0x33, 0x32, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0f, 0x8a, 0xb5, 0x18,
|
||||||
0x5a, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f,
|
0x04, 0x3f, 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x10, 0x66, 0x69,
|
||||||
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
|
0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x12, 0x3a,
|
||||||
0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4e,
|
0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22,
|
||||||
0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x07,
|
0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61,
|
||||||
0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69,
|
0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||||
0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x12, 0x66,
|
0x65, 0x72, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x5d, 0x0a, 0x0d, 0x62, 0x69,
|
||||||
0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x33,
|
0x74, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||||
0x32, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0f, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x33,
|
0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||||
0x32, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x10, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c,
|
0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f,
|
||||||
0x69, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x12, 0x3a, 0x0a, 0x06, 0x6e, 0x65,
|
0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x6c,
|
||||||
0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x73, 0x7a,
|
0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0c, 0x62, 0x69, 0x74,
|
||||||
0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e,
|
0x6c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61,
|
||||||
0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x06,
|
0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||||
0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69,
|
0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c,
|
||||||
0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06,
|
0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68,
|
||||||
0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67,
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c,
|
||||||
0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x73,
|
0x74, 0x6f, 0x2f, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72,
|
||||||
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
|
||||||
0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -20,29 +20,42 @@ message FixedNestedContainer {
|
|||||||
|
|
||||||
// FixedTestContainer - comprehensive fixed-size container for SSZ query testing
|
// FixedTestContainer - comprehensive fixed-size container for SSZ query testing
|
||||||
// Tests: All basic fixed-size SSZ types, nested containers, vectors, offset/length calculations
|
// 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 {
|
message FixedTestContainer {
|
||||||
// Basic integer types - test different integer sizes and their SSZ serialization
|
// Basic integer types - test different integer sizes and their SSZ serialization
|
||||||
uint32 field_uint32 = 3; // Test: uint32 basic type, offset: 0
|
uint32 field_uint32 = 1; // Test: uint32 basic type, offset: 0
|
||||||
uint64 field_uint64 = 4; // Test: uint64 basic type, offset: 4
|
uint64 field_uint64 = 2; // Test: uint64 basic type, offset: 4
|
||||||
|
|
||||||
// Boolean type - test boolean serialization (1 byte in SSZ)
|
// 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
|
// 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
|
// 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
|
// 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)
|
// 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
|
// 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 =====
|
// ===== VARIABLE-SIZE TEST CONTAINERS =====
|
||||||
@@ -76,7 +89,14 @@ message VariableTestContainer {
|
|||||||
// Variable nested container - test nested container access within variable container
|
// Variable nested container - test nested container access within variable container
|
||||||
VariableNestedContainer nested = 5;
|
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
|
// Fixed-size trailing field - test fixed field after variable fields
|
||||||
// Verifies correct offset calculation after variable-size 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,21 @@ func (f *FixedTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
|||||||
dst = append(dst, f.TwoDimensionBytesField[ii]...)
|
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 {
|
if size := len(f.TrailingField); size != 56 {
|
||||||
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
||||||
return
|
return
|
||||||
@@ -145,7 +159,7 @@ func (f *FixedTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
|||||||
func (f *FixedTestContainer) UnmarshalSSZ(buf []byte) error {
|
func (f *FixedTestContainer) UnmarshalSSZ(buf []byte) error {
|
||||||
var err error
|
var err error
|
||||||
size := uint64(len(buf))
|
size := uint64(len(buf))
|
||||||
if size != 493 {
|
if size != 565 {
|
||||||
return ssz.ErrSize
|
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]...)
|
f.TwoDimensionBytesField[ii] = append(f.TwoDimensionBytesField[ii], buf[277:437][ii*32:(ii+1)*32]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Field (7) 'TrailingField'
|
// Field (7) 'Bitvector64Field'
|
||||||
if cap(f.TrailingField) == 0 {
|
if cap(f.Bitvector64Field) == 0 {
|
||||||
f.TrailingField = make([]byte, 0, len(buf[437:493]))
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SizeSSZ returns the ssz encoded size in bytes for the FixedTestContainer object
|
// SizeSSZ returns the ssz encoded size in bytes for the FixedTestContainer object
|
||||||
func (f *FixedTestContainer) SizeSSZ() (size int) {
|
func (f *FixedTestContainer) SizeSSZ() (size int) {
|
||||||
size = 493
|
size = 565
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +291,21 @@ func (f *FixedTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
|||||||
hh.Merkleize(subIndx)
|
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 {
|
if size := len(f.TrailingField); size != 56 {
|
||||||
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
||||||
return
|
return
|
||||||
@@ -393,7 +433,7 @@ func (v *VariableTestContainer) MarshalSSZ() ([]byte, error) {
|
|||||||
// MarshalSSZTo ssz marshals the VariableTestContainer object to a target array
|
// MarshalSSZTo ssz marshals the VariableTestContainer object to a target array
|
||||||
func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||||
dst = buf
|
dst = buf
|
||||||
offset := int(104)
|
offset := int(108)
|
||||||
|
|
||||||
// Field (0) 'LeadingField'
|
// Field (0) 'LeadingField'
|
||||||
if size := len(v.LeadingField); size != 32 {
|
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()
|
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 {
|
if size := len(v.TrailingField); size != 56 {
|
||||||
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
||||||
return
|
return
|
||||||
@@ -466,6 +510,13 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Field (5) 'BitlistField'
|
||||||
|
if size := len(v.BitlistField); size > 2048 {
|
||||||
|
err = ssz.ErrBytesLengthFn("--.BitlistField", size, 2048)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dst = append(dst, v.BitlistField...)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,12 +524,12 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
|
|||||||
func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
||||||
var err error
|
var err error
|
||||||
size := uint64(len(buf))
|
size := uint64(len(buf))
|
||||||
if size < 104 {
|
if size < 108 {
|
||||||
return ssz.ErrSize
|
return ssz.ErrSize
|
||||||
}
|
}
|
||||||
|
|
||||||
tail := buf
|
tail := buf
|
||||||
var o1, o2, o3, o4 uint64
|
var o1, o2, o3, o4, o5 uint64
|
||||||
|
|
||||||
// Field (0) 'LeadingField'
|
// Field (0) 'LeadingField'
|
||||||
if cap(v.LeadingField) == 0 {
|
if cap(v.LeadingField) == 0 {
|
||||||
@@ -491,7 +542,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
|||||||
return ssz.ErrOffset
|
return ssz.ErrOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
if o1 != 104 {
|
if o1 != 108 {
|
||||||
return ssz.ErrInvalidVariableOffset
|
return ssz.ErrInvalidVariableOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,11 +561,16 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
|||||||
return ssz.ErrOffset
|
return ssz.ErrOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Field (5) 'TrailingField'
|
// Offset (5) 'BitlistField'
|
||||||
if cap(v.TrailingField) == 0 {
|
if o5 = ssz.ReadOffset(buf[48:52]); o5 > size || o4 > o5 {
|
||||||
v.TrailingField = make([]byte, 0, len(buf[48:104]))
|
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'
|
// Field (1) 'FieldListUint64'
|
||||||
{
|
{
|
||||||
@@ -565,7 +621,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
|||||||
|
|
||||||
// Field (4) 'Nested'
|
// Field (4) 'Nested'
|
||||||
{
|
{
|
||||||
buf = tail[o4:]
|
buf = tail[o4:o5]
|
||||||
if v.Nested == nil {
|
if v.Nested == nil {
|
||||||
v.Nested = new(VariableNestedContainer)
|
v.Nested = new(VariableNestedContainer)
|
||||||
}
|
}
|
||||||
@@ -573,12 +629,24 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
|
|||||||
return err
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SizeSSZ returns the ssz encoded size in bytes for the VariableTestContainer object
|
// SizeSSZ returns the ssz encoded size in bytes for the VariableTestContainer object
|
||||||
func (v *VariableTestContainer) SizeSSZ() (size int) {
|
func (v *VariableTestContainer) SizeSSZ() (size int) {
|
||||||
size = 104
|
size = 108
|
||||||
|
|
||||||
// Field (1) 'FieldListUint64'
|
// Field (1) 'FieldListUint64'
|
||||||
size += len(v.FieldListUint64) * 8
|
size += len(v.FieldListUint64) * 8
|
||||||
@@ -595,6 +663,9 @@ func (v *VariableTestContainer) SizeSSZ() (size int) {
|
|||||||
}
|
}
|
||||||
size += v.Nested.SizeSSZ()
|
size += v.Nested.SizeSSZ()
|
||||||
|
|
||||||
|
// Field (5) 'BitlistField'
|
||||||
|
size += len(v.BitlistField)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,7 +741,14 @@ func (v *VariableTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
|||||||
return
|
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 {
|
if size := len(v.TrailingField); size != 56 {
|
||||||
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user