A core design choice of Celestia is to minimise on-chain state, thereby creating an overhead-minimised and minimal DA layer. This means that Celestia does not have an on-chain smart contract environment, and does not act as a “settlement layer” (i.e. a bridging hub) for rollups. Instead, developers are expected to deploy their own settlement layers and shared security clusters on Celestia that rollups can use if they wish.
This allows Celestia to be credibly neutral to rollup settlement layers or shared security clusters built on top of it regardless of what execution environment they use. However, this means that although rollups can form trust-minimised validating two-way bridges with each other, they cannot form one with the Celestia L1 itself to bridge Celestia tokens (they can, however, use IBC and non-native committee-based bridging solutions). For this reason, we do not call rollups on Celestia “L2s”; they are independent (and possibly sovereign) clusters of chains that use Celestia for ordering or DA.
In order to allow for rollups to be L2s of Celestia and form a trust-minimised bridge, Celestia needs to achieve “functional escape velocity”, which in this case means having a sufficiently expressive execution environment such that you can run a validating bridge (i.e. run a light client for the rollup) that can withdraw or deposit assets to a rollup.
Previous wisdom has told us that in order to achieve functional escape velocity, you need a smart contract environment where it is possible to “execute custom user-generated scripts on-chain”. However is it possible to achieve functional escape velocity without a smart contract environment, thus still retaining Celestia’s credible neutrality and overhead-minimisation? It turns out that yes, you can, by simply adding a ”ZK verification key address type” to Celestia, and utilising sovereign ZK rollups.
A zkSNARK verifier consists of a verifier V that computes V(vk, x, prf) and returns true if the proof is correct, where vk is a verification key that corresponds to some ZK program, x is a public input, and prf is the proof. We notice that this is actually very similar to verifying signatures for standard blockchain addresses with standard public keys (e.g. using ECDSA). Therefore, what if we simply added a new type of blockchain address and “signature scheme”, where a blockchain address is a ZK verification key that funds can be sent to, and funds can only be spent from that address upon providing a valid public input and proof (the “signature”)?
This would allow you to send funds to arbitrary ZK programs, that dictate the conditions needed for funds to be withdrawn. That ZK program can be a light client for a sovereign ZK rollup, that only allows funds to be withdrawn if a valid withdrawal transaction occurred on the ZK rollup. A sovereign ZK rollup does not require an on-chain smart contract to track its latest state. Instead, the rollup’s fork-choice rule can be executed directly inside the ZK rollup’s program. Quoting Sovereign Labs:
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.
From an implementation perspective, the basic idea is that the public input to the rollup’s Celestia ZK address would be the last Celestia block height (which would be enforced as an input by Celestia’s state machine), and the identifier of some “withdrawal transaction” on the rollup. The ZK program would return true if up to that block height, the identifier corresponds to a valid, unclaimed, withdrawal transaction.
Optimistic rollups can also benefit from this, if they settle and post their fraud proofs to an intermediate or “wrapper” sovereign ZK rollup. This is effectively “ZK proofs of fraud proofs”.
There is a question over what zk scheme to support, and if we need to support multiple. However, even if we support one, and a rollup uses a different scheme, they may be able to use recursive proofs (a ZK proof of a ZK proof).
This post describes the most state-minimised functional escape velocity possible, however if we add some extra state, it can be beneficial to rollups. For example, if add a special transaction type to also update the state root of a rollup on-chain, this means the rollup no longer has to recursively prove previous proofs.
Thanks to Preston Evans for helpful comments on this post.