The 4 Features of a zkVM: How to Choose your ZK Toolkit
Paul Gafni
So, you’ve realized the power of using verifiable, off-chain computation to scale blockchains.
You have a project you’d like to build, but you’re not sure where to start building. How should you evaluate your options?
This article will guide you through the key features you’ll need, and contextualize the state of ZK tooling today. We’ll consider the following questions:
Why should you choose a zkVM?
What are the essential features of zkVMs?
Which zkVMs offer these essential features?
Why should you choose a zkVM?
Two years ago, the primary workflow for ZK software development was to write circuits by hand using circom. The process of writing circuits is incredibly labor-intensive: circuits are difficult to write, update, audit, and maintain. The time and cost required to bring a circuit-based ZK project to market is on the order of 2 years and $100 million dollars.
Over the past two years, RISC Zero has demonstrated that rather than writing circuits directly, writing an application for a zkVM is a much faster/cheaper option for getting your project to market. zkVMs make ZK accessible to ordinary developers, and make it possible to bring complex applications to reality in the course of a weekend.
In early 2022, we unlocked the ability to prove correct execution of regular Rust code, including your favorite Rust crates. Suddenly, ZK builders were able to focus on building real applications, leveraging all the mature tooling of the Rust ecosystem.
Today, there are a number of options for zkVMs, which brings us to our next question…
What are the essential features for a zkVM?
There are four things you’ll definitely need in order to build anything interesting.
Support for importing crates/packages.
Support for on-chain proof verification.
Support for unbounded computation, without ballooning costs for verification.
Support for proof composition.
For the purposes of enabling the ZK future, these four features are mandatory. Keep reading to find out which zkVMs offer these features, and why they’re so important.
Which toolkits offer these features?
As of this writing, here’s the state of the zkVM industry.
For each of these features, let’s run through a quick explanation of:
Why it matters
Why it’s hard to implement
RISC Zero’s approach
Feature 1: Crate Support
Why it matters
Without support for importing crates, software development is a nightmare. Allowing developers to import crates is essential for any complex application.
Why it’s hard to implement
A couple years ago, ZK systems were so inefficient and hard-to-build that they could support a mature language like Rust or C++ seemed technologically out-of-reach. Today, the trend in zkVM development has moved from bespoke instruction sets to standard instruction sets like RISC-V, MIPS, and WASM.
RISC Zero’s approach
In April 2022, RISC Zero released the first zkVM capable of making proofs about a high level language like Rust or C++. Today, we run nightly tests to check compatibility of the top 1000 Rust crates with our zkVM; currently 70% work out-of-the-box. Check out our examples directory to see examples of how to use Rust crates inside the zkVM.
Feature 2: On-Chain verification
Why it matters
On-chain verification is tables stakes for ZK applications in blockchain – the basic recipe is:1. Prove computation off-chain.
2. Verify computation on-chain.
Why it’s hard to implement
Proof system design involves a fundamental tradeoff between prover complexity and verifier complexity. The current trend is that SNARKs based on hashing and error-correcting codes (aka STARKs) offer the best prover costs for zkVMs, while SNARKs based on elliptic curves offer better on-chain verification costs. zkVMs today typically include a merger of multiple proof systems in order to get the best of both worlds.
RISC Zero’s approach
RISC Zero uses STARKs for efficient proving, and then verifies the STARK proof inside a SNARK circuit in order to “translate” the STARK into a SNARK. In August 2023, we posted and verified our first proof on Sepolia. Today, we support an on-chain verifier contract that works for any zkVM application.
Feature 3: Unbounded Computation Size, with constant verification costs
Why it matters
If you want to prove the correct construction of an Ethereum block or an OP block, you’re going to need to prove a very large computation.
Why it’s hard to implement
The naive approach to proving large computations doesn’t scale well – increasing the size of your computation by 2x will increase the computational complexity by more than 2x. In order to unlock unbounded computation size (without interfering with on-chain verification), we need two components, each of which is a major technical feat:
The ability to split a large computation into chunks, to be proven separately
The ability to aggregate these “segment proofs” into a single succinct proof.
RISC Zero’s approach
RISC Zero introduced continuations to address the problem of generating proofs for computations of unbounded size – we prove each segment independently and then use recursion to aggregate the segment proofs. With this approach, RISC Zero manages to achieve linear-time proving with constant verification costs.
Feature 4: Proof Composition
Why it matters
Proof composition (aka proof of proof) unlocks a wide variety of use cases, including more complex privacy applications, more modular zkVM applications, and proof aggregation (including proofs from RISC Zero and from other proof systems).
Why it’s hard to implement
Making proof composition efficient is sufficiently challenging that no one besides RISC Zero has even mentioned the idea. Unlocking this feature requires not only a solution to the problem of recursion, but also requires building an API to allow developers to call the recursive prover from inside the zkVM.
RISC Zero’s approach
Users can access proof composition by calling the `env::verify()` function inside the zkVM. This feature is new as of February of this year; learn more about proof composition in this blog and/or this study club session.
Recursive Circuits: the hardest part of ZK building
Three of these key features (on-chain verification, unbounded computation, and proof composition) rely on recursion. In the ZK world, recursion refers to the ability to prove the correct verification of a proof. In other words, you run the verifier inside the prover.
This may sound straight-forward, but building recursive circuits is notoriously complex. The RISC Zero zkVM is designed to be as easy-to-use as possible, but under the hood, we’re maintaining compatibility of three related but separate ZK circuits. At RISC Zero, we actually have two STARK-based zkVMs: we first use our RISC-V circuit to generate proofs of RISC-V execution, and then we use a separate recursion circuit to aggregate those proofs. And then, we feed the result into a SNARK circuit in order to enable on-chain verification.
The engineering required here is a serious endeavor – in order to support this effort, we’re building an MLIR-based language for building recursive circuits called Zirgen. To learn more about Zirgen, check out this talk from Julian Sutherland (Nethermind).
How should I compare zkVMs today?
Performance seems to be the most natural axis for comparison, but unfortunately, benchmarking for ZK projects is still in its infancy. There are a number of benchmarking projects out there, but it turns out to be incredibly difficult to come up with a robust framework for apples-to-apples comparison.
Before comparing performance, make sure you’re looking at an apples-to-apples comparison in terms of capabilities. When a newer entrant announced their version of Zeth, they were quick to claim that their proofs of block construction is 30x faster than RISC Zero. Unfortunately, their Zeth proofs are also 1000x larger than ours. If you can’t get your proofs on-chain, does it really matter how fast you can generate proofs?
RISC Zero has been focused on getting a feature-complete zkVM ready for production use. Once we wrap up our audits and our trusted setup ceremony, and get our verifier deployed on mainnet, you can count on some serious performance improvements. For now, we recommend using the only feature-complete zkVM: RISC Zero.
Besides the features mentioned above, what other features are important?
A couple of other features worth mentioning are:
Deterministic buildszkVMs natively prove correct execution of a given binary file, but for most use cases, we’ll want to be able to prove correct execution of a given Rust program (or some other high level language. RISC Zero addresses this problem with our cargo risczero tool.
Accelerator circuit support
When you identify a performance bottleneck in a zkVM application, it would be nice to be able to modify the zkVM in order to offer use-case-specific acceleration. For example, one might add a Keccak accelerator to support efficient proofs about Ethereum block construction. RISC Zero currently offers acceleration for big integer operations and SHA; check out Victor’s upcoming talk at zkSummit 11 to learn more about our plans to expand this functionality.
Proof aggregation support
Proof aggregation refers to the ability to consolidate many proofs into a single proof. This feature is essential for making on-chain verification affordable. Proof composition enables this feature, but it’s worth noting that other systems may offer a solution to proof aggregation without fully solving the problem of proof composition.
If you’re ready to build, check out our Get Started guide and docs.