Achieving fast finality with sovereign zk-rollups
Sovereign
0xd974
March 7th, 2023

There’s a broad misconception in the crypto space that zk-rollups have a very long time-to-finality. In this post, we’ll explain why first-generation zk-rollups take so long to finalize, and how we can achieve lower latency without sacrificing security.

By solving this problem, we’ll motivate a design for sovereign zk-rollups. Then, we’ll briefly explore the other advantages offered by sovereign designs.

Finality Bottlenecks… and How to Solve Them

For most zk-rollups, one of the largest expenses is proof verification. Depending on the underlying proof system, a rollup on Ethereum might spend anywhere from 300k to 5m gas to validate a single proof. But since proof sizes grow very slowly (or not at all) with the number of transactions, rollups can reduce their per-transaction cost by waiting to accumulate a large batch of transactions before submitting a proof. And indeed, this is exactly what most zk-rollups do today; popular rollups like StarkEx typically post proofs to L1 only once every few hours.

But waiting several hours for your transaction to finalize is an unacceptably bad user-experience. Can we do better? If a rollup posts raw transaction data onto its DA layer (rather than state diffs), then power-users who want fast finality can run full nodes. But if the rollup uses state-diffs, then even running a full-node doesn’t help. This is why most zk-rollups today have their sequencers give out “soft confirmations”. But soft confirmations are only possible in systems with centralized sequencers. So the question remains - how do we make decentralized zk-rollup competitive on latency?

If we only care about lowering the latency for full-nodes, then posting raw transaction data on chain solves the problem. As long as the full transaction data is available, full nodes can finalize as quickly as transactions can be applied (assuming the DA layer has single-slot finality). This lets our zk-rollup be just as responsive as a traditional L1!

This is a very powerful result. It makes zk-rollups viable for highly latency-sensitive applications like on-chain order books. Nevertheless, it doesn’t completely solve the original problem. What we really want is to reduce latency for light clients. Can we do that without drastically increasing proof verification costs?

Surprisingly, the answer is still yes! Here’s how: instead of waiting to create a single batch proof, we can create proofs in real time and use recursion to aggregate them into a batch proof later. As long as we distribute incremental proofs right away via the p2p network, light clients will experience fast finality. And since we’re still just posting the slower batch proofs on chain, we don’t have to pay extra for on-chain verification. In other words, we still get a trust-minimized bridge with the L1 - but the bridge is no longer the source of truth for light clients. Congratulations, we’ve just built a sovereign rollup!

Proving the Fork Choice

Eagle-eyed readers will have noticed a problem with the system described in the previous paragraph. In today’s rollups, the L1 smart contract is responsible for enforcing the rollups fork-choice rule. In other words, the smart contract doesn’t just verify the zk-proof, it also checks that the proof builds on the previous proof (and not some other fork), and that it’s processed all of the relevant “forced transactions” which were sent on L1. So, if we don’t use a smart contract, how do we pick a canonical fork?

Once again, the answer is surprisingly simple - if we require proofs to be posted as calldata on the L1, then we can add a rule that a new proof is only valid if it builds on the previous valid proof. Although we could enforce this rule client-side, it would require users to scan through the chain’s history all the way back to genesis (or at least some widely known checkpoint) - which isn’t ideal.

Thankfully, it’s not too hard to add it directly into the zk-proof instead. By tying calldata back to the L1 block headers, we can add a statement saying “I have scanned the DA layer for proofs (starting at block X and ending at block Y), and this proof builds on the most recent valid proof”. This lets us prove the fork-choice rule directly, rather than enforcing it client side! And if we’re already scanning the DA layer for proofs, we can easily scan for forced transactions as well.

Portability and Interoperability

In the Smart Contract rollup paradigm, the L1 bridge is unique. Since the bridge is responsible for checking statements that aren’t included in the proof (statements like “this proof includes all of the forced transactions”), adding proof-based bridges to other destinations doesn’t usually make sense. But once we’ve moved all of our logic inside the proof, this is no longer an issue. We can add bridges anywhere we want!

And we can even go a step further. If our L1 smart contract is just a regular bridge, we can do away with it altogether. For the first time, it makes sense to think about building rollups on systems that don’t support smart contracts. Just take your existing rollup logic and remove the L1 bridge. Suddenly, you can deploy on any DA layer! In other words, your rollup logic becomes instantly portable across different L1s.

Conclusion

The future of rollups is sovereign. By proving their fork-choice rules directly, sovereign zk-rollups enable seamless interoperability, instant portability, and fast finality. Just like smart-contract rollups, they provide low gas costs and trust-minimized bridges - but they aren’t forced to trade-off between cost and latency. Sometimes, you can have your cake and eat it too 🙂

As always at Sovereign, we’re building in public. All of our code is free and open source, and contributions are welcome. Oh, and we’re hiring. If this sounds interesting, come build with us!

Subscribe to Sovereign
Receive new entries directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.