Rollups
A rollup, also called a SwarmClient session, is how Skyhook finalizes Zcash blocks. Anyone can build one. The builder, called a validator although no stake is involved, picks a Zcash block to finalize, references it with the blocks that follow it, and the rollup is completed with FlyClient samples of the chain’s history behind it. Transactions waiting for finality join the rollup by proving that they are included in one of its blocks. When every sample is satisfied the rollup is valid, and finalizing it opens the joined transactions’ locks and pays the validator a share of their fees.
Validators need no permission and post no collateral, because they have nothing to vote on: a rollup is either valid, which anyone can check, or useless. An invalid rollup is simply never joined, and its builder has wasted the gas spent on it. The blocks a rollup uses are normally already on-chain, put there by oracles, who receive a share of the rollup’s fee for the blocks it reuses.
Two modes
Every rollup is built in one of two modes. The contract records the mode when the rollup is initiated, so anyone deciding whether to join can see it.
| Fully sampled (default) | Root-anchored (opt-in) | |
|---|---|---|
| How samples are checked | Proof-of-work, verified once when an oracle stored the block; the rollup reads it from storage | An MMR proof against a root the participants agreed on |
| Who must check anything off-chain | No one | Every participant checks the root against its own view of the chain |
| Initiation, 1,000-block gap | About 1.4M gas with oracles | About 9.5M gas |
| With no oracles running | Every block submitted at about 950k gas, over several transactions | Unchanged: always one transaction, about 5–13M gas |
| Oracle fees | A share for each stored block it reuses | Only for stored blocks it actually reuses |
| Best for | Everyday use while oracles are running | Oracle outages, and participants who prefer not to depend on oracles |
Fully sampled rollups are the cheapest option while oracles are running. Root-anchored rollups keep the bridge live and fairly priced when they aren’t: because one can always finalize in a single transaction without any oracle, it also caps what oracles can charge. An oracle that withholds blocks, or prices them above the root-anchored alternative, is simply routed around. Root-anchored rollups use the online-offline check described on the chain identity page.
Keeping the modes apart
A root is only as good as the check behind it, so the two modes must not contaminate each other. Three rules keep them apart:
- The mode is part of the rollup. The contract records whether a rollup is fully sampled or anchored to a particular root, and a swap sees which before joining. Wallets should check the root against their own node automatically, and refuse to join a root-anchored rollup they can’t check.
- Root-anchored finality never becomes a starting point for full sampling. Tail samples are drawn from the history since the last finalized block. If a root-anchored rollup could serve as that block, a later fully sampled rollup would inherit an unchecked root and quietly lose its guarantee. The anchor therefore tracks the last fully sampled block separately, and fully sampled rollups only build on it.
- Oracles are paid only for blocks that are reused. A root-anchored rollup that proves its samples under its root, rather than reading them from the block store, owes oracles nothing for them.
Lifecycle
Initiate
A validator initiates a rollup by choosing a main block to roll up to. Typically it does so by aggregating non-rollup transactions: transactions that have advertised a transaction ID without any attached finality, and have signaled that they want to be aggregated. The blocks themselves are normally already on-chain, submitted by oracles, so the validator references them by hash rather than uploading them and paying to verify their proof-of-work; if a block is missing, the validator can submit it itself. The validator can add transactions to the rollup’s mempool by supplying Merkle proofs of their inclusion in its blocks, either at initiation or as blocks are submitted.
Size and growth
A rollup consists of the main block, the three head blocks that directly follow it, and tail samples drawn by FlyClient from the history between the last finalized block and the main block. Skyhook uses full FlyClient sampling by default, which stays secure even if nobody checks anything off-chain. Each verification performs several independent FlyClient sampling runs of about 5 × log₁₀(gap) samples each, with more runs for longer gaps:
| Gap since the last finalized block | Runs | Tail samples |
|---|---|---|
| under 100 blocks | 2 | e.g. 17 for 50 blocks |
| 100 blocks | 3 | about 30 |
| 500 blocks | 5 | about 68 |
| 1,000 blocks | 10 | about 150 |
| 10,000 blocks | 10 | about 200 |
| 100,000 blocks | 10 | about 250 |
A gap never needs more samples than it has blocks. The rollup can grow when more transactions want to be finalized in it:
- every two head blocks added require one more tail sample;
- a sparse rollup can add a block that doesn’t directly follow the previous one, and the gap before it is sampled in the same way, anchored on the last block.
Other transactions can join the rollup by providing a Merkle proof of their inclusion in one of its blocks and paying a minimum fee, either deducted from the funds the transaction unlocks or paid separately.
Cement
The rollup becomes valid once all its tail samples are satisfied. A sample already in the block store is satisfied by reference; otherwise anyone can submit it, provided its Equihash solution is valid and its difficulty is valid: consistent with Zcash’s difficulty rules and above the bridge’s difficulty floor. Because the samples are derived by Fiat–Shamir from the block headers themselves, a builder can’t choose convenient blocks, and a forger can only get a different set of samples by mining a different block. With every sample already stored, initiating the rollup costs 1.1M gas for the main block (about 950k to verify its Equihash, plus the storage writes that create the rollup) plus 2,100 gas to read each sample, about 1.4M for a 1,000-block gap. Cementing costs another 1.3–1.5M gas: one more Equihash verification plus bookkeeping.
Finalize
Finalizing a valid rollup notifies every transaction lock in it to open, if the transaction asked for that, and collects the fees for the validator. Its cost grows with the number of transactions it has to notify. The finalized rollup remains on-chain, and later transactions can reference it.
Validators and incentives
Building rollups is open to anyone willing to do the work: aggregating blocks and completing a FlyClient validation. The reward is a share of the protocol fees paid by every transaction that uses the rollup, so a validator profits by building rollups that many transactions want to join. Part of that fee goes to the oracles that submitted the blocks the rollup reuses. By default, a minimum-size rollup pays them 1.75% of the fee per block, and the per-block share shrinks as rollups grow so that oracles never receive more than half of the fee in total; the exact curve is a deployment’s choice. A validator that submitted blocks itself keeps those shares. See Oracles and the Block Store.
The incentives are self-correcting. A rollup with invalid samples can’t become valid; one whose blocks have suspicious difficulty is refused by participants, who recompute Zcash’s real difficulty off-chain before joining. Either way the builder loses its gas and earns nothing.
Trust model
A rollup involves no trusted party. Its validity rests on Zcash’s consensus rules and proof-of-work, checked through Equihash verification and FlyClient sampling, and on the contract code. The only configurable input is the per-bridge difficulty floor, which matters only to users who trust a bridge blindly; Proving Chain Identity explains why it is “trusted” only in quotation marks. A root-anchored rollup adds exactly one assumption: that each participant has checked the agreed root against its own view of the chain.
See also
- Chain Finality, including a cost comparison on Base
- One-Shot Finality
- Proving Chain Identity