{"id":50099748,"url":"https://github.com/lambdaclass/libssz","last_synced_at":"2026-05-23T06:33:05.639Z","repository":{"id":345192891,"uuid":"1173085849","full_name":"lambdaclass/libssz","owner":"lambdaclass","description":"A fast, zkVM-friendly SSZ library for Ethereum","archived":false,"fork":false,"pushed_at":"2026-03-25T18:34:06.000Z","size":210375,"stargazers_count":5,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T18:19:55.866Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lambdaclass.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-05T01:56:36.000Z","updated_at":"2026-03-25T18:33:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lambdaclass/libssz","commit_stats":null,"previous_names":["lambdaclass/libssz"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lambdaclass/libssz","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flibssz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flibssz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flibssz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flibssz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lambdaclass","download_url":"https://codeload.github.com/lambdaclass/libssz/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambdaclass%2Flibssz/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33385195,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-23T06:33:04.996Z","updated_at":"2026-05-23T06:33:05.627Z","avatar_url":"https://github.com/lambdaclass.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# libssz\n\nA fast, zkVM-friendly [Simple Serialize (SSZ)](https://ethereum.github.io/consensus-specs/ssz/simple-serialize) library for Ethereum consensus.\n\n`no_std + alloc` from day one. Up to 2.9x faster than Lighthouse on BeaconState encode and decode. Validated against 62,489 official Ethereum consensus spec test cases across all 9 forks (phase0 through eip7805). Fuzz-tested against both reference implementations.\n\n## Performance\n\nBenchmarked against [Lighthouse](https://github.com/sigp/lighthouse) (`ethereum_ssz` + `tree_hash`) and [ssz_rs](https://github.com/ralexstokes/ssz-rs) v0.9, `--release` with thin LTO.\n\n### Apple M3 Max (ARM)\n\n#### Encode\n\n| Type | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|------|--------|------------|--------|---------------|-----------|\n| `bool` | 214 ps | 3.9 ns | 29 ns | **18x** | **135x** |\n| `u64` | 235 ps | 4.0 ns | 29 ns | **17x** | **123x** |\n| `[u8; 32]` | 4.1 ns | 4.2 ns | 30 ns | ~1x | **7.3x** |\n| `BeaconBlockHeader` | 13.7 ns | 113 ns | 1.8 µs | **8.2x** | **131x** |\n| `Vec\u003cu64\u003e` (1K) | 118 ns | 433 ns | 14 µs | **3.7x** | **119x** |\n| `Vec\u003cu64\u003e` (100K) | 10.4 µs | 56 µs | 1.5 ms | **5.4x** | **144x** |\n\n#### Decode\n\n| Type | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|------|--------|------------|--------|---------------|-----------|\n| `bool` | 430 ps | 430 ps | 432 ps | ~1x | ~1x |\n| `u64` | 461 ps | 461 ps | 480 ps | ~1x | ~1x |\n| `[u8; 32]` | 4.1 ns | 3.8 ns | 66 ns | ~1x | **16x** |\n| `BeaconBlockHeader` | 12.7 ns | 12.3 ns | 207 ns | ~1x | **16x** |\n| `Vec\u003cu64\u003e` (1K) | 123 ns | 1.23 µs | 780 ns | **10x** | **6.3x** |\n| `Vec\u003cu64\u003e` (100K) | 10.3 µs | 154 µs | 112 µs | **15x** | **10.9x** |\n\n#### BeaconState (21 fields, variable-length)\n\n| Benchmark | Validators | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|-----------|-----------|--------|------------|--------|---------------|-----------|\n| Encode | 16K | 808 µs | 756 µs | 75.1 ms | ~1x | **93x** |\n| Encode | 100K | 654 µs | 5.61 ms | 215 ms | **8.6x** | **329x** |\n| Encode | 300K | 11.9 ms | 18.0 ms | 551 ms | **1.5x** | **46x** |\n| Encode | 1M | 5.67 ms | 19.0 ms | 1.73 s | **3.4x** | **305x** |\n| Decode | 16K | 123 µs | 237 µs | 9.16 ms | **1.9x** | **74x** |\n| Decode | 100K | 539 µs | 804 µs | 28.4 ms | **1.5x** | **53x** |\n| Decode | 300K | 1.51 ms | 2.23 ms | 76.1 ms | **1.5x** | **50x** |\n| Decode | 1M | 4.94 ms | 7.22 ms | 230 ms | **1.5x** | **47x** |\n\n#### Hash Tree Root\n\n| Type | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|------|--------|------------|--------|---------------|-----------|\n| `bool` | 3.1 ns | 3.2 ns | 3.2 ns | ~1x | ~1x |\n| `u64` | 3.1 ns | 3.2 ns | 48.6 ns | ~1x | **15.7x** |\n| `[u8; 32]` | 3.6 ns | 3.6 ns | 88.3 ns | ~1x | **24.5x** |\n\n### AMD Ryzen 9 9950X3D (x86_64)\n\n#### Encode\n\n| Type | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|------|--------|------------|--------|---------------|-----------|\n| `u64` | 3.39 ns | 11.0 ns | 11.1 ns | **3.2x** | **3.3x** |\n| `[u8; 32]` | 3.47 ns | 11.1 ns | 539 ns | **3.2x** | **155x** |\n| `BeaconBlockHeader` | 10.1 ns | 84.2 ns | 1.71 µs | **8.4x** | **170x** |\n| `Vec\u003cu64\u003e` (1K) | 58.6 ns | 400 ns | 23.9 µs | **6.8x** | **407x** |\n| `Vec\u003cu64\u003e` (100K) | 9.20 µs | 35.8 µs | 2.36 ms | **3.9x** | **257x** |\n\n#### Decode\n\n| Type | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|------|--------|------------|--------|---------------|-----------|\n| `u64` | 315 ps | 317 ps | 317 ps | ~1x | ~1x |\n| `[u8; 32]` | 3.2 ns | 3.4 ns | 72 ns | ~1x | **23x** |\n| `BeaconBlockHeader` | 8.96 ns | 7.08 ns | 196 ns | 0.8x | **22x** |\n| `Vec\u003cu64\u003e` (1K) | 55.7 ns | 843 ns | 591 ns | **15x** | **11x** |\n| `Vec\u003cu64\u003e` (100K) | 9.24 µs | 59.7 µs | 31.8 µs | **6.5x** | **3.4x** |\n\n#### BeaconState (21 fields, variable-length)\n\n| Benchmark | Validators | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|-----------|-----------|--------|------------|--------|---------------|-----------|\n| Encode | 16K | 148 µs | 160 µs | 74.9 ms | ~1x | **506x** |\n| Encode | 100K | 450 µs | 773 µs | 201 ms | **1.7x** | **446x** |\n| Encode | 300K | 3.22 ms | 6.21 ms | 513 ms | **1.9x** | **159x** |\n| Encode | 1M | 10.1 ms | 20.3 ms | 1.58 s | **2.0x** | **156x** |\n| Decode | 16K | 72.5 µs | 185 µs | 6.83 ms | **2.6x** | **94x** |\n| Decode | 100K | 313 µs | 908 µs | 20.5 ms | **2.9x** | **66x** |\n| Decode | 300K | 2.74 ms | 4.18 ms | 55.2 ms | **1.5x** | **20x** |\n| Decode | 1M | 9.27 ms | 13.9 ms | 172 ms | **1.5x** | **19x** |\n\n#### Hash Tree Root\n\n| Type | libssz | Lighthouse | ssz_rs | vs Lighthouse | vs ssz_rs |\n|------|--------|------------|--------|---------------|-----------|\n| `bool` | 2.24 ns | 2.20 ns | 2.30 ns | ~1x | ~1x |\n| `u64` | 2.36 ns | 2.10 ns | 33.0 ns | ~1x | **14x** |\n| `[u8; 32]` | 2.79 ns | 2.79 ns | 57.8 ns | ~1x | **21x** |\n\nlibssz beats Lighthouse on both BeaconState encode and decode at every validator count, and dominates on primitives and vectors. Full results: `cargo bench --bench differential`.\n\n\u003cdetails\u003e\n\u003csummary\u003eHow\u003c/summary\u003e\n\n- **Direct-write `ContainerEncoder`** — variable data writes directly to the output buffer with no intermediate allocation. Fixed fields are patched in-place into a pre-allocated region. Eliminates the double-write that a separate variable buffer would cause\n- **All-fixed containers** bypass `ContainerEncoder`/`ContainerDecoder` entirely — the derive macro generates direct field-by-field append/decode, eliminating heap allocations and offset bookkeeping\n- **Inlined bulk encode/decode** — the derive macro generates `ssz_append_fixed_slice` and `ssz_decode_fixed_vec` overrides that inline per-field operations directly into the loop body, skipping per-item struct-level length checks\n- **Bulk memcpy for `[u8; N]` and integers** — both encode and decode use a single memcpy on little-endian platforms instead of per-element iteration\n- **Aggressive inlining** — `#[inline(always)]` on all trait impls that cross crate boundaries\n\n\u003c/details\u003e\n\n## Getting Started\n\n### Adding dependencies\n\nAdd libssz to your project from [crates.io](https://crates.io/crates/libssz):\n\n```bash\ncargo add libssz libssz-derive libssz-merkle libssz-types\n```\n\nFor `no_std` environments (zkVMs, WASM, embedded), disable default features and enable `alloc`:\n\n```bash\ncargo add libssz --no-default-features --features alloc\ncargo add libssz-types --no-default-features --features alloc\ncargo add libssz-merkle --no-default-features --features alloc\ncargo add libssz-derive\n```\n\n### Encode and decode\n\n```rust\nuse libssz::{SszEncode, SszDecode};\n\nlet value: u64 = 42;\nlet encoded = value.to_ssz();\nlet decoded = u64::from_ssz_bytes(\u0026encoded).unwrap();\nassert_eq!(decoded, 42);\n```\n\n### Derive macros\n\n```rust\nuse libssz_derive::{SszEncode, SszDecode, HashTreeRoot};\nuse libssz::{SszEncode, SszDecode};\nuse libssz_merkle::HashTreeRoot;\n\n#[derive(SszEncode, SszDecode, HashTreeRoot)]\nstruct BeaconBlockHeader {\n    slot: u64,\n    proposer_index: u64,\n    parent_root: [u8; 32],\n    state_root: [u8; 32],\n    body_root: [u8; 32],\n}\n\nlet header = BeaconBlockHeader {\n    slot: 1,\n    proposer_index: 0,\n    parent_root: [0u8; 32],\n    state_root: [0u8; 32],\n    body_root: [0u8; 32],\n};\n\nlet bytes = header.to_ssz();\nlet decoded = BeaconBlockHeader::from_ssz_bytes(\u0026bytes).unwrap();\nlet root = header.hash_tree_root();\n```\n\n### Bounded collections\n\n```rust\nuse libssz_types::{SszVector, SszList, SszBitvector, SszBitlist};\n\n// Vector: exactly 4 elements\nlet v = SszVector::\u003cu64, 4\u003e::try_from(vec![1, 2, 3, 4]).unwrap();\n\n// List: at most 1024 elements\nlet mut l = SszList::\u003cu64, 1024\u003e::default();\nl.push(42).unwrap();\n\n// Bitvector: exactly 8 bits\nlet bv = SszBitvector::\u003c8\u003e::default();\n\n// Bitlist: at most 64 bits\nlet mut bl = SszBitlist::\u003c64\u003e::default();\nbl.push(true).unwrap();\n```\n\n### Union types\n\n```rust\nuse libssz_derive::{SszEncode, SszDecode, HashTreeRoot};\n\n#[derive(SszEncode, SszDecode, HashTreeRoot)]\n#[ssz(enum_behaviour = \"union\")]\nenum ExecutionPayload {\n    Bellatrix(BellatrixPayload),\n    Capella(CapellaPayload),\n    Deneb(DenebPayload),\n}\n```\n\n### `no_std` usage\n\nEvery crate works without the standard library. CI verifies `no_std` compilation against `thumbv7m-none-eabi` on every commit.\n\n```rust\n#![no_std]\nextern crate alloc;\n\nuse libssz::{SszEncode, SszDecode};\n\nfn encode_slot(slot: u64) -\u003e alloc::vec::Vec\u003cu8\u003e {\n    slot.to_ssz()\n}\n\nfn decode_slot(bytes: \u0026[u8]) -\u003e Result\u003cu64, libssz::DecodeError\u003e {\n    u64::from_ssz_bytes(bytes)\n}\n```\n\n## Crates\n\n| Crate | Description |\n|-------|-------------|\n| [`libssz`](crates/ssz) | Core `SszEncode` / `SszDecode` traits, primitive and container impls |\n| [`libssz-types`](crates/ssz-types) | Bounded collections: `SszVector`, `SszList`, `SszBitvector`, `SszBitlist`, `ProgressiveList`, `ProgressiveBitlist` |\n| [`libssz-merkle`](crates/ssz-merkle) | `HashTreeRoot` trait, `merkleize`, `merkleize_progressive`, precomputed zero hashes |\n| [`libssz-derive`](crates/ssz-derive) | `#[derive(SszEncode, SszDecode, HashTreeRoot)]` |\n\nDependency graph: `libssz-derive` → `libssz-merkle` → `libssz` ← `libssz-types`\n\n## Supported Types\n\n| SSZ type | Rust type | Encode | Decode | HashTreeRoot |\n|----------|-----------|--------|--------|-------------|\n| `bool` | `bool` | Y | Y | Y |\n| `uint8`..`uint128` | `u8`..`u128` | Y | Y | Y |\n| `Bytes4`..`Bytes96` | `[u8; N]` | Y | Y | Y |\n| `Vector[T, N]` | `SszVector\u003cT, N\u003e` | Y | Y | Y |\n| `List[T, N]` | `SszList\u003cT, N\u003e` | Y | Y | Y |\n| `Bitvector[N]` | `SszBitvector\u003cN\u003e` | Y | Y | Y |\n| `Bitlist[N]` | `SszBitlist\u003cN\u003e` | Y | Y | Y |\n| `ProgressiveList[T]` | `ProgressiveList\u003cT\u003e` | Y | Y | Y |\n| `ProgressiveBitlist` | `ProgressiveBitlist` | Y | Y | Y |\n| Container | `struct` + derive | Y | Y | Y |\n| Union | `enum` + `#[ssz(enum_behaviour = \"union\")]` | Y | Y | Y |\n| Transparent | `struct` + `#[ssz(transparent)]` | Y | Y | Y |\n\n## Testing\n\n```sh\nmake test                  # unit + integration tests\nmake test-alloc            # no_std + alloc only\nmake download-spec-tests   # download consensus spec vectors (~1.25GB, cached)\nmake spec-tests            # run 62,489 spec test cases (downloads if needed)\nmake fuzz-quick            # 10s smoke fuzz per target (19 targets)\nmake bench                 # criterion benchmarks\nmake ci                    # full CI pipeline locally\n```\n\n### Consensus Spec Tests\n\nThe library is validated against the official [Ethereum consensus spec test vectors](https://github.com/ethereum/consensus-specs) (v1.6.1). This covers:\n\n- **ssz_generic**: all SSZ primitive types, vectors, lists, bitfields, containers, progressive types (EIP-7916), and compatible unions — valid and invalid cases\n- **ssz_static mainnet**: all Ethereum consensus types (BeaconState, BeaconBlock, Attestation, etc.) across 9 forks (phase0, altair, bellatrix, capella, deneb, electra, fulu, gloas, eip7805) at mainnet parameters\n- **ssz_static minimal**: same types at minimal preset parameters\n\nEach test case verifies decode, re-encode roundtrip, and hash tree root correctness.\n\n### Fuzzing\n\nDifferential fuzz-tested against Lighthouse and ssz_rs across 19 fuzz targets, run nightly in CI.\n\n## Documentation\n\n- [Architecture](docs/architecture.md) — crate layout, dependency graph, design rationale\n- [Technical Design](docs/technical-design.md) — trait design, encoding/decoding algorithms\n- [SSZ Spec Summary](docs/ssz-spec-summary.md) — concise reference of the spec as implemented\n\n## License\n\nLicensed under either of\n\n- [Apache License, Version 2.0](LICENSE-APACHE)\n- [MIT License](LICENSE-MIT)\n\nat your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaclass%2Flibssz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flambdaclass%2Flibssz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambdaclass%2Flibssz/lists"}