Skip to main content

This page explains how ZisK proves programs too long for a single fixed-height proof. It contrasts checkpointed continuations with ZisK's per-chip trace splitting (which limits padding to one tail segment per chip), shows how state is carried across segment boundaries on Continuation Buses, and describes how the many per-segment proofs fold into one root proof through an opportunistic recursive aggregation tree, an order-independent LtHash shared challenge, and two final root checks.

Scaling

A single proof can only cover a trace of fixed height. Real programs may run for billions of steps, vastly more than fits in one chip. So to upcome this limitation we have to break the work into pieces, prove the pieces independently, and fold them all back into a single proof at the end. This page covers how that works at an overview the mechanics of trace splitting, proof continuations and proof aggregation.

Splitting trace segments

Breaking the execution into fixed-height segments can be done two ways, and the choice shapes how much of the prover's effort goes into real computation rather than padding.

ApproachHow it splitsHow state is carried over
Checkpointed continuationsRun for N steps, halt, save the state, prove that block, then resume from the checkpoint.The whole machine state is threaded through every segment's public inputs at each halt.
Per-chip continuationsRun the program to completion in one pass, then partition each chip's trace at its own height.Each stateful chip carries its own state across its own segment boundaries on a dedicated Continuation Bus.

Splitting the trace

The two approaches cut the trace at different points, and the choice decides how much of each segment is real work versus padding.

Checkpointed split

Run the program for N steps, halt, save the machine state, generate a proof for those N steps, then resume from the saved checkpoint and repeat. Each segment proof certifies one N-step block.

The catch is padding. If a chip performs only k ≪ N operations in a given segment, its remaining N − k rows still have to be filled with dummy entries. Those rows satisfy the constraints but carry no useful computation, yet they still enter the polynomial commitment and constraint evaluation. In a multi-chip system the cost compounds: chips that fire heavily and chips that barely fire all pay the same per-segment height, in every segment of the whole run.

Segment 1Segment 2Segment 3Segment 4Segment 5
Main████████████████████████████··
Memory████··████··██····██····█·····
Ops█·····█·····█·····██····█·····

Per-chip split

Zisk decouples segmentation from execution. Instead of halting at periodic checkpoints, it runs the program to completion in a single pass and then partitions each chip's trace independently. Chips that did little produce short traces; chips that did a lot produce long ones; each chip's trace is sliced into segments of that chip's own fixed height. Padding shrinks from "every chip × every segment" to at most one partial segment per chip (only the tail of each chip's trace can carry any padding at all).

Segment 1Segment 2Segment 3Segment 4Segment 5
Main████████████████████████████··
Memory███████████████···
Ops██████

Continuing the state

Splitting the trace into independent pieces creates a new problem: the prover proves each piece on its own, but the pieces still describe one continuous execution. They have to agree at their boundaries. Otherwise the prover could quietly stitch unrelated pieces together.

Checkpointed continuations

At every halt, the entire machine state is saved and threaded through the next segment's public inputs. The next segment verifies the handoff before running. Every chip's state moves through every boundary, even chips that didn't participate at all.

Per-chip

ZisK does the same handoff but per chip. Each stateful chip has its own dedicated Continuation Bus that carries that chip's own state across its own segment boundaries. Each segment emits its final state on its bus; the next segment of the same chip picks it up and bus balancing rejects the proof if anything fails to match. Stateless chips carry nothing across boundaries and need no Continuation Bus at all.

Aggregating the proofs

After splitting and state continuation, the prover holds many independent per-segment proofs. Each one is succinct on its own, but a verifier expecting a single proof can't be handed a stack of thousands. The final step folds them all into a single root proof that attests to the whole execution.

The mechanism is proof recursion. A verifier is itself a computation, so it can be expressed as polynomial constraints and proved. A recursive proof attests "this other proof was valid"; iterating the construction collapses any number of input proofs into one output proof, regardless of how many segments the workload produced.

The aggregation tree

