ssztypes

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 31, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package ssztypes provides SSZ type descriptors, caching, and struct tag parsing for the dynamic-ssz library.

It defines the core type system used to describe how Go types map to SSZ encoding: containers, lists, vectors, bitlists, bitvectors, unions, and all basic SSZ types. Type descriptors are computed from Go reflect types and SSZ struct tags (ssz-size, ssz-max, dynssz-size, dynssz-max, etc.) and cached in a TypeCache for reuse.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseTags added in v1.3.0

func ParseTags(tag string) (typeHints []SszTypeHint, sizeHints []SszSizeHint, maxSizeHints []SszMaxSizeHint, err error)

ParseTags parses SSZ annotations from a string in struct tag format. This is used for extracting SSZ annotations from sources other than struct fields, such as type-level annotations registered via sszutils.Annotate[T]().

Types

type ContainerDescriptor

type ContainerDescriptor struct {
	Fields    []FieldDescriptor    `json:"fields"`     // For structs
	DynFields []DynFieldDescriptor `json:"dyn_fields"` // Dynamic struct fields
}

FieldDescriptor represents a cached descriptor for a struct field

type DynFieldDescriptor

type DynFieldDescriptor struct {
	Field        *FieldDescriptor `json:"field"`
	HeaderOffset uint32           `json:"offset"`
	Index        int16            `json:"index"` // Index of the field in the struct
}

DynFieldDescriptor represents a dynamic field descriptor for a struct

type FieldDescriptor

type FieldDescriptor struct {
	Name       string          `json:"name"`                  // Name of the field (from schema struct)
	Type       *TypeDescriptor `json:"type"`                  // Type descriptor (built from runtime/schema pair)
	SszIndex   uint16          `json:"index,omitempty"`       // SSZ index for progressive containers
	FieldIndex uint16          `json:"field_index,omitempty"` // Index into the runtime struct's field list
}

FieldDescriptor represents a cached descriptor for a struct field. When using view descriptors (schema type differs from runtime type), the FieldIndex points to the corresponding field in the runtime struct, while Name and Type come from the schema struct's field definition.

type GoTypeFlag

type GoTypeFlag uint8

GoTypeFlag is a bitmask indicating Go-specific type properties that affect SSZ encoding behavior.

const (
	GoTypeFlagIsPointer   GoTypeFlag = 1 << iota // Whether the type is a pointer type
	GoTypeFlagIsByteArray                        // Whether the type is a byte array
	GoTypeFlagIsString                           // Whether the type is a string type
	GoTypeFlagIsTime                             // Whether the type is a time.Time type
	GoTypeFlagIsView                             // Whether the type uses a view descriptor
)

type SszCompatFlag

type SszCompatFlag uint16

SszCompatFlag is a flag indicating whether a type implements a specific SSZ compatibility interface

const (
	SszCompatFlagFastSSZMarshaler       SszCompatFlag = 1 << iota // Whether the type implements fastssz.Marshaler
	SszCompatFlagFastSSZHasher                                    // Whether the type implements fastssz.HashRoot
	SszCompatFlagHashTreeRootWith                                 // Whether the type implements HashTreeRootWith
	SszCompatFlagDynamicMarshaler                                 // Whether the type implements DynamicMarshaler
	SszCompatFlagDynamicUnmarshaler                               // Whether the type implements DynamicUnmarshaler
	SszCompatFlagDynamicSizer                                     // Whether the type implements DynamicSizer
	SszCompatFlagDynamicHashRoot                                  // Whether the type implements DynamicHashRoot
	SszCompatFlagDynamicEncoder                                   // Whether the type implements DynamicEncoder
	SszCompatFlagDynamicDecoder                                   // Whether the type implements DynamicDecoder
	SszCompatFlagDynamicViewMarshaler                             // Whether the type implements DynamicViewMarshaler
	SszCompatFlagDynamicViewUnmarshaler                           // Whether the type implements DynamicViewUnmarshaler
	SszCompatFlagDynamicViewSizer                                 // Whether the type implements DynamicViewSizer
	SszCompatFlagDynamicViewHashRoot                              // Whether the type implements DynamicViewHashRoot
	SszCompatFlagDynamicViewEncoder                               // Whether the type implements DynamicViewEncoder
	SszCompatFlagDynamicViewDecoder                               // Whether the type implements DynamicViewDecoder
)

type SszMaxSizeHint

type SszMaxSizeHint struct {
	Size    uint64
	NoValue bool
	Custom  bool
	Expr    string
}

