Towards the endgame of blockchain interoperability with proof of consensus
Over the past few years, there has been a variety of different blockchain ecosystems offering decentralized settlement layers for various applications. These blockchains lie on different points of the tradeoff curve of decentralization, security, throughput, and cost. Decentralized applications have varied requirements and developers can choose which platform is best suited for their needs.
As the number of blockchains have grown, so has the fragmentation of the space. Generally, each chain runs in isolation, such that state in one chain is not easily accessible in another. As a result, blockchain ecosystems have become somewhat siloed, where assets such as tokens and NFTs, liquidity, and non-financialized positions such as governance votes or gameplay history are locked in the originating ecosystem.
One of the main promises of crypto and web3 compared to the previous generation of internet applications is permissionless interoperability. In a future where users want to use applications across ecosystems, it is important that these blockchains can communicate in a secure, decentralized, and permissionless manner. In this world, the interoperability layer is critical infrastructure. Reliable cross-chain communication is crucial for a seamless user experience.
Today, there is a lot of user demand for interoperability, mostly for token bridging. To meet these demands, the current solutions for bridging go through centralized entities. On one end of the spectrum, there are centralized exchanges (with off-ramps to different chains) functioning as asset bridges for a large number of users. Another popular bridge design is a multisig bridge (opens in a new tab), where a centralized entity controlled by a multisig of validators is responsible for watching one chain for deposits and signing off on withdrawals on another chain.
Not only does centralization ideologically contradict the values of crypto, it has very real, practical consequences. Centralized designs are not censorship resistant and have very large trust assumptions placed on a small set of trusted parties. Furthermore, these centralized bridges empirically have been much less secure than the underlying blockchains that they are bridging between. In the past six months, several bridge hacks have resulted in over a billion dollars of lost user funds. These hacks not only negatively impact users, but they also weaken the credibility of the entire blockchain space and lead to downstream consequences like regulation.
The current state of cross-chain interoperability is less than ideal. How can we do better?
Given two chains that do not have shared security (i.e. their validator sets and consensus mechanisms are potentially different) verifying the state of a source chain on a target chain is equivalent to validating the consensus of the source chain in the execution environment of the target chain.
This is the exact principle that light client nodes (opens in a new tab) use to keep track of the state of a blockchain in a compute and storage-efficient manner.
The best design for blockchain interoperability, assuming two chains with different validator sets, is to have an on-chain light client for a source chain running on the target chain (which is what IBC (opens in a new tab) does). With this design, there are no additional trust assumptions placed on cross-chain communication, aside from trusting the economic security of the consensus of each participating chain. (A more detailed discussion can be found in footnote1).
Once an on-chain light client can keep track of block headers of another chain, anyone can supply state proofs to prove any information (balances, storage, transactions, events) about the source chain in the context of the target chain. With this, building a cross-chain application, such as a token bridge becomes simple. We provide some pseudocode architecture below of how such a token bridge would work.
Historically, this approach has been difficult because on-chain computation is quite expensive. From a compute perspective, it’s not feasible to run these on-chain light clients--especially because different consensus protocols use different signature schemes that may not be supported across all execution environments. However, recent advances in zero-knowledge proof systems, which allow for succinctly verifiable computation, make this approach feasible today.
In blockchains, on-chain compute is much more expensive than off-chain compute. With zkSNARKs, the user (broadly speaking) can generate a proof of an expensive computation in a compute-cheap environment (off-chain) and then cheaply verify (using the succinctness property) the result of this computation in an on-chain environment. Similar to how zkSNARKs are powering zk rollup teams to scale execution, verifiable compute can also scale verification of consensus.
We believe that a significant step towards the endgame of interoperability is succinct on-chain verification of consensus.
In the short-term, verification of consensus has far fewer trust assumptions than current centralized approaches and is much more secure. In the longer term, once it is possible to provide a succinct validity proof of execution (using zk(E)VMs), we can combine the two validity proofs to have an on-chain light client that verifies both state transitions and consensus, for maximal security--similar to running an honest full-node on-chain.
We coin the term "proof of consensus" to succinctly 😉 encapsulate the idea described above: use zero-knowledge proofs to generate a validity proof of the state of a chain according to its consensus protocol. This validity proof can be used to power a gas-efficient light client, which facilitates trust-minimized interoperability. We note that we don't actually use the zero-knowledge property of "zero-knowledge proofs", we are using the succinctness property for scaling.
⚠️ This section dives into more technical details, feel free to skip ahead for information about Succinct Labs.
For a given consensus protocol, how does one generate a succinctly verifiable validity proof for the state of the chain? Here, proof of work (PoW) vs. proof of stake (PoS) and the actual details of the consensus algorithm matter quite a bit. We describe at a high-level an approach that works for most PoS consensus algorithms.
A quick review of PoS
Generally in PoS, there are a set of validators who stake capital and provide signatures that serve as attestations for blocks they believe should be part of the canonical chain. Different PoS systems have varied finalization mechanisms (a block is considered "finalized" if it cannot be changed without a significant amount of the staked capital being slashed), but in most PoS systems, if >2/3 of the validators have signed off on a block then the block is considered "finalized".
A quick review of zkSNARKs
Before we go into more detail, if you are unfamiliar with the concept of zkSNARKs, we recommend reading Vitalik's blogpost (opens in a new tab) that provides a great overview. We quote the most relevant part below as a reminder:
A zkSNARK allows you to generate a proof that some computation has some particular output, in such a way that the proof can be verified extremely quickly even if the underlying computation takes a very long time to run.
Combining the two
Verification of consensus is a computation that requires verifying for a particular block that there exist valid signatures from >2/3 of the set of known validators. If we are able to verify signatures within a zkSNARK and also verify these signatures came from a list of public keys corresponding to a set of validators, then we have a validity proof that a block is finalized. Futhermore, because of the succinctness property of zkSNARKs, this validity proof can be verified extremely efficiently on-chain.
The function signature of a SNARK proof looks like the following pseudocode:
def verify_block(block, signatures, public_keys, validator_set_commitment): for pub_key, signature in zip(public_keys, signatures): verify_inclusion(pub_key, validator_set_commitment) verify_signature(pub_key, signature, block) assert 3 * len(public_keys) > 2 * VALIDATOR_SET_SIZE
Generally for any consensus protocol for which we want to generate validity proofs, we have to implement the following core primitives:
- verification of the signature scheme used by the validators
- inclusion proof of validator public keys in validator set commitment (which is stored on-chain)
Both of the above look deceptively simple but are actually quite difficult! To implement various signature schemes inside a zkSNARK requires implementing out of field arithmetic and complex elliptic curve operations. We will explain more details in an upcoming blog post.
Another subtlety is we have to keep track of the set of validators, which changes with varied frequency according to the particular PoS protocol. In most PoS protocols, the current validator set signs off on the updated validator set, which we must keep track of on-chain as it is an input into zkSNARK proof (the
At Succinct Labs, we are dedicated to building the foundation of a decentralized, permissionless, and secure interoperability layer for blockchains. We believe that the latest breakthroughs in zero-knowledge proofs make it feasible to generate succinct validity proofs of consensus that can power on-chain light clients for trust-minimized interoperability. The terminal design for cross-chain communication will be proof-based, and we want such a design to become the canonical method for interoperability.
Our first partnership is with Gnosis Chain, generously funded by Gnosis DAO and 0xPARC. To build a trust-minimized bridge between Gnosis Chain and Ethereum, we built a succinct light client for Ethereum 2.0 proof of stake consensus (Gnosis chain also uses Ethereum 2.0 PoS). This involved building out zkSNARKs for BLS signature verification and verifying the validator hash to validate the Ethereum 2.0 PoS light client protocol. More technical details will be forthcoming in an upcoming blog post alongside a demo token bridge between Goerli (Ethereum test net) and Gnosis Chain.
In the future, we want to build succinct light clients for all consensus protocols to allow for trust-minimized cross-chain interoperability across all blockchains. Please reach out if your ecosystem is interested in these ideas!
We are also very interested in empowering builders using this primitive to build the next generation of interesting decentralized applications that live across chains.
We are very excited by the ideas in this blog post and are looking for collaborators to work with. The zkSNARK technology we are working with is cutting edge and the trust-minimized cross-chain communication protocol we are building will be quite impactful for the whole blockchain ecosystem.
Reach out if you're interested in joining the team: we are looking for strong developers with experience in Solidity and general smart contract engineering, blockchain infrastructure and writing zkSNARK/STARK circuits.
If your blockchain ecosystem or application is interested in using our underlying primitives, please reach out as well. We're looking for a small group of early partners and would love to chat.
Finally, we would like to thank Gnosis DAO for an extremely generous grant to fund the R&D behind this work and much of the originating ideas in this blog post and 0xPARC for grant funding and supporting us from the beginning.
If >2/3 of source-chain validators collude to double-sign a header to decieve the light client, then as long as the signatures are data-available, these validators are subject to any source-chain slashing conditions. To decieve the light client without getting slashed, >2/3 of the source-chain validators must collude to go offline during their normal duties (incurring applicable penalties) and also sign an invalid header. IBC-based interoperability also has this exact weakness. In the future, once zk(E)VMs become omnipresent and it becomes possible to provide a succinct validity proof of execution, we can succinctly verify both execution and consensus of a source chain on a target chain. Then our on-chain light client will reject invalid state transitions, similar to an honest full-node. ↩