An introduction to zero-knowledge virtual machines (zkVMs)

Jun 20

| 7 min read

This is the first article in our series exploring the security of zkVMs and the applications built on top of them.

zkVM security series:
📚 Part I: Introduction to Zero-Knowledge Virtual Machines (zkVMs)
📚 Part II: Identifying common vulnerabilities in zkVMs
📚 Part III: Writing and auditing secure zkVM applications: A practical example with RISC Zero

Introduction

Zero-knowledge virtual machines (zkVMs) are transforming the way developers approach verifiable computation. By abstracting away much of the underlying cryptography, zkVMs enable developers to write provable programs in familiar programming languages. This is especially useful in blockchains with smart contract capabilities. It allows for more scalable applications without requiring deep cryptographic expertise.

At Veridise, we’ve worked on a number of zkVM-related audits. We’ve conducted in-depth security reviews of entire zkVMs, for example, for RISC Zero and Linea, and have also audited many zkVM applications built on top of them. These experiences have given us a good view into the kinds of pitfalls, design decisions, and security issues that tend to come up in practice.

This article shares some of the lessons we’ve picked up through our audit work, with the goal of providing practical guidance for security researchers in the zero-knowledge space, and developers who are planning to use zkVMs.

We’ll cover ZK circuit pitfalls that still apply inside zkVMs — such as weak input validation, replay vulnerabilities, and front-running attacks — as well as challenges unique to zkVM environments, like improper use of libraries. We also include a concrete example of a mock zkVM program written in RISC Zero to illustrate these points in practice.

What are zero-knowledge proofs?

Zero-knowledge proofs (ZKP) are a cryptographic construct that allows one to prove a statement is true without revealing any other information. This enables a form of verifiable computation, which essentially means that the result of the computation can be verified to be correct without having to execute the computation.

This paradigm operates with two parties participating: a prover who is looking to convince a verifier they executed a computation correctly. This enables two primary benefits:

  1. Privacy — Programs can be designed to operate over private data. The guarantees of the ZKP ensure that the inputs to the program (the private data) conform to the defined constraints of the system.
  2. Scalability — Computationally intense programs can be offloaded to servers that provide guarantees on the legitimacy of the claimed output of execution, with verifiers doing a much smaller amount of work to verify this legitimacy (this is technically due to a property called “succinctness,” which is built into the design of most popular ZKP systems).

Notice the word constraint used in (1). This is the core of what ZKPs enable: guarantees that the prover has satisfied a set of constraints that the verifier has access to and can efficiently check (without checking each individual constraint). As can be seen in later sections, these constraints are what zero-knowledge circuit developers create, either directly or indirectly, in order to mathematically ascertain a computation has occurred correctly.

Virtual Machines (VMs) in a nutshell

Virtual Machines (VMs) are emulations of computer systems. Just like physical computers, they contain their own means to process a set of instructions, except this virtual execution is all emulated in software instead of directly executing on a CPU. While entire computers can be emulated, in the context of a zkEVM, a smaller instruction set is interpreted with more limited functionality.

As an example of a VM, if you develop smart contracts on Ethereum or related platforms, you are hopefully aware of a VM that you are already interacting with: the Ethereum Virtual Machine (EVM). This article will not dive deep into the EVM, for that I recommend this fantastic series by Noxx.

However, the EVM is a great example of a simple VM used for simply processing a set of instructions. It is a program (with multiple different implementations that conform to the same standard) that exposes an instruction set to manipulate a stack-based virtual machine.

Let’s have a look at an example.


The default example OPCodes in the playground at https://www.evm.codes/playground

In the example above, the value of 0x42 is stored in memory (via MSTORE) at the 0x00 location. The size of the return data (32 bytes) and location (0x00) in memory where the data is stored are pushed to the stack, and then the RETURN opcode is executed. The EVM contains some unique instructions (such as RETURN) that are appropriate for a smart contract environment. Not seen in this example are instructions that modify a separate storage area in which accounts in Ethereum can store arbitrary data.

In reality, these instructions (PUSH1, MSTORE, RETURN) each have a unique byte value in which the EVM interprets to determine the instruction to execute. The above example would be represented as 604260005260206000F3, in which the 0x60 instruction translates to the PUSH1.