SszMaxSizeHint encapsulates max size information for SSZ encoding and decoding, derived from 'ssz-max'/'ssz-bitmax' and 'dynssz-max'/'dynssz-bitmax' tag annotations. It provides detailed insights into the max size attributes of fields or types, particularly noting whether max sizes are fixed or dynamic, and if special specification values are applied, differing from default assumptions.

Fields:

  • size: A uint64 value indicating the statically annotated max size of the type or field, as specified by 'ssz-max'/'ssz-bitmax' tag annotations. For dynamic fields, where the max size may vary depending on the instance of the data, this field is set to 0, and the dynamic flag is used to indicate its dynamic nature.
  • dynamic: A boolean flag indicating whether the field's max size is dynamic, set to true for fields whose max size can change or is not fixed at compile time. This determination is based on the presence of 'dynssz-max'/'dynssz-bitmax' annotations or the inherent variability of the type.
  • custom: A boolean indicating whether a non-default specification value has been applied to the type or field, typically through 'dynssz-max'/'dynssz-bitmax' annotations, suggesting a deviation from standard max size expectations that might influence the encoding or decoding process.
  • expr: The dynamic expression used to calculate the max size of the field, typically through 'dynssz-max'/'dynssz-bitmax' annotations.

type SszSizeHint

type SszSizeHint struct {
	Size    uint32
	Dynamic bool
	Custom  bool
	Bits    bool
	Expr    string
}

SszSizeHint encapsulates size information for SSZ encoding and decoding, derived from 'ssz-size' and 'dynssz-size' tag annotations. It provides detailed insights into the size attributes of fields or types, particularly noting whether sizes are fixed or dynamic, and if special specification values are applied, differing from default assumptions.

Fields:

  • size: A uint64 value indicating the statically annotated size of the type or field, as specified by 'ssz-size' tag annotations. For dynamic fields, where the size may vary depending on the instance of the data, this field is set to 0, and the dynamic flag is used to indicate its dynamic nature.
  • dynamic: A boolean flag indicating whether the field's size is dynamic, set to true for fields whose size can change or is not fixed at compile time. This determination is based on the presence of 'dynssz-size' annotations or the inherent variability of the type.
  • custom: A boolean indicating whether a non-default specification value has been applied to the type or field, typically through 'dynssz-size' annotations, suggesting a deviation from standard size expectations that might influence the encoding or decoding process.
  • bits: A boolean flag indicating whether the size is in bits rather than bytes.
  • expr: The dynamic expression used to calculate the size of the field, typically through 'dynssz-size' annotations.

type SszType

type SszType uint8

SszType identifies the SSZ encoding type for a field or value. It covers basic types (bool, uintN), complex types (container, list, vector, bitlist, bitvector), progressive types, unions, and extended non-standard types (signed integers, floats, bigint).

const (
	SszUnspecifiedType SszType = iota
	SszCustomType
	SszTypeWrapperType

	// basic types
	SszBoolType
	SszUint8Type
	SszUint16Type
	SszUint32Type
	SszUint64Type
	SszUint128Type
	SszUint256Type

	// complex types
	SszContainerType
	SszListType
	SszVectorType
	SszBitlistType
	SszBitvectorType
	SszProgressiveListType
	SszProgressiveBitlistType
	SszProgressiveContainerType
	SszCompatibleUnionType

	// extended types (not supported by SSZ spec)
	SszInt8Type
	SszInt16Type
	SszInt32Type
	SszInt64Type
	SszBigIntType
	SszFloat32Type
	SszFloat64Type
	SszOptionalType
)

func ParseSszType

func ParseSszType(typeStr string) (SszType, error)

ParseSszType converts an ssz-type tag string value (e.g., "container", "list", "uint64") into the corresponding SszType constant. Returns an error for unrecognized type strings.

type SszTypeFlag

type SszTypeFlag uint8

SszTypeFlag is a flag indicating whether a type has a specific SSZ type feature

const (
	SszTypeFlagIsDynamic      SszTypeFlag = 1 << iota // Whether the type is a dynamic type (or has nested dynamic types)
	SszTypeFlagHasLimit                               // Whether the type has a max size tag
	SszTypeFlagHasDynamicSize                         // Whether this type or any of its nested types uses dynamic spec size value that differs from the default
	SszTypeFlagHasDynamicMax                          // Whether this type or any of its nested types uses dynamic spec max value that differs from the default
	SszTypeFlagHasSizeExpr                            // Whether this type or any of its nested types uses a dynamic expression to calculate the size or max size
	SszTypeFlagHasMaxExpr                             // Whether this type or any of its nested types uses a dynamic expression to calculate the max size
	SszTypeFlagHasBitSize                             // Whether the type has a bit size tag
)

