diff --git a/changelog/syjn99_ssz-ql-index-accessing.md b/changelog/syjn99_ssz-ql-index-accessing.md new file mode 100644 index 0000000000..1ebefa4965 --- /dev/null +++ b/changelog/syjn99_ssz-ql-index-accessing.md @@ -0,0 +1,3 @@ +### Added + +- SSZ-QL: Access n-th element in `List`/`Vector`. diff --git a/encoding/ssz/query/path.go b/encoding/ssz/query/path.go index 4fd976828d..a45ed171d3 100644 --- a/encoding/ssz/query/path.go +++ b/encoding/ssz/query/path.go @@ -2,12 +2,16 @@ package query import ( "errors" + "fmt" + "strconv" "strings" ) // PathElement represents a single element in a path. type PathElement struct { Name string + // [Optional] Index for List/Vector elements + Index *uint64 } func ParsePath(rawPath string) ([]PathElement, error) { @@ -24,7 +28,34 @@ func ParsePath(rawPath string) ([]PathElement, error) { var path []PathElement for _, elem := range rawElements { - path = append(path, PathElement{Name: elem}) + if elem == "" { + return nil, errors.New("invalid path: consecutive dots or trailing dot") + } + + fieldName := elem + var index *uint64 + + // Check for index notation, e.g., "field[0]" + if strings.Contains(elem, "[") { + parts := strings.SplitN(elem, "[", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("invalid index notation in path element %s", elem) + } + + fieldName = parts[0] + indexPart := strings.TrimSuffix(parts[1], "]") + if indexPart == "" { + return nil, errors.New("index cannot be empty") + } + + indexValue, err := strconv.ParseUint(indexPart, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid index in path element %s: %w", elem, err) + } + index = &indexValue + } + + path = append(path, PathElement{Name: fieldName, Index: index}) } return path, nil diff --git a/encoding/ssz/query/query.go b/encoding/ssz/query/query.go index c19ec94b20..62eb6810ee 100644 --- a/encoding/ssz/query/query.go +++ b/encoding/ssz/query/query.go @@ -19,7 +19,7 @@ func CalculateOffsetAndLength(sszInfo *sszInfo, path []PathElement) (*sszInfo, u walk := sszInfo offset := uint64(0) - for _, elem := range path { + for pathIndex, elem := range path { containerInfo, err := walk.ContainerInfo() if err != nil { return nil, 0, 0, fmt.Errorf("could not get field infos: %w", err) @@ -32,6 +32,51 @@ func CalculateOffsetAndLength(sszInfo *sszInfo, path []PathElement) (*sszInfo, u offset += fieldInfo.offset walk = fieldInfo.sszInfo + + // Check for accessing List/Vector elements by index + if elem.Index != nil { + switch walk.sszType { + case List: + index := *elem.Index + listInfo := walk.listInfo + if index >= listInfo.length { + return nil, 0, 0, fmt.Errorf("index %d out of bounds for field %s with size %d", index, elem.Name, listInfo.length) + } + + walk = listInfo.element + if walk.isVariable { + // Cumulative sum of sizes of previous elements to get the offset. + for i := range index { + offset += listInfo.elementSizes[i] + } + + // NOTE: When populating recursively, the shared element template is updated for each + // list item, causing it to retain the size information of the last processed element. + // This wouldn't be an issue if this is in the middle of the path, as the walk would be updated + // to the next field's sszInfo, which would have the correct size information. + // However, if this is the last element in the path, we need to ensure we return the correct size + // for the indexed element. Hence, we return the size from elementSizes. + if pathIndex == len(path)-1 { + return walk, offset, listInfo.elementSizes[index], nil + } + } else { + offset += index * listInfo.element.Size() + } + + case Vector: + index := *elem.Index + vectorInfo := walk.vectorInfo + if index >= vectorInfo.length { + return nil, 0, 0, fmt.Errorf("index %d out of bounds for field %s with size %d", index, elem.Name, vectorInfo.length) + } + + offset += index * vectorInfo.element.Size() + walk = vectorInfo.element + + default: + return nil, 0, 0, fmt.Errorf("field %s of type %s does not support index access", elem.Name, walk.sszType) + } + } } return walk, offset, walk.Size(), nil diff --git a/encoding/ssz/query/query_test.go b/encoding/ssz/query/query_test.go index 0b11a57556..a84046b597 100644 --- a/encoding/ssz/query/query_test.go +++ b/encoding/ssz/query/query_test.go @@ -25,7 +25,7 @@ func TestSize(t *testing.T) { { name: "VariableTestContainer", obj: &sszquerypb.VariableTestContainer{}, - expectedSize: 128, + expectedSize: 132, }, } @@ -102,6 +102,19 @@ func TestCalculateOffsetAndLength(t *testing.T) { expectedOffset: 85, expectedLength: 192, // 24 * 8 bytes }, + // Accessing an element in the vector + { + name: "vector field (0th element)", + path: ".vector_field[0]", + expectedOffset: 85, + expectedLength: 8, + }, + { + name: "vector field (10th element)", + path: ".vector_field[10]", + expectedOffset: 165, + expectedLength: 8, + }, // 2D bytes field { name: "two_dimension_bytes_field", @@ -109,6 +122,13 @@ func TestCalculateOffsetAndLength(t *testing.T) { expectedOffset: 277, expectedLength: 160, // 5 * 32 bytes }, + // Accessing an element in the 2D bytes field + { + name: "two_dimension_bytes_field (1st element)", + path: ".two_dimension_bytes_field[1]", + expectedOffset: 309, + expectedLength: 32, + }, // Bitvector fields { name: "bitvector64_field", @@ -161,26 +181,53 @@ func TestCalculateOffsetAndLength(t *testing.T) { { name: "field_list_uint64", path: ".field_list_uint64", - expectedOffset: 112, // First part of variable-sized type. + expectedOffset: 116, // First part of variable-sized type. expectedLength: 40, // 5 elements * uint64 (8 bytes each) }, + // Accessing an element in the list + { + name: "field_list_uint64 (2nd element)", + path: ".field_list_uint64[2]", + expectedOffset: 132, + expectedLength: 8, + }, { name: "field_list_container", path: ".field_list_container", - expectedOffset: 152, // Second part of variable-sized type. + expectedOffset: 156, // Second part of variable-sized type. expectedLength: 120, // 3 elements * FixedNestedContainer (40 bytes each) }, + // Accessing an element in the list of containers + { + name: "field_list_container (1st element)", + path: ".field_list_container[1]", + expectedOffset: 196, + expectedLength: 40, + }, { name: "field_list_bytes32", path: ".field_list_bytes32", - expectedOffset: 272, + expectedOffset: 276, expectedLength: 96, // 3 elements * 32 bytes each }, + // Accessing an element in the list of bytes32 + { + name: "field_list_bytes32 (0th element)", + path: ".field_list_bytes32[0]", + expectedOffset: 276, + expectedLength: 32, + }, + { + name: "field_list_bytes32 (2nd element)", + path: ".field_list_bytes32[2]", + expectedOffset: 340, + expectedLength: 32, + }, // Nested paths { name: "nested", path: ".nested", - expectedOffset: 368, + expectedOffset: 372, // Calculated with: // - Value1: 8 bytes // - field_list_uint64 offset: 4 bytes @@ -194,40 +241,85 @@ func TestCalculateOffsetAndLength(t *testing.T) { { name: "nested.value1", path: ".nested.value1", - expectedOffset: 368, + expectedOffset: 372, expectedLength: 8, }, { name: "nested.field_list_uint64", path: ".nested.field_list_uint64", - expectedOffset: 384, + expectedOffset: 388, expectedLength: 40, }, + { + name: "nested.field_list_uint64 (3rd element)", + path: ".nested.field_list_uint64[3]", + expectedOffset: 412, + expectedLength: 8, + }, { name: "nested.nested_list_field", path: ".nested.nested_list_field", - expectedOffset: 436, + expectedOffset: 440, expectedLength: 99, }, + // Accessing an element in the nested list of bytes + { + name: "nested.nested_list_field (1st element)", + path: ".nested.nested_list_field[1]", + expectedOffset: 472, + expectedLength: 33, + }, + { + name: "nested.nested_list_field (2nd element)", + path: ".nested.nested_list_field[2]", + expectedOffset: 505, + expectedLength: 34, + }, + // Variable list of variable-sized containers + { + name: "variable_container_list", + path: ".variable_container_list", + expectedOffset: 547, + expectedLength: 604, + }, // Bitlist field { name: "bitlist_field", path: ".bitlist_field", - expectedOffset: 535, + expectedOffset: 1151, expectedLength: 33, // 32 bytes + 1 byte for length delimiter }, // 2D bytes field { name: "nested_list_field", path: ".nested_list_field", - expectedOffset: 580, + expectedOffset: 1196, expectedLength: 99, }, + // Accessing an element in the list of nested bytes + { + name: "nested_list_field (0th element)", + path: ".nested_list_field[0]", + expectedOffset: 1196, + expectedLength: 32, + }, + { + name: "nested_list_field (1st element)", + path: ".nested_list_field[1]", + expectedOffset: 1228, + expectedLength: 33, + }, + { + name: "nested_list_field (2nd element)", + path: ".nested_list_field[2]", + expectedOffset: 1261, + expectedLength: 34, + }, // Fixed trailing field { name: "trailing_field", path: ".trailing_field", - expectedOffset: 56, // After leading_field + 6 offset pointers + expectedOffset: 60, // After leading_field + 7 offset pointers expectedLength: 56, }, } @@ -419,11 +511,27 @@ func getFixedTestContainerSpec() testutil.TestSpec { Path: ".vector_field", Expected: testContainer.VectorField, }, + { + Path: ".vector_field[0]", + Expected: testContainer.VectorField[0], + }, + { + Path: ".vector_field[10]", + Expected: testContainer.VectorField[10], + }, // 2D bytes field { Path: ".two_dimension_bytes_field", Expected: testContainer.TwoDimensionBytesField, }, + { + Path: ".two_dimension_bytes_field[0]", + Expected: testContainer.TwoDimensionBytesField[0], + }, + { + Path: ".two_dimension_bytes_field[1]", + Expected: testContainer.TwoDimensionBytesField[1], + }, // Bitvector fields { Path: ".bitvector64_field", @@ -481,6 +589,28 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer { } } + // Two VariableOuterContainer elements, each with two VariableInnerContainer elements + variableContainerList := make([]*sszquerypb.VariableOuterContainer, 2) + for i := range variableContainerList { + // Inner1: 8 + 4 + 4 + (8*3) + (4*3) + 99 = 151 bytes + inner1 := &sszquerypb.VariableNestedContainer{ + Value1: 42, + FieldListUint64: []uint64{uint64(i), uint64(i + 1), uint64(i + 2)}, + NestedListField: nestedListField, + } + // Inner2: 8 + 4 + 4 + (8*2) + (4*3) + 99 = 143 bytes + inner2 := &sszquerypb.VariableNestedContainer{ + Value1: 84, + FieldListUint64: []uint64{uint64(i + 3), uint64(i + 4)}, + NestedListField: nestedListField, + } + // (4*2) + 151 + 143 = 302 bytes per VariableOuterContainer + variableContainerList[i] = &sszquerypb.VariableOuterContainer{ + Inner_1: inner1, + Inner_2: inner2, + } + } + return &sszquerypb.VariableTestContainer{ // Fixed leading field LeadingField: leadingField, @@ -501,6 +631,9 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer { NestedListField: nestedListField, }, + // Variable list of variable-sized containers + VariableContainerList: variableContainerList, + // Bitlist field BitlistField: bitlistField, @@ -530,11 +663,24 @@ func getVariableTestContainerSpec() testutil.TestSpec { Path: ".field_list_uint64", Expected: testContainer.FieldListUint64, }, + { + Path: ".field_list_uint64[2]", + Expected: testContainer.FieldListUint64[2], + }, // Variable-size list of (fixed-size) containers { Path: ".field_list_container", Expected: testContainer.FieldListContainer, }, + // Accessing an element in the list of containers + { + Path: ".field_list_container[0]", + Expected: testContainer.FieldListContainer[0], + }, + { + Path: ".field_list_container[1]", + Expected: testContainer.FieldListContainer[1], + }, // Variable-size list of bytes32 { Path: ".field_list_bytes32", @@ -553,10 +699,55 @@ func getVariableTestContainerSpec() testutil.TestSpec { Path: ".nested.field_list_uint64", Expected: testContainer.Nested.FieldListUint64, }, + { + Path: ".nested.field_list_uint64[3]", + Expected: testContainer.Nested.FieldListUint64[3], + }, { Path: ".nested.nested_list_field", Expected: testContainer.Nested.NestedListField, }, + { + Path: ".nested.nested_list_field[0]", + Expected: testContainer.Nested.NestedListField[0], + }, + { + Path: ".nested.nested_list_field[1]", + Expected: testContainer.Nested.NestedListField[1], + }, + { + Path: ".nested.nested_list_field[2]", + Expected: testContainer.Nested.NestedListField[2], + }, + // Variable list of variable-sized containers + { + Path: ".variable_container_list", + Expected: testContainer.VariableContainerList, + }, + { + Path: ".variable_container_list[0]", + Expected: testContainer.VariableContainerList[0], + }, + { + Path: ".variable_container_list[0].inner_1.field_list_uint64[1]", + Expected: testContainer.VariableContainerList[0].Inner_1.FieldListUint64[1], + }, + { + Path: ".variable_container_list[0].inner_2.field_list_uint64[1]", + Expected: testContainer.VariableContainerList[0].Inner_2.FieldListUint64[1], + }, + { + Path: ".variable_container_list[1]", + Expected: testContainer.VariableContainerList[1], + }, + { + Path: ".variable_container_list[1].inner_1.field_list_uint64[1]", + Expected: testContainer.VariableContainerList[1].Inner_1.FieldListUint64[1], + }, + { + Path: ".variable_container_list[1].inner_2.field_list_uint64[1]", + Expected: testContainer.VariableContainerList[1].Inner_2.FieldListUint64[1], + }, // Bitlist field { Path: ".bitlist_field", @@ -567,6 +758,18 @@ func getVariableTestContainerSpec() testutil.TestSpec { Path: ".nested_list_field", Expected: testContainer.NestedListField, }, + { + Path: ".nested_list_field[0]", + Expected: testContainer.NestedListField[0], + }, + { + Path: ".nested_list_field[1]", + Expected: testContainer.NestedListField[1], + }, + { + Path: ".nested_list_field[2]", + Expected: testContainer.NestedListField[2], + }, // Fixed trailing field { Path: ".trailing_field", diff --git a/proto/ssz_query/ssz_query.pb.go b/proto/ssz_query/ssz_query.pb.go index 3d273eeeb1..6b9d5bd7d5 100755 --- a/proto/ssz_query/ssz_query.pb.go +++ b/proto/ssz_query/ssz_query.pb.go @@ -251,23 +251,76 @@ func (x *VariableNestedContainer) GetNestedListField() [][]byte { return nil } +type VariableOuterContainer struct { + state protoimpl.MessageState `protogen:"open.v1"` + Inner_1 *VariableNestedContainer `protobuf:"bytes,1,opt,name=inner_1,json=inner1,proto3" json:"inner_1,omitempty"` + Inner_2 *VariableNestedContainer `protobuf:"bytes,2,opt,name=inner_2,json=inner2,proto3" json:"inner_2,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VariableOuterContainer) Reset() { + *x = VariableOuterContainer{} + mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VariableOuterContainer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VariableOuterContainer) ProtoMessage() {} + +func (x *VariableOuterContainer) ProtoReflect() protoreflect.Message { + mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VariableOuterContainer.ProtoReflect.Descriptor instead. +func (*VariableOuterContainer) Descriptor() ([]byte, []int) { + return file_proto_ssz_query_ssz_query_proto_rawDescGZIP(), []int{3} +} + +func (x *VariableOuterContainer) GetInner_1() *VariableNestedContainer { + if x != nil { + return x.Inner_1 + } + return nil +} + +func (x *VariableOuterContainer) GetInner_2() *VariableNestedContainer { + if x != nil { + return x.Inner_2 + } + return nil +} + type VariableTestContainer struct { - state protoimpl.MessageState `protogen:"open.v1"` - 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"` - NestedListField [][]byte `protobuf:"bytes,7,rep,name=nested_list_field,json=nestedListField,proto3" json:"nested_list_field,omitempty" ssz-max:"100,50" ssz-size:"?,?"` - TrailingField []byte `protobuf:"bytes,8,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + 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"` + VariableContainerList []*VariableOuterContainer `protobuf:"bytes,6,rep,name=variable_container_list,json=variableContainerList,proto3" json:"variable_container_list,omitempty" ssz-max:"10"` + BitlistField github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,7,opt,name=bitlist_field,json=bitlistField,proto3" json:"bitlist_field,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"2048"` + NestedListField [][]byte `protobuf:"bytes,8,rep,name=nested_list_field,json=nestedListField,proto3" json:"nested_list_field,omitempty" ssz-max:"100,50" ssz-size:"?,?"` + TrailingField []byte `protobuf:"bytes,9,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *VariableTestContainer) Reset() { *x = VariableTestContainer{} - mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3] + mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -279,7 +332,7 @@ func (x *VariableTestContainer) String() string { func (*VariableTestContainer) ProtoMessage() {} func (x *VariableTestContainer) ProtoReflect() protoreflect.Message { - mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3] + mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -292,7 +345,7 @@ func (x *VariableTestContainer) ProtoReflect() protoreflect.Message { // Deprecated: Use VariableTestContainer.ProtoReflect.Descriptor instead. func (*VariableTestContainer) Descriptor() ([]byte, []int) { - return file_proto_ssz_query_ssz_query_proto_rawDescGZIP(), []int{3} + return file_proto_ssz_query_ssz_query_proto_rawDescGZIP(), []int{4} } func (x *VariableTestContainer) GetLeadingField() []byte { @@ -330,6 +383,13 @@ func (x *VariableTestContainer) GetNested() *VariableNestedContainer { return nil } +func (x *VariableTestContainer) GetVariableContainerList() []*VariableOuterContainer { + if x != nil { + return x.VariableContainerList + } + return nil +} + func (x *VariableTestContainer) GetBitlistField() github_com_prysmaticlabs_go_bitfield.Bitlist { if x != nil { return x.BitlistField @@ -411,45 +471,60 @@ var file_proto_ssz_query_ssz_query_proto_rawDesc = []byte{ 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5, 0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18, 0x06, 0x31, 0x30, 0x30, 0x2c, 0x35, 0x30, 0x52, 0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c, 0x69, 0x73, - 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x9e, 0x04, 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, 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, 0x3d, 0x0a, 0x11, 0x6e, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x07, - 0x20, 0x03, 0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5, 0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18, - 0x06, 0x31, 0x30, 0x30, 0x2c, 0x35, 0x30, 0x52, 0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c, - 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, 0x08, 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, + 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x92, 0x01, 0x0a, 0x16, 0x56, 0x61, 0x72, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x31, 0x18, 0x01, 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, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x31, 0x12, 0x3b, + 0x0a, 0x07, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x32, 0x18, 0x02, 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, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x32, 0x22, 0x81, 0x05, 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, + 0x61, 0x0a, 0x17, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72, + 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x30, 0x52, 0x15, 0x76, 0x61, 0x72, + 0x69, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0d, 0x62, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x18, 0x07, 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, 0x3d, 0x0a, 0x11, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, + 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5, + 0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18, 0x06, 0x31, 0x30, 0x30, 0x2c, 0x35, 0x30, 0x52, + 0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c, 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, 0x09, 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 ( @@ -464,22 +539,26 @@ func file_proto_ssz_query_ssz_query_proto_rawDescGZIP() []byte { return file_proto_ssz_query_ssz_query_proto_rawDescData } -var file_proto_ssz_query_ssz_query_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_proto_ssz_query_ssz_query_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_proto_ssz_query_ssz_query_proto_goTypes = []any{ (*FixedNestedContainer)(nil), // 0: ssz_query.FixedNestedContainer (*FixedTestContainer)(nil), // 1: ssz_query.FixedTestContainer (*VariableNestedContainer)(nil), // 2: ssz_query.VariableNestedContainer - (*VariableTestContainer)(nil), // 3: ssz_query.VariableTestContainer + (*VariableOuterContainer)(nil), // 3: ssz_query.VariableOuterContainer + (*VariableTestContainer)(nil), // 4: ssz_query.VariableTestContainer } var file_proto_ssz_query_ssz_query_proto_depIdxs = []int32{ 0, // 0: ssz_query.FixedTestContainer.nested:type_name -> ssz_query.FixedNestedContainer - 0, // 1: ssz_query.VariableTestContainer.field_list_container:type_name -> ssz_query.FixedNestedContainer - 2, // 2: ssz_query.VariableTestContainer.nested:type_name -> ssz_query.VariableNestedContainer - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 2, // 1: ssz_query.VariableOuterContainer.inner_1:type_name -> ssz_query.VariableNestedContainer + 2, // 2: ssz_query.VariableOuterContainer.inner_2:type_name -> ssz_query.VariableNestedContainer + 0, // 3: ssz_query.VariableTestContainer.field_list_container:type_name -> ssz_query.FixedNestedContainer + 2, // 4: ssz_query.VariableTestContainer.nested:type_name -> ssz_query.VariableNestedContainer + 3, // 5: ssz_query.VariableTestContainer.variable_container_list:type_name -> ssz_query.VariableOuterContainer + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_proto_ssz_query_ssz_query_proto_init() } @@ -493,7 +572,7 @@ func file_proto_ssz_query_ssz_query_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_ssz_query_ssz_query_proto_rawDesc, NumEnums: 0, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/ssz_query/ssz_query.proto b/proto/ssz_query/ssz_query.proto index 4fe88515d7..4898eab1cb 100644 --- a/proto/ssz_query/ssz_query.proto +++ b/proto/ssz_query/ssz_query.proto @@ -71,6 +71,13 @@ message VariableNestedContainer { ]; } + +// Mock of AttesterSlashingElectra +message VariableOuterContainer { + VariableNestedContainer inner_1 = 1; + VariableNestedContainer inner_2 = 2; +} + // VariableTestContainer - comprehensive variable-size container for SSZ query testing // Tests: Variable-size lists, offsets in variable containers, mixed fixed/variable fields message VariableTestContainer { @@ -93,8 +100,12 @@ message VariableTestContainer { // Variable nested container - test nested container access within variable container VariableNestedContainer nested = 5; + // List of variable-sized containers + // e.g., BeaconBlockBody.attester_slashings + repeated VariableOuterContainer variable_container_list = 6 [ (ethereum.eth.ext.ssz_max) = "10" ]; // Test: List[VariableOuterContainer, 10] + // Bitlist type - test bitlist serialization - bytes bitlist_field = 6 [ + bytes bitlist_field = 7 [ (ethereum.eth.ext.ssz_max) = "2048", (ethereum.eth.ext.cast_type) = "github.com/prysmaticlabs/go-bitfield.Bitlist" @@ -102,12 +113,12 @@ message VariableTestContainer { // 2D bytes list - test list of bytelists. // e.g., ExecutionPayload.transactions - repeated bytes nested_list_field = 7 [ + repeated bytes nested_list_field = 8 [ (ethereum.eth.ext.ssz_size) = "?,?", (ethereum.eth.ext.ssz_max) = "100,50" ]; // Fixed-size trailing field - test fixed field after variable fields // Verifies correct offset calculation after variable-size fields - bytes trailing_field = 8 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 + 4 + 4 = 56 + bytes trailing_field = 9 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 + 4 + 4 + 4 = 60 } diff --git a/proto/ssz_query/ssz_query.ssz.go b/proto/ssz_query/ssz_query.ssz.go index 677d3db7a9..0a0f65fbc3 100644 --- a/proto/ssz_query/ssz_query.ssz.go +++ b/proto/ssz_query/ssz_query.ssz.go @@ -509,6 +509,134 @@ func (v *VariableNestedContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } +// MarshalSSZ ssz marshals the VariableOuterContainer object +func (v *VariableOuterContainer) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(v) +} + +// MarshalSSZTo ssz marshals the VariableOuterContainer object to a target array +func (v *VariableOuterContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(8) + + // Offset (0) 'Inner_1' + dst = ssz.WriteOffset(dst, offset) + if v.Inner_1 == nil { + v.Inner_1 = new(VariableNestedContainer) + } + offset += v.Inner_1.SizeSSZ() + + // Offset (1) 'Inner_2' + dst = ssz.WriteOffset(dst, offset) + if v.Inner_2 == nil { + v.Inner_2 = new(VariableNestedContainer) + } + offset += v.Inner_2.SizeSSZ() + + // Field (0) 'Inner_1' + if dst, err = v.Inner_1.MarshalSSZTo(dst); err != nil { + return + } + + // Field (1) 'Inner_2' + if dst, err = v.Inner_2.MarshalSSZTo(dst); err != nil { + return + } + + return +} + +// UnmarshalSSZ ssz unmarshals the VariableOuterContainer object +func (v *VariableOuterContainer) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 8 { + return ssz.ErrSize + } + + tail := buf + var o0, o1 uint64 + + // Offset (0) 'Inner_1' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 != 8 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'Inner_2' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Field (0) 'Inner_1' + { + buf = tail[o0:o1] + if v.Inner_1 == nil { + v.Inner_1 = new(VariableNestedContainer) + } + if err = v.Inner_1.UnmarshalSSZ(buf); err != nil { + return err + } + } + + // Field (1) 'Inner_2' + { + buf = tail[o1:] + if v.Inner_2 == nil { + v.Inner_2 = new(VariableNestedContainer) + } + if err = v.Inner_2.UnmarshalSSZ(buf); err != nil { + return err + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the VariableOuterContainer object +func (v *VariableOuterContainer) SizeSSZ() (size int) { + size = 8 + + // Field (0) 'Inner_1' + if v.Inner_1 == nil { + v.Inner_1 = new(VariableNestedContainer) + } + size += v.Inner_1.SizeSSZ() + + // Field (1) 'Inner_2' + if v.Inner_2 == nil { + v.Inner_2 = new(VariableNestedContainer) + } + size += v.Inner_2.SizeSSZ() + + return +} + +// HashTreeRoot ssz hashes the VariableOuterContainer object +func (v *VariableOuterContainer) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(v) +} + +// HashTreeRootWith ssz hashes the VariableOuterContainer object with a hasher +func (v *VariableOuterContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) { + indx := hh.Index() + + // Field (0) 'Inner_1' + if err = v.Inner_1.HashTreeRootWith(hh); err != nil { + return + } + + // Field (1) 'Inner_2' + if err = v.Inner_2.HashTreeRootWith(hh); err != nil { + return + } + + hh.Merkleize(indx) + return +} + // MarshalSSZ ssz marshals the VariableTestContainer object func (v *VariableTestContainer) MarshalSSZ() ([]byte, error) { return ssz.MarshalSSZ(v) @@ -517,7 +645,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(112) + offset := int(116) // Field (0) 'LeadingField' if size := len(v.LeadingField); size != 32 { @@ -545,18 +673,25 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) } offset += v.Nested.SizeSSZ() - // Offset (5) 'BitlistField' + // Offset (5) 'VariableContainerList' + dst = ssz.WriteOffset(dst, offset) + for ii := 0; ii < len(v.VariableContainerList); ii++ { + offset += 4 + offset += v.VariableContainerList[ii].SizeSSZ() + } + + // Offset (6) 'BitlistField' dst = ssz.WriteOffset(dst, offset) offset += len(v.BitlistField) - // Offset (6) 'NestedListField' + // Offset (7) 'NestedListField' dst = ssz.WriteOffset(dst, offset) for ii := 0; ii < len(v.NestedListField); ii++ { offset += 4 offset += len(v.NestedListField[ii]) } - // Field (7) 'TrailingField' + // Field (8) 'TrailingField' if size := len(v.TrailingField); size != 56 { err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56) return @@ -601,14 +736,32 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) return } - // Field (5) 'BitlistField' + // Field (5) 'VariableContainerList' + if size := len(v.VariableContainerList); size > 10 { + err = ssz.ErrListTooBigFn("--.VariableContainerList", size, 10) + return + } + { + offset = 4 * len(v.VariableContainerList) + for ii := 0; ii < len(v.VariableContainerList); ii++ { + dst = ssz.WriteOffset(dst, offset) + offset += v.VariableContainerList[ii].SizeSSZ() + } + } + for ii := 0; ii < len(v.VariableContainerList); ii++ { + if dst, err = v.VariableContainerList[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (6) 'BitlistField' if size := len(v.BitlistField); size > 2048 { err = ssz.ErrBytesLengthFn("--.BitlistField", size, 2048) return } dst = append(dst, v.BitlistField...) - // Field (6) 'NestedListField' + // Field (7) 'NestedListField' if size := len(v.NestedListField); size > 100 { err = ssz.ErrListTooBigFn("--.NestedListField", size, 100) return @@ -635,12 +788,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 < 112 { + if size < 116 { return ssz.ErrSize } tail := buf - var o1, o2, o3, o4, o5, o6 uint64 + var o1, o2, o3, o4, o5, o6, o7 uint64 // Field (0) 'LeadingField' if cap(v.LeadingField) == 0 { @@ -653,7 +806,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o1 != 112 { + if o1 != 116 { return ssz.ErrInvalidVariableOffset } @@ -672,21 +825,26 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - // Offset (5) 'BitlistField' + // Offset (5) 'VariableContainerList' if o5 = ssz.ReadOffset(buf[48:52]); o5 > size || o4 > o5 { return ssz.ErrOffset } - // Offset (6) 'NestedListField' + // Offset (6) 'BitlistField' if o6 = ssz.ReadOffset(buf[52:56]); o6 > size || o5 > o6 { return ssz.ErrOffset } - // Field (7) 'TrailingField' - if cap(v.TrailingField) == 0 { - v.TrailingField = make([]byte, 0, len(buf[56:112])) + // Offset (7) 'NestedListField' + if o7 = ssz.ReadOffset(buf[56:60]); o7 > size || o6 > o7 { + return ssz.ErrOffset } - v.TrailingField = append(v.TrailingField, buf[56:112]...) + + // Field (8) 'TrailingField' + if cap(v.TrailingField) == 0 { + v.TrailingField = make([]byte, 0, len(buf[60:116])) + } + v.TrailingField = append(v.TrailingField, buf[60:116]...) // Field (1) 'FieldListUint64' { @@ -746,9 +904,31 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { } } - // Field (5) 'BitlistField' + // Field (5) 'VariableContainerList' { buf = tail[o5:o6] + num, err := ssz.DecodeDynamicLength(buf, 10) + if err != nil { + return err + } + v.VariableContainerList = make([]*VariableOuterContainer, num) + err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { + if v.VariableContainerList[indx] == nil { + v.VariableContainerList[indx] = new(VariableOuterContainer) + } + if err = v.VariableContainerList[indx].UnmarshalSSZ(buf); err != nil { + return err + } + return nil + }) + if err != nil { + return err + } + } + + // Field (6) 'BitlistField' + { + buf = tail[o6:o7] if err = ssz.ValidateBitlist(buf, 2048); err != nil { return err } @@ -758,9 +938,9 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { v.BitlistField = append(v.BitlistField, buf...) } - // Field (6) 'NestedListField' + // Field (7) 'NestedListField' { - buf = tail[o6:] + buf = tail[o7:] num, err := ssz.DecodeDynamicLength(buf, 100) if err != nil { return err @@ -785,7 +965,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error { // SizeSSZ returns the ssz encoded size in bytes for the VariableTestContainer object func (v *VariableTestContainer) SizeSSZ() (size int) { - size = 112 + size = 116 // Field (1) 'FieldListUint64' size += len(v.FieldListUint64) * 8 @@ -802,10 +982,16 @@ func (v *VariableTestContainer) SizeSSZ() (size int) { } size += v.Nested.SizeSSZ() - // Field (5) 'BitlistField' + // Field (5) 'VariableContainerList' + for ii := 0; ii < len(v.VariableContainerList); ii++ { + size += 4 + size += v.VariableContainerList[ii].SizeSSZ() + } + + // Field (6) 'BitlistField' size += len(v.BitlistField) - // Field (6) 'NestedListField' + // Field (7) 'NestedListField' for ii := 0; ii < len(v.NestedListField); ii++ { size += 4 size += len(v.NestedListField[ii]) @@ -886,14 +1072,30 @@ func (v *VariableTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) { return } - // Field (5) 'BitlistField' + // Field (5) 'VariableContainerList' + { + subIndx := hh.Index() + num := uint64(len(v.VariableContainerList)) + if num > 10 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range v.VariableContainerList { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 10) + } + + // Field (6) 'BitlistField' if len(v.BitlistField) == 0 { err = ssz.ErrEmptyBitlist return } hh.PutBitlist(v.BitlistField, 2048) - // Field (6) 'NestedListField' + // Field (7) 'NestedListField' { subIndx := hh.Index() num := uint64(len(v.NestedListField)) @@ -916,7 +1118,7 @@ func (v *VariableTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) { hh.MerkleizeWithMixin(subIndx, num, 100) } - // Field (7) 'TrailingField' + // Field (8) 'TrailingField' if size := len(v.TrailingField); size != 56 { err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56) return