ZisK combines per-segment proofs in a binary aggregation tree built opportunistically. As soon as any two child proofs are ready, an aggregation node verifies them and combines them into one. Branches that finish early are folded immediately while slower branches are still running, so the shape of the tree reflects the timing of proof generation rather than a fixed structure decided in advance.

The tree has four node types:

NodeRole
LeafThe raw per-segment proof, one per chip × segment.
CompressorSits directly above each leaf and re-proves it in a recursion-friendly form so the aggregation circuit can verify it efficiently. Same public outputs as the leaf below.
AggregationVerifies its two children and combines them into a single compressed proof for the next level up.
RootThe top of the tree; runs the two final consistency checks.

At every level, each node propagates two scalars upward alongside its own proof:

  • A partial bus-balancing sum that accumulates the bus contributions of every proof in the node's subtree.
  • A partial challenge contribution that accumulates the shared-challenge fragments of every proof in the subtree.

Combining two children is cheap: each scalar is just an addition in the appropriate field. Tree depth grows as log₂(n) in the number of leaves, so even workloads with thousands of per-chip segments aggregate in roughly a dozen levels. The verifier on the other side only ever sees the root proof, and verification cost is constant in the number of segments — a million-segment execution verifies in the same time as a four-segment one.

The "fold as soon as two are ready" property is what makes the prover scale horizontally. Distributed workers can generate leaf proofs in parallel and the coordinator stitches them upward as they arrive, with no global synchronisation step. Adding more workers reduces wall-clock proving time linearly until the tree's critical path (the longest root-ward chain) becomes the bottleneck.

The shared challenge

STARK proofs depend on a shared random challenge α that every segment uses to compress its bus interactions into a single accumulator value. The global equation that proves correctness — "all chips' partial sums combine to zero" — is only meaningful if every prover used the same α. Otherwise the partial sums are incommensurable and adding them up tells you nothing.

The classical Fiat-Shamir hash derives α from the prover's commitments in a fixed order. That works when one prover does everything, but with many independent segment provers it forces a bad choice:

  • Hash all commitments in order — kills the parallelism the whole architecture was built around.
  • Each segment derives its own challenge — makes the per-segment partial sums uncombinable, breaking the global equation.

ZisK avoids both with LtHash, a lattice-based homomorphic multiset hash whose defining property is order-independent addition:

LtHash(S ∪ T) = LtHash(S) + LtHash(T)

Each segment prover hashes its commitment into a long pseudorandom vector vᵢ ∈ ℤⁿ_p. The global accumulator is just the component-wise sum acc = Σ vᵢ, and the shared challenge α is read off acc. Because the operation is commutative, any subset of provers can compute their partial sum independently and the partial sums can be merged later by ordinary addition — full parallelism is preserved.

Security (no two distinct commitment multisets produce the same acc) reduces to the Short Integer Solution (SIS) lattice problem, which is believed to remain hard even against quantum adversaries.

The challenge is broadcast to every leaf prover up front as a public input, so each segment proof is generated under a known, fixed α. The aggregation tree carries the matching partial challenge contributions upward alongside the bus- balancing sums, and the root verifies that the broadcast value matches what the tree actually accumulated. That's how the verifier knows α was derived honestly from the full set of commitments rather than chosen by the prover to make the bus-balancing equation balance artificially.

Root checks

Two arithmetic checks finalise the proof at the top of the tree:

CheckWhat it guarantees
Bus-balancing sum equals zeroEvery chip message — cross-chip dispatches, Continuation Bus handoffs, table lookups — was received exactly once with matching content.
Accumulated challenge reconstructs the broadcastThe shared random challenge α was derived honestly from the full set of commitments rather than chosen by a malicious prover to make the bus sum balance.

Both checks reduce to ordinary arithmetic on the public outputs of the root proof — the verifier never inspects an individual chip trace, segment witness, or commitment. If either check fails the root proof is rejected outright; there is no partial-credit verification.