type SszTypeHint

type SszTypeHint struct {
	Type SszType
}

SszTypeHint holds a parsed SSZ type hint from an ssz-type struct tag. Multiple hints may be present for nested types (e.g., a list of vectors).

type TypeCache

type TypeCache struct {
	CompatFlags   map[string]SszCompatFlag
	ExtendedTypes bool
	// contains filtered or unexported fields
}

TypeCache manages cached type descriptors

func NewTypeCache

func NewTypeCache(specs sszutils.DynamicSpecs) *TypeCache

NewTypeCache creates a new type cache

func (*TypeCache) GetAllTypes

func (tc *TypeCache) GetAllTypes() [][2]reflect.Type

GetAllTypes returns a slice of all type keys currently cached in the TypeCache.

This method is useful for cache inspection, debugging, and understanding which types have been processed and cached during the application's lifetime. The returned slice contains pairs of (runtime, schema) types in no particular order.

When runtime == schema (normal usage), these represent standard type descriptors. When they differ, the pair represents a view descriptor for fork-dependent SSZ.

The method acquires a read lock to ensure thread-safe access to the cache.

Returns:

  • [][2]reflect.Type: A slice of [runtime, schema] type pairs

Example:

cachedTypes := cache.GetAllTypes()
fmt.Printf("TypeCache contains %d type pairs\n", len(cachedTypes))
for _, pair := range cachedTypes {
    if pair[0] == pair[1] {
        fmt.Printf("  - %s\n", pair[0].String())
    } else {
        fmt.Printf("  - %s (view: %s)\n", pair[0].String(), pair[1].String())
    }
}

func (*TypeCache) GetTypeDescriptor

func (tc *TypeCache) GetTypeDescriptor(t reflect.Type, sizeHints []SszSizeHint, maxSizeHints []SszMaxSizeHint, typeHints []SszTypeHint) (*TypeDescriptor, error)

GetTypeDescriptor returns a cached type descriptor for the given type, computing it if necessary.

This method is the primary interface for obtaining type descriptors, which contain optimized metadata about how to serialize, deserialize, and hash types according to SSZ specifications. Type descriptors are cached for performance, avoiding repeated reflection and analysis of the same types.

The method is thread-safe and ensures sequential processing to prevent duplicate computation of type descriptors when called concurrently for the same type.

Parameters:

  • t: The reflect.Type for which to obtain a descriptor
  • sizeHints: Optional size hints from parent structures' tags. Pass nil for top-level types.
  • maxSizeHints: Optional max size hints from parent structures' tags. Pass nil for top-level types.
  • typeHints: Optional type hints from parent structures' tags. Pass nil for top-level types.

Returns:

  • *TypeDescriptor: The type descriptor containing metadata for SSZ operations
  • error: An error if the type cannot be analyzed or contains unsupported features

Type descriptors are only cached when no size hints are provided (i.e., for root types). When size hints are present, the descriptor is computed dynamically to accommodate the specific constraints.

Example:

typeDesc, err := cache.GetTypeDescriptor(reflect.TypeOf(myStruct), nil, nil)
if err != nil {
    log.Fatal("Failed to get type descriptor:", err)
}
fmt.Printf("Type size: %d bytes (dynamic: %v)\n", typeDesc.Size, typeDesc.Size < 0)

func (*TypeCache) GetTypeDescriptorWithSchema added in v1.3.0

func (tc *TypeCache) GetTypeDescriptorWithSchema(runtimeType, schemaType reflect.Type, sizeHints []SszSizeHint, maxSizeHints []SszMaxSizeHint, typeHints []SszTypeHint) (*TypeDescriptor, error)

GetTypeDescriptorWithSchema returns a cached type descriptor for a (runtime, schema) type pair.

This method supports fork-dependent SSZ schemas (view descriptors) where the schema type defines the SSZ layout while the runtime type holds the actual data. This allows different SSZ serializations of the same runtime data based on the schema provided.

When runtimeType == schemaType, this behaves identically to GetTypeDescriptor. When they differ, the descriptor is built using schema's field definitions (names, tags, order) but accessing data from the runtime type's fields.

Parameters:

  • runtimeType: The reflect.Type where actual data lives
  • schemaType: The reflect.Type that defines SSZ layout (field order, tags, limits)
  • sizeHints: Optional size hints from parent structures' tags
  • maxSizeHints: Optional max size hints from parent structures' tags
  • typeHints: Optional type hints from parent structures' tags

Returns:

  • *TypeDescriptor: The type descriptor for the (runtime, schema) pair
  • error: An error if types are incompatible or analysis fails

Example with view descriptor:

// Runtime type (superset)
type BeaconBlockBody struct { ... }
// Schema/view type for Altair fork
type BodyAltairView struct { ... }

desc, err := cache.GetTypeDescriptorWithSchema(
    reflect.TypeOf(BeaconBlockBody{}),
    reflect.TypeOf(BodyAltairView{}),
    nil, nil, nil,
)

func (*TypeCache) RemoveAllTypes

func (tc *TypeCache) RemoveAllTypes()

RemoveAllTypes clears all cached type descriptors from the cache.

This method is useful for:

  • Resetting the cache after configuration changes
  • Memory management in long-running applications
  • Testing scenarios requiring a clean cache state

The method acquires a write lock to ensure thread-safe clearing. After calling this method, all subsequent type descriptor requests will trigger recomputation.

Example:

// Clear cache after updating specifications
ds.UpdateSpecs(newSpecs)
cache.RemoveAllTypes()

// All types will be recomputed with new specs
desc, err := cache.GetTypeDescriptor(reflect.TypeOf(MyStruct{}), nil, nil)

func (*TypeCache) RemoveType

func (tc *TypeCache) RemoveType(t reflect.Type)

RemoveType removes a specific type (with runtime == schema) from the cache.

This method is useful for cache management scenarios where you need to force recomputation of a type descriptor, such as after configuration changes or when testing different type configurations.

The method acquires a write lock to ensure thread-safe removal. Note: This only removes entries where runtime type equals schema type. Use RemoveTypeKey to remove view descriptor entries.

Parameters:

  • t: The reflect.Type to remove from the cache

Example:

// Remove a type to force recomputation
cache.RemoveType(reflect.TypeOf(MyStruct{}))

// Next call to GetTypeDescriptor will rebuild the descriptor
desc, err := cache.GetTypeDescriptor(reflect.TypeOf(MyStruct{}), nil, nil)

func (*TypeCache) RemoveTypeKey added in v1.3.0

func (tc *TypeCache) RemoveTypeKey(runtimeType, schemaType reflect.Type)

RemoveTypeKey removes a specific (runtime, schema) type pair from the cache.

This method supports removing view descriptor entries where runtime differs from schema.

Parameters:

  • runtimeType: The runtime type of the cache entry to remove
  • schemaType: The schema type of the cache entry to remove

type TypeDescriptor

type TypeDescriptor struct {
	Type                   reflect.Type              `json:"-"`                   // Reflect type (runtime type where data lives)
	SchemaType             reflect.Type              `json:"-"`                   // Schema type that defines SSZ layout (may differ from Type for view descriptors)
	CodegenInfo            *any                      `json:"-"`                   // Codegen information or view pointer
	Kind                   reflect.Kind              `json:"kind"`                // Reflect kind of the type
	Size                   uint32                    `json:"size"`                // SSZ size (-1 if dynamic)
	Len                    uint32                    `json:"len"`                 // Length of array/slice / static size of container
	Limit                  uint64                    `json:"limit"`               // Limit of array/slice (ssz-max tag)
	ContainerDesc          *ContainerDescriptor      `json:"container,omitempty"` // For structs
	UnionVariants          map[uint8]*TypeDescriptor `json:"union,omitempty"`     // Union variant types by index (for CompatibleUnion)
	ElemDesc               *TypeDescriptor           `json:"field,omitempty"`     // For slices/arrays
	HashTreeRootWithMethod *reflect.Method           `json:"-"`                   // Cached HashTreeRootWith method for performance
	SizeExpression         *string                   `json:"size_expr,omitempty"` // The dynamic expression used to calculate the size of the type
	MaxExpression          *string                   `json:"max_expr,omitempty"`  // The dynamic expression used to calculate the max size of the type
	BitSize                uint32                    `json:"bit_size,omitempty"`  // Bit size for bit vector types (ssz-bitsize tag)
	SszType                SszType                   `json:"type"`                // SSZ type of the type
	SszTypeFlags           SszTypeFlag               `json:"flags"`               // SSZ type flags
	SszCompatFlags         SszCompatFlag             `json:"compat"`              // SSZ compatibility flags
	GoTypeFlags            GoTypeFlag                `json:"go_flags"`            // Additional go type flags
}

TypeDescriptor represents a cached, optimized descriptor for a type's SSZ encoding/decoding

func (*TypeDescriptor) GetTypeHash

func (td *TypeDescriptor) GetTypeHash() [32]byte

GetTypeHash computes a SHA-256 hash of the TypeDescriptor's JSON representation. This hash uniquely identifies the type's SSZ layout and is used by the code generator to detect when a type's structure has changed and regeneration is needed.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL