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 ¶
- func ParseTags(tag string) (typeHints []SszTypeHint, sizeHints []SszSizeHint, ...)
- type ContainerDescriptor
- type DynFieldDescriptor
- type FieldDescriptor
- type GoTypeFlag
- type SszCompatFlag
- type SszMaxSizeHint
- type SszSizeHint
- type SszType
- type SszTypeFlag
- type SszTypeHint
- type TypeCache
- func (tc *TypeCache) GetAllTypes() [][2]reflect.Type
- func (tc *TypeCache) GetTypeDescriptor(t reflect.Type, sizeHints []SszSizeHint, maxSizeHints []SszMaxSizeHint, ...) (*TypeDescriptor, error)
- func (tc *TypeCache) GetTypeDescriptorWithSchema(runtimeType, schemaType reflect.Type, sizeHints []SszSizeHint, ...) (*TypeDescriptor, error)
- func (tc *TypeCache) RemoveAllTypes()
- func (tc *TypeCache) RemoveType(t reflect.Type)
- func (tc *TypeCache) RemoveTypeKey(runtimeType, schemaType reflect.Type)
- type TypeDescriptor
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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
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.