# Understanding SSZ Proofs in Lodestar: A Beginner’s Guide

By [Lady_in_Stem](https://paragraph.com/@devsaisa) · 2025-10-08

---

  

So far, you’ve learned that every SSZ **View** in Lodestar is backed by a **Merkle tree** — a structure that allows you to represent and verify data efficiently.

But what if you only need to prove or verify **part** of an SSZ object — like a specific field inside a large Ethereum state object?

That’s where **proofs** come in.

* * *

1\. What Is a Merkle Proof?
---------------------------

A **Merkle proof** is a compact, cryptographic way to prove that _a specific piece of data exists inside a larger dataset_ — without revealing the entire dataset.

It’s built using a **Merkle tree**, where:

*   Every leaf node represents a piece of data (e.g. a field value)
    
*   Every parent node represents the hash of its two children
    
*   The top node (root) represents the entire dataset
    

To verify a proof, you only need:

*   The **root hash** of the full dataset, and
    
*   The **proof** (a minimal set of sibling hashes + the leaf value)
    

If the proof recomputes the same root, the data is valid

* * *

2\. Proofs in SSZ and Lodestar
------------------------------

In **Lodestar SSZ**, proofs let you:

*   Generate a Merkle proof for selected fields
    
*   Send or store _only_ those parts (great for light clients)
    
*   Verify or reconstruct the partial object later
    

Every **View** in Lodestar comes with methods for working with proofs.

Method

Purpose

`view.createProof(paths)`

Create a proof for selected subfields

`Type.createFromProof(proof)`

Reconstruct a partial view from a proof

* * *

3\. Creating a Proof
--------------------

Let’s create a proof for an SSZ type — the **Attestation** object.

    import { ssz } from "@lodestar/types";
    
    // Create a tree-backed view
    const attestation = ssz.phase0.Attestation.defaultView();
    
    // Update a field
    attestation.data.source.epoch = 100;
    attestation.data.target.epoch = 120;
    
    // Create a proof for only specific subfields
    const proof = attestation.createProof([
      ['data', 'source', 'epoch'],
      ['data', 'target', 'epoch'],
    ]);
    
    console.log(proof);
    

**What this does:**

*   The proof includes only the paths to those two fields (`source.epoch`, `target.epoch`)
    
*   Lodestar automatically collects the necessary sibling hashes
    
*   You can now send this `proof` object to someone else who just needs to verify those fields
    

* * *

4\. Reconstructing from a Proof
-------------------------------

Later, someone else can use that proof to reconstruct a **partial view** of the object:

    const partialAttestation = ssz.phase0.Attestation.createFromProof(proof);
    
    // Access included fields
    console.log(partialAttestation.data.source.epoch); //  Works
    
    // Access excluded fields
    try {
      console.log(partialAttestation.aggregationBits);
    } catch (e) {
      console.error(" Field not included in proof");
    }
    

The partial view only contains the fields included in the proof — accessing anything else throws an error.

* * *

5\. Anatomy of a Proof
----------------------

A Lodestar SSZ proof is an object that contains:

*   `type` – the SSZ type definition
    
*   `gindices` – generalized indices for each field (tree positions)
    
*   `leaves` – serialized field values
    
*   `witnesses` – sibling hashes needed to recompute the root
    

You rarely need to inspect these manually, but here’s a conceptual breakdown:

    Proof {
      type: Attestation,
      leaves: [
        { path: ['data', 'source', 'epoch'], value: 100 },
        { path: ['data', 'target', 'epoch'], value: 120 }
      ],
      witnesses: [ <hash1>, <hash2>, ... ]
    }
    

* * *

6\. Verifying a Proof
---------------------

To verify a proof, Lodestar recomputes the Merkle root from the provided values and sibling hashes, then compares it to the expected root.

    const root = attestation.hashTreeRoot();
    const proofRoot = partialAttestation.hashTreeRoot();
    
    console.log(root.equals(proofRoot)); // ✅ true if proof is valid
    

This is the same logic that Ethereum’s **light clients** and **consensus layer** use to verify data efficiently without downloading the whole chain.

* * *

7\. Common Proof Use Cases
--------------------------

Use Case

Description

**Light Clients**

Verify only specific parts of Ethereum state without syncing everything

**Cross-client communication**

Pass compact, verifiable data between nodes

**Data availability checks**

Confirm inclusion of a field without revealing the rest

**Testing & debugging**

Check integrity of partial SSZ objects

**Optimized syncs**

Send proofs instead of full objects to reduce bandwidth

* * *

8\. Proofs + Views: Working Together
------------------------------------

Since each **Subview** in Lodestar represents a subtree, you can create proofs for any nested field simply by specifying the path.

Example:

    const proof = attestation.createProof([
      ['data', 'source'],
      ['data', 'target', 'root'],
    ]);
    

*   `['data', 'source']` → proves the whole `source` container
    
*   `['data', 'target', 'root']` → proves only one field from `target`
    

Subviews make it intuitive to target exactly what you need to prove — no manual Merkle math required.

* * *

9\. Tips & Gotchas
------------------

Pitfall

Explanation

Trying to access fields not in proof

Will throw an error — the partial view doesn’t have that data

Modifying a partial view

Possible, but rehashing won’t match the original root unless recomputed properly

Proof ≠ Serialization

A proof includes only paths + hashes, not full byte data

Order matters

Paths are hierarchical — `['data','source','epoch']` is not the same as `['data','epoch']`

* * *

Summary
-------

Concept

Meaning

**Proof**

A compact structure that proves specific fields exist in an SSZ object

**View**

A Merkle-aware SSZ object that can create proofs

**Partial View**

A reconstructed object from a proof containing only the proved fields

**Why it matters**

Enables lightweight, verifiable data syncing (like light clients)

* * *

### Key Takeaway

> SSZ proofs let you _prove data, not trust it_.
> 
> With just a few lines of Lodestar code, you can generate and verify Merkle proofs for any part of an Ethereum consensus object — from validator sets to attestations — without handling the full state.

---

*Originally published on [Lady_in_Stem](https://paragraph.com/@devsaisa/understanding-ssz-proofs-in-lodestar-a-beginners-guide)*
