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.
| Approach | How it splits | How state is carried over |
|---|---|---|
| Checkpointed continuations | Run 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 continuations | Run 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 1 | Segment 2 | Segment 3 | Segment 4 | Segment 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 1 | Segment 2 | Segment 3 | Segment 4 | Segment 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:
| Node | Role |
|---|---|
| Leaf | The raw per-segment proof, one per chip × segment. |
| Compressor | Sits 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. |
| Aggregation | Verifies its two children and combines them into a single compressed proof for the next level up. |
| Root | The 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:
| Check | What it guarantees |
|---|---|
| Bus-balancing sum equals zero | Every chip message — cross-chip dispatches, Continuation Bus handoffs, table lookups — was received exactly once with matching content. |
| Accumulated challenge reconstructs the broadcast | The 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.