ssz.h

ssz implementation for building and reading ssz encoded data.

ssz_flag_t

util/ssz.h

Flags to control SSZ type behavior and serialization. These flags can be combined using bitwise OR.

typedef enum {
  SSZ_FLAG_NONE     = 0, /**< No special flags */
  SSZ_FLAG_OPT_MASK = 1, /**< Marks a field containing a bitmask indicating which optional fields are present in the container */
  SSZ_FLAG_UINT     = 2, /**< Render bytes as uint in JSON output (for numeric fields stored as bytes) */
  SSZ_FLAG_STRING   = 4, /**< Render bytes as string in JSON output (for text fields stored as bytes) */
} ssz_flag_t;

ssz_len

util/ssz.h

Gets the number of elements in a list, vector, or bit container.

For SSZ_TYPE_VECTOR: Returns the fixed length defined in the type definition. For SSZ_TYPE_LIST: Returns the actual number of elements in the list by analyzing the offset array (dynamic types) or dividing total bytes by element size (fixed types). For SSZ_TYPE_BIT_VECTOR: Returns the number of bits (total bytes * 8). For SSZ_TYPE_BIT_LIST: Returns the number of bits by finding the sentinel bit in the last byte.

Example:

ssz_ob_t transactions = ssz_get(&block, "transactions");
uint32_t tx_count = ssz_len(transactions);
printf("Block contains %u transactions\n", tx_count);

Parameters

  • ob : The SSZ object to get the length from

Returns

The number of elements, or 0 if the type doesn't support length

ssz_at

util/ssz.h

Retrieves an element from a list or vector at the specified index.

For lists/vectors with dynamic element types: Uses the offset array to locate the element. For lists/vectors with fixed element types: Calculates the position by multiplying index with element size.

Example:

Parameters

  • ob : The SSZ list or vector object

  • index : Zero-based index of the element to retrieve

Returns

An ssz_ob_t containing the element, or an error object (with NULL def/data) if index is out of bounds

ssz_get

util/ssz.h

Retrieves a field value from a container by name.

Searches through the container's field definitions to find a matching name, then extracts and returns the corresponding value. Handles both fixed and dynamic fields, computing offsets as needed. if the field is a union, the union value will be returned.

Example:

Parameters

  • ob : Pointer to the container SSZ object

  • name : Name of the field to retrieve

Returns

An ssz_ob_t containing the field value, or an error object if not found or invalid type

ssz_get_def

util/ssz.h

Gets the type definition for a named field within a container.

Parameters

  • def : The container type definition

  • name : Name of the field to find

Returns

Pointer to the field's type definition, or NULL if not found

ssz_add_gindex

util/ssz.h

Combines two generalized indices where gindex2 represents a subtree of gindex1.

This is used to navigate deeper into the Merkle tree structure by appending one path to another. The depth of gindex2 is determined and then combined with gindex1.

Parameters

  • gindex1 : The base generalized index

  • gindex2 : The subtree generalized index to append

Returns

The combined generalized index, or 0 on error (depth too large)

ssz_verify_multi_merkle_proof

util/ssz.h

Verifies a multi-Merkle proof for multiple leaves and computes the root hash.

Takes a proof (witness nodes), the leaf values, and their generalized indices, then reconstructs the Merkle tree to verify the proof is valid and compute the root.

IMPORTANT: This function may use recursion for complex proofs and does NOT allocate heap memory during verification. Ensure adequate stack size for proofs with many leaves or deep tree structures.

Parameters

  • proof_data : The proof witness nodes (32 bytes each)

  • leafes : The leaf values to verify (32 bytes each)

  • gindex : Array of generalized indices for each leaf (length must match leafes.len/32)

  • out : Output buffer for the computed root hash (32 bytes)

Returns

true if the proof is valid, false otherwise

ssz_verify_single_merkle_proof

util/ssz.h

Verifies a single-leaf Merkle proof and computes the root hash.

IMPORTANT: This function may use recursion and does NOT allocate heap memory during verification. Ensure adequate stack size for proofs in deep tree structures.

Parameters

  • proof_data : The proof witness nodes (32 bytes each)

  • leaf : The leaf value to verify (32 bytes)

  • gindex : The generalized index of the leaf

  • out : Output buffer for the computed root hash (32 bytes)

ssz_union

util/ssz.h

Extracts the active variant from a union object.

A union in SSZ is serialized as [selector_byte][data...] where the selector indicates which variant is active. This function reads the selector and returns the corresponding variant as an ssz_ob_t.

Example:

Parameters

  • ob : The union object to unwrap

Returns

An ssz_ob_t containing the active variant, or an empty object if invalid.

ssz_fixed_length

util/ssz.h

Calculates the size of the fixed portion of an SSZ type in bytes.

For dynamic types (lists, unions, bit lists): Returns SSZ_OFFSET_SIZE (4 bytes) for the offset. For fixed types: Returns the actual size in bytes. For containers: Sums the fixed lengths of all fields.

Parameters

  • def : The SSZ type definition

Returns

Size in bytes of the fixed portion

ssz_dump_to_file

util/ssz.h

Serializes an SSZ object to JSON format and writes to a file.

Parameters

  • f : File handle to write to

  • ob : The SSZ object to dump

  • include_name : If true, includes the type name in output

  • write_unit_as_hex : If true, renders uint values as hex strings

ssz_dump_to_str

util/ssz.h

Serializes an SSZ object to JSON string.

Parameters

  • ob : The SSZ object to dump

  • include_name : If true, includes the type name in output

  • write_unit_as_hex : If true, renders uint values as hex strings

Returns

Allocated string containing JSON representation (caller must free)

ssz_dump_to_file_no_quotes

util/ssz.h

Serializes an SSZ object to JSON without quotes around hex values. Used for RPC-compatible output.

Parameters

  • f : File handle to write to

  • ob : The SSZ object to dump

ssz_hash_tree_root

util/ssz.h

Computes the SSZ hash tree root of an object.

Implements the SSZ hash_tree_root algorithm by:

  1. Chunking the data into 32-byte pieces

  2. Building a Merkle tree from the chunks

  3. For lists/bit lists: mixing in the length

IMPORTANT: This function uses the stack for recursive Merkle tree computation and does NOT allocate heap memory. For deeply nested structures or large Merkle trees, ensure your stack size is sufficient (typically 1-2 MB is adequate). The recursion depth is log2(number_of_chunks), so even large objects have manageable stack usage.

Example:

Parameters

  • ob : The SSZ object to hash

  • out : Output buffer for the root hash (32 bytes)

ssz_create_proof

util/ssz.h

Creates a Merkle proof for a single leaf in an SSZ object.

IMPORTANT: Like ssz_hash_tree_root(), this function uses the stack for recursive computation and does NOT allocate heap memory during tree traversal. Only the final proof bytes are heap-allocated (which the caller must free). Ensure adequate stack size for deeply nested structures.

Parameters

  • root : The SSZ object serving as the Merkle tree root

  • root_hash : The hash tree root of the object

  • gindex : The generalized index of the leaf to prove

Returns

Allocated bytes containing the proof (caller must free)

ssz_create_multi_proof

util/ssz.h

Creates a multi-Merkle proof for multiple leaves in an SSZ object.

IMPORTANT: Like ssz_hash_tree_root(), this function uses the stack for recursive computation and does NOT allocate heap memory during tree traversal. Only the final proof bytes are heap-allocated (which the caller must free). Ensure adequate stack size for deeply nested structures.

Parameters

  • root : The SSZ object serving as the Merkle tree root

  • root_hash : The hash tree root of the object

  • gindex_len : Number of generalized indices

  • ... : Variable arguments: gindex_len generalized indices (gindex_t)

Returns

Allocated bytes containing the proof (caller must free)

ssz_gindex

util/ssz.h

Computes a generalized index for navigating into an SSZ structure.

Takes a path through the SSZ structure and returns the corresponding generalized index. For containers: provide field names (const char*) For lists/vectors: provide element indices (int)

Example:

Parameters

  • def : The root SSZ type definition

  • num_elements : Number of path elements

  • ... : Variable arguments: path elements (field names or indices)

Returns

The computed generalized index, or 0 on error

ssz_create_multi_proof_for_gindexes

util/ssz.h

Creates a multi-Merkle proof for leaves specified by an array of generalized indices.

IMPORTANT: Like ssz_hash_tree_root(), this function uses the stack for recursive computation and does NOT allocate heap memory during tree traversal. Only the final proof bytes are heap-allocated (which the caller must free). Ensure adequate stack size for deeply nested structures.

Parameters

  • root : The SSZ object serving as the Merkle tree root

  • root_hash : The hash tree root of the object

  • gindex : Array of generalized indices

  • gindex_len : Number of generalized indices in the array

Returns

Allocated bytes containing the proof (caller must free)

ssz_is_dynamic

util/ssz.h

Checks if an SSZ type has dynamic length.

Dynamic types include: lists, bit lists, unions, and containers containing dynamic fields. Dynamic types are serialized with offsets in the fixed portion.

Parameters

  • def : The SSZ type definition to check

Returns

true if the type is dynamic, false if fixed-size

ssz_is_type

util/ssz.h

Checks if an SSZ object matches a given type definition.

Parameters

  • ob : Pointer to the SSZ object to check

  • def : The type definition to match against

Returns

true if the object matches the type, false otherwise

ssz_is_valid

util/ssz.h

Validates an SSZ object according to SSZ specification rules.

This is the first line of defense for untrusted data. It checks:

  • Object size doesn't exceed SSZ_MAX_BYTES (1GB) to prevent integer overflows

  • Byte lengths match type requirements

  • For booleans: value is 0 or 1

  • For vectors: length matches definition

  • For lists: offsets are valid and monotonically increasing

  • For containers: all field offsets are valid

  • For unions: selector is in valid range

  • For bit lists/vectors: length is correct

If recursive=true, recursively validates all nested objects.

IMPORTANT: All user/network data MUST be validated with this function before use. After validation, no further safety checks are performed.

Example:

Parameters

  • ob : The SSZ object to validate

  • recursive : If true, recursively validates nested objects

  • state : Optional state object for error reporting (can be NULL)

Returns

true if valid, false if invalid (error details in state->error if provided)

ssz_builder_t

util/ssz.h

Builder for constructing SSZ-encoded data incrementally.

Maintains separate buffers for fixed and dynamic portions, automatically handling offset calculations for dynamic fields.

ssz_add_bytes

util/ssz.h

Adds a field to a container builder by name.

Parameters

  • buffer : The builder to add to

  • name : Name of the field (must exist in container definition)

  • data : Bytes to add for this field

ssz_add_ob

util/ssz.h

Adds a field to a container builder by name.

Parameters

  • buffer : The builder to add to

  • name : Name of the field (must exist in container definition)

  • ob : The SSZ object to add for this field

ssz_add_builders

util/ssz.h

Adds a nested builder as a field to a container builder.

Converts the nested builder to bytes and adds it to the parent. Automatically adds union selector if the type is a union. Frees the resources of the nested builder.

Parameters

  • buffer : The parent builder

  • name : Name of the field

  • data : The nested builder (will be consumed and freed)

ssz_add_dynamic_list_bytes

util/ssz.h

Adds bytes to a list builder for dynamic element types.

Parameters

  • buffer : The list builder

  • num_elements : Current number of elements in the list

  • data : Bytes for the new element

ssz_add_dynamic_list_builders

util/ssz.h

Adds a nested builder to a list builder for dynamic element types.

Parameters

  • buffer : The list builder

  • num_elements : Current number of elements in the list

  • data : The nested builder (will be consumed and freed)

ssz_add_uint256

util/ssz.h

Adds a uint256 value to the builder in little-endian format.

Parameters

  • buffer : The builder

  • data : Bytes representing the uint256 (any length, will be padded/truncated to 32 bytes)

ssz_from_json

util/ssz.h

Converts a JSON object to SSZ-encoded bytes.

Recursively converts JSON values to SSZ format according to the type definition. Handles type conversions, optional fields, and CamelCase/snake_case field names.

Example:

Parameters

  • json : The JSON object to convert

  • def : The SSZ type definition to convert to

  • state : State object for error reporting

Returns

An ssz_ob_t with allocated bytes (caller must free bytes.data)

ssz_builder_free

util/ssz.h

Frees the buffers in a builder. Does not free the builder struct itself.

Parameters

  • buffer : The builder to free

return

util/ssz.h

Creates a builder from an existing SSZ object. The bytes are referenced, not copied.

Parameters

  • val : The SSZ object to create a builder from

Returns

A builder wrapping the object's bytes

ssz_builder_to_bytes

util/ssz.h

Converts a builder to final SSZ-encoded bytes and frees the builder's buffers.

Combines the fixed and dynamic portions into a single byte array. The builder should not be used after this call.

Example:

Parameters

  • buffer : The builder to convert (will be consumed)

Returns

An ssz_ob_t with allocated bytes (caller must free bytes.data)

Last updated