> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# SSZ Encoding

> Simple Serialize (SSZ) encoding for Ethereum consensus layer

## Overview

SSZ (Simple Serialize) is the serialization format used by Ethereum's consensus layer (Beacon Chain). It provides efficient, deterministic encoding with Merkle tree support for proofs.

## Features

* Basic type encoding (uint8, uint16, uint32, uint64, uint256, bool)
* Variable-length types (vectors, lists, bitvectors, bitlists)
* Container (struct) encoding
* Hash tree root computation for Merkle proofs
* Full Zig implementation with TypeScript bindings

## Basic Types

### Encoding

```typescript theme={null}
import { Ssz } from '@voltaire/primitives';

// Encode unsigned integers
const uint8 = Ssz.encodeBasic(42, 'uint8');        // [42]
const uint16 = Ssz.encodeBasic(0x1234, 'uint16');  // [0x34, 0x12] (little-endian)
const uint32 = Ssz.encodeBasic(0x12345678, 'uint32');
const uint64 = Ssz.encodeBasic(0x123n, 'uint64');
const uint256 = Ssz.encodeBasic(0xDEADBEEFn, 'uint256');

// Encode boolean
const bool = Ssz.encodeBasic(true, 'bool');        // [1]
```

### Decoding

```typescript theme={null}
// Decode unsigned integers
const value8 = Ssz.decodeBasic(bytes, 'uint8');    // number
const value16 = Ssz.decodeBasic(bytes, 'uint16');  // number
const value32 = Ssz.decodeBasic(bytes, 'uint32');  // number
const value64 = Ssz.decodeBasic(bytes, 'uint64');  // bigint
const value256 = Ssz.decodeBasic(bytes, 'uint256'); // bigint

// Decode boolean
const flag = Ssz.decodeBasic(bytes, 'bool');       // boolean
```

## Merkleization

### Hash Tree Root

Compute Merkle tree root for proofs:

```typescript theme={null}
// Hash tree root of data
const data = new Uint8Array([1, 2, 3, 4, 5]);
const root = await Ssz.hashTreeRoot(data);
// Returns: 32-byte hash

// Empty data returns zero hash
const zeroRoot = await Ssz.hashTreeRoot(new Uint8Array(0));
```

### Properties

* Deterministic: Same input always produces same root
* 32-byte output: Compatible with Merkle proofs
* SHA256-based: Uses standard cryptographic hash

## Examples

### Validator Deposit

```typescript theme={null}
// Encode deposit data
const pubkey = Ssz.encodeBasic(validatorPubkey, 'uint256');
const withdrawalCredentials = Ssz.encodeBasic(credentials, 'uint256');
const amount = Ssz.encodeBasic(32000000000n, 'uint64'); // 32 ETH in gwei
const signature = Ssz.encodeBasic(sig, 'uint256');

// Compute deposit root
const depositData = new Uint8Array([
  ...pubkey,
  ...withdrawalCredentials,
  ...amount,
  ...signature
]);
const depositRoot = await Ssz.hashTreeRoot(depositData);
```

### Beacon Block Header

```typescript theme={null}
// Encode block header fields
const slot = Ssz.encodeBasic(12345n, 'uint64');
const proposerIndex = Ssz.encodeBasic(67890n, 'uint64');
const parentRoot = new Uint8Array(32); // 32-byte hash
const stateRoot = new Uint8Array(32);
const bodyRoot = new Uint8Array(32);

// Combine and hash
const headerData = new Uint8Array([
  ...slot,
  ...proposerIndex,
  ...parentRoot,
  ...stateRoot,
  ...bodyRoot
]);
const headerRoot = await Ssz.hashTreeRoot(headerData);
```

### Sync Committee

```typescript theme={null}
// Encode sync committee data
const aggregatePubkey = new Uint8Array(48); // BLS pubkey
const slot = Ssz.encodeBasic(100n, 'uint64');

const data = new Uint8Array([
  ...aggregatePubkey,
  ...slot
]);
const root = await Ssz.hashTreeRoot(data);
```

## Zig API

### Basic Types

```zig theme={null}
const primitives = @import("primitives");
const Ssz = primitives.Ssz;

// Encode
const uint8_bytes = Ssz.encodeUint8(42);
const uint16_bytes = Ssz.encodeUint16(0x1234);
const uint32_bytes = Ssz.encodeUint32(0x12345678);
const uint64_bytes = Ssz.encodeUint64(0x123456789ABCDEF0);
const bool_bytes = Ssz.encodeBool(true);

// Decode
const value = try Ssz.decodeUint32(&bytes);
const flag = try Ssz.decodeBool(&bytes);
```

### Variable Types

```zig theme={null}
// Vector (fixed-length)
const items = [_]u8{ 1, 2, 3, 4 };
const encoded = try Ssz.encodeVector(allocator, u8, &items);
defer allocator.free(encoded);

// List (variable-length with max)
const list = try Ssz.encodeList(allocator, u8, &items, 10);
defer allocator.free(list);

// Bitvector
const bits = [_]bool{ true, false, true, true };
const bitvec = try Ssz.encodeBitvector(allocator, &bits);
defer allocator.free(bitvec);

// Bitlist
const bitlist = try Ssz.encodeBitlist(allocator, &bits, 100);
defer allocator.free(bitlist);
```

### Container Encoding

```zig theme={null}
const MyStruct = struct {
    a: u8,
    b: u16,
    c: u32,
};

const value = MyStruct{
    .a = 1,
    .b = 0x0203,
    .c = 0x04050607,
};

const encoded = try Ssz.encodeContainer(allocator, MyStruct, value);
defer allocator.free(encoded);
```

### Hash Tree Root

```zig theme={null}
// Hash tree root of data
const data = [_]u8{ 1, 2, 3, 4, 5 };
const root = try Ssz.hashTreeRoot(allocator, &data);
// root: [32]u8

// Basic type hash tree root (no allocation)
const root_basic = Ssz.hashTreeRootBasic(u64, 12345);
```

## Specification

SSZ follows the [Ethereum consensus-specs](https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md):

### Basic Types

* **Boolean**: 1 byte (0 = false, 1 = true)
* **Unsigned integers**: Little-endian encoding
  * uint8: 1 byte
  * uint16: 2 bytes
  * uint32: 4 bytes
  * uint64: 8 bytes
  * uint256: 32 bytes

### Variable Types

* **Vector**: Fixed-length homogeneous collection
* **List**: Variable-length with maximum size
* **Bitvector**: Fixed-length collection of bits
* **Bitlist**: Variable-length collection of bits with sentinel

### Container Encoding

1. **Fixed part**: All fixed-size fields + offsets for variable fields
2. **Variable part**: Concatenated variable-size fields

### Merkleization

1. Chunk data into 32-byte leaves
2. Pad to next power of 2
3. Build binary Merkle tree bottom-up using SHA256
4. Return root hash

## Performance

### TypeScript

* Basic types: \~10-50 ns per operation
* Hash tree root: \~100-500 μs depending on data size
* Web Crypto API used for SHA256

### Zig

* Basic types: \~5-20 ns per operation
* Hash tree root: \~50-200 μs with optimized hashing
* Zero-copy decoding where possible

## Limitations

Current implementation:

* ✅ Basic types (all unsigned integers, bool)
* ✅ Variable types (vector, list, bitvector, bitlist)
* ✅ Container encoding (fixed fields only)
* ✅ Hash tree root computation
* ⚠️ Variable fields in containers (partial support)
* ❌ Union types (not yet implemented)
* ❌ Full consensus-specs test vectors (in progress)

## See Also

* [SSZ (Effect)](https://voltaire-effect.tevm.sh/primitives/ssz) - Effect.ts integration with Schema validation
* [RLP Encoding](/primitives/rlp) - Execution layer serialization
* [ABI Encoding](/primitives/abi) - Contract interface encoding
* [Hash](/primitives/hash) - Cryptographic hashing
* [Consensus Specs](https://github.com/ethereum/consensus-specs) - Official specification