This paradigm of having a simple, stack-based virtual machine allows a deterministic execution of code that guarantees all correct implementations will resolve to the same state for given bytecode and identical user inputs, starting blockchain state, and other environmental data. This is necessary for a smart contract-enabled blockchain to function: all nodes must be able to verify that the execution of a block and the resulting storage and balance changes are valid.

The EVM is just one example of a deterministic VM. In general, all single-threaded execution environments aim to have a specification that enables deterministic execution in their specified domain. With a well-defined instruction set, a stream of bytes can be interpreted as a program to be executed by such a VM.

Now that we understand both zero-knowledge proofs and virtual machines, we can explore how zkVMs combine these two concepts to create a new paradigm in verifiable computing.

Introducing zkVMs: Verifying programs without re-execution

By combining VMs and ZK, the guarantees surrounding a deterministic virtual machine can be taken a step further. Instead of requiring re-execution of the entire VM, a VM implemented in a ZK proving system can be utilized to output a proof that correct execution occurred inside the VM with respect to the input provided. These are called zero-knowledge virtual machines (zkVM). The security of these relies on the correctness of the VM implementation and the soundness of the ZK proving system.

zkVM implementations are created by the tedious process of programming each individual component of a VM as a series of constraints. Examples of these components are memory reading/writing operations and instruction handling. When combined, the circuit for the VM (ideally) constrains the ZKP to only produce proofs for valid executions. Once a general-purpose zkVM is built, developers can supply a program and its inputs for execution, and the zkVM will produce a corresponding proof. Given that zkVMs are created for existing instructions sets, this allow writing a ZK application in a common programming language and already existing libraries in that language’s ecosystem can instantly become available for usage inside of circuits.

The diagram is taken from RISC Zero’s blog article “Designing high-performance zkVMs

Sidenote on zkEVMs: Emulating the EVM inside zero-knowledge circuits

While this article focuses on general-purpose zkVMs, it’s worth briefly highlighting a related but more specific development: zkEVMs. A zkEVM is a type of zkVM specifically designed to emulate the Ethereum Virtual Machine (EVM) within a zero-knowledge context. The distinction matters — zkEVMs aim to support Ethereum-compatible smart contracts and execution models, whereas general zkVMs often won’t have components optimized for Ethereum-specific operations.

In the blockchain space, the work towards zkEVMs is being actively pursued by many different organizations. There are two main goals for creating a zkEVM:

  1. Enables zk-rollups (aka validity rollups). At a high-level, rollups (aka L2s) are separate blockchains that anchor the finality of their state to a different chain, dubbed the L1 (Ethereum). The zk-rollup enables this blockchain to produce a proof that a proposed state transition is valid and therefore enables fast finality for the L2 on the L1.
  2. Enable efficient verification of Ethereum state. A general purpose zkEVM can prove the valid execution of a series of Ethereum transactions (and blocks). This will enable users to download the latest Ethereum state, along with a ZKP and have confidence the state was correctly produced from executed transactions. This is much faster than the normal syncing process of requiring local re-execution of every single transaction that has occurred since the inception of the chain.

Both of these use-cases rely on executing transactions/blocks inside of the zkEVM and offloading the trust of the output to the “zk” part of the zkEVM. As mentioned in the “What are zero-knowledge proofs?” section above, this presents large scalability benefits and even possible privacy benefits. If the operator of the L2 is trusted to keep transactions private, the L2 can introduce techniques to enable users to transact privately on the L2, with the L1 only learning that the executed transactions are valid.

While zkEVMs are a popular specialized use case, in the following articles we focus on general-purpose zkVMs.

That’s it for Part I of our zkVM security series. Stay tuned for Part II, where we’ll walk through the most common pitfalls and vulnerabilities in zkVMs.

Author: Tyler Diamond, Security Analyst at Veridise

zkVM security series:
📚 Part I: Introduction to Zero-Knowledge Virtual Machines (zkVMs)
📚 Part II: Identifying common vulnerabilities in zkVMs (Coming in two weeks!)
📚 Part III: Writing and auditing secure zkVM applications: A practical example with RISC Zero (Coming in four weeks!)

More by Veridise

Subscribe to our blog

Be the first to get the latest from Veridise — including educational articles on ZK and smart contracts, audit case studies, and updates on our tool development. Delivered twice a month.

Please enable JavaScript in your browser to complete this form.