ZK13: Bringing modularity to zkVMs with OpenVM - Yi Sun

28 May 2025 · 13:41

Recorded at ZK13 in Toronto, Yi Sun of Axiom introduces OpenVM, a modular zkVM framework built on a no-CPU architecture where the execution trace is never materialized in a single circuit. He explains how customizable VM extensions, groups of opcodes sharing common memory, support RISC-V execution, unbounded program proving through continuations, and on-chain verification, and shares performance benchmarks for the framework.

Speakers

Topics

Transcript

[Music] Hey, my name's Ye and I'm here to talk about OpenVM. And so I I think I can skip this slide given Jeremy's talk right before, but OpenVM is a ZKVM framework. And the main impetus for OpenVM is this trade-off be between performance and usability of current ZKVMs that occurs primarily at the ISA level. So I think broadly there are two types of ZKVMs today. I would say some use a ZK adapted ISA uh things like Cairo or Valita where they've created a entirely new ISA um which is tailored

for the performance characteristics of ZK. Now the advantage of this is that it's going to be much faster if you're able to pair your ISA to the actual proving you're doing. up the problem is all programs need to be rewritten to run on this ISA uh which is a challenge from an engineering perspective and a security perspective. Now the other approach which Jeremy was speaking about is to use an ISA which appears in an existing processor and this has the very big advantage that you can use existing compiler tool chains. Uh but it can impose some performance overhead because risk 5 is not designed to be proven in ZK. And what's common between both of

these choices is that the VM is committing to a fixed choice of ISA. And so with OpenVM, our design philosophy is to try to remove this trade-off between performance and usability of the VM by introducing a modular approach to putting together a ZKVM. And so what is a OpenVM? It's really a framework for constructing ZKVMs that is modular and designed for customization and extensibility. Uh so it can prove arbitrary Rust programs. Um, it's fully modular around a concept of VM extensions and it all rests upon a new type of ZKVM architecture we're calling

the no CPU architecture. So, first let me tell you what OpenVM can do today. Um, as I mentioned as a developer using OpenVM, you can construct your own modular ISA using a concept we're calling a VM extension. An extension is a set of op codes that's able to interoperate over op codes interoperate with op codes from other extensions over a set of common address spaces. So these address spaces can be typed meaning we can have address spaces for risfi format memory or address spaces which are natively in the native field which is particularly useful for recursion.

Um so OpenVM ships with a default set of extensions covering riskfi support, recursion support and all common pre-ompiles which occur in proving Ethereum blocks. However, the design of OpenVM is fundamentally extension first, meaning the framework itself does not commit to any particular extension and all functionality is implemented through extensions that live on an equal basis to extensions that you could yourself add to OpenVM. In particular, it's possible for developers to write and add their own OpenVM extensions without forking or modifying the core library.

Um, one thing this allows us to do is to accelerate performance for particular workloads with custom VM extensions. So for the recursion part of OpenVM, we applied this technique to heavily optimize the recursion circuits and we recently worked with Powder Labs to create an PC to automatically synthesize extensions uh based on user programs. And one thing to note is that these extensions created by powder are able to interoperate with user programs without any modification to the core open VM libraries. So another possibility that

the modular approach opens up is to support multiple tool chains over the same backend. So today we support uh Rust tool chain by building to RV32. Um and we also support a tool chain that's more adapted for native recursion. Both the Rust and native tool chains build to an openVM program binary after which we have a uniform process of turning them into Stark proofs applying recursion and ending up with a proof verifiable efficiently on the EVM.

And so in particular on both tool chains we support arbitrary unbounded execution. So how does this work? Now the key design consideration we had was to not be skumorphic to existing processor architectures when we're building the ZKVM. And the reason is that obviously the constraints of ZK are quite different from the constraints of physical hardware. And the one thing we realized is that existing ZKVMs have a central CPU trace where essentially every op code in the VM must be processed in this trace and as a result there's a centralizing

effect in that this circuit needs to know about all the op codes and process all of them and typically this will be the largest trace in any segment of a VM. So in openVM we're introducing uh what we're calling a no CPU architecture. What that means is that there is no single tra chip in the open VM circuits that knows about all the op codes. And so instead the execution consistency of the VM is just spread out around different components each of which only apply to one set of op codes. So this has two advantages.

First, it just removes a lot of cells from the trace, allowing for faster proving, but probably more importantly, it allows us to create modularity at the ISA level. If you want to add more op codes to the VM, you simply create a chip that plays well with the other chips and conforms to the API interface. And in particular, because the central CPU circuit doesn't need to know about any other op codes, uh you don't need to fork the core library. Another feature that we've added to is the ability to handle variable word sizes in memory. So in existing ZKVMs, typically there's a fixed word size

that's applied across all all of memory. Um that's similar to how in a sim in a physical processor, of course, physical RAM has a word size. And so what that means is if you're running an operation that's accessing larger blocks of contiguous RAM, then you'll typically use multiple u memory accesses. So in OpenVM, we actually introduce offline memory checking with a variable word size. So we allow block sizes between 1 and 32. And in particular, if you write a block of size 32, you can directly read it without breaking it up into blocks of size one.

behind the hood, we convert between these blocks uh with length adapters if you happen to write a larger block and read a smaller component of that block um later. And so the consequence is that when you're adding different chips into the system, you don't need to keep a uniform word size. You can create chips with the block sizes that make sense for your application and behind the scenes the framework will convert between them for you. And finally, we're able to handle proving unbounded programs via a continuations approach. Uh so we separate a large execution into different segments, prove them

independently, and then apply a recursion program um all the way to an EVM verifiable proof. Uh one thing to note is that we're able to config flexibly and configurably change the degree of the recursion um as well as the configuration of the VM in the recursion without modifying the final verifier. All of those can be done dynamically in the recursion. So let me just tell you concretely what OpenVM can do today. So we're able to prove Ethereum mainet blocks. Uh currently we have a CPU prover and on a range of a thousand recent blocks uh we're able to prove in 8 minutes average for close to 0.1 cents

per transaction. Um if parallelized we're projecting around 90 seconds uh parallel. Um, we just went live on scroll mainet uh last month and they were able to see a number of the benefits of actually using a ZKVM instead of using handwritten ZK circuits they had previously. And I want to say that we're continually working on the performance. So give to give you a sense on the progression over time, we released the first public version of OpenVM in December. So that actually already had onchain verification and as you can see in the last couple months we've been

able to improve both the cost and latency of proving quite a bit. Um these graphs show our progression on block 21 million. Um so as of the latest benchmarks which are a bit more recent than the average sample we're able to prove that in a little over 6 minutes on a single CPU machine. So in the next couple months, we're going to continue to optimize and add features for OpenVM. Uh to talk through a couple of the highlights, first we are building a GPU prover to further accelerate uh proving and working on making our execution and trace gen zero copy. Uh secondly, on the ISA front, one

thing we think is really exciting about the modular approach is to add support for different ISAs like RV64 and web assembly while maintaining uniformity on the VM back end. Um secondly, we think it's interesting to keep pushing this programspecific pre-ompile direction to really enable developers to accelerate uh a ZKVM for their specific workload. And finally, we're building out a hosted API for OpenVM uh to allow developers to try out proving on OpenVM and deploy to production on Axiom's hosted cloud infrastructure. So if you want to find

out more about OpenVM, you can check out our developer book or the codebase. And if you're interested in getting support from Axiom on implementing OpenVM in your application, you can fill out a form we have at our website. Uh so I think we have time for a couple questions. Yeah, we got about 2 minutes for any questions for Ye. Yeah, I really like the slide on when you were comparing the Rust. You write in Rust and then at the very end you have this uh EVM verifier. Um I just wanted to understand how does that compare to things like risk zero from a app developer or a developer point of view? Like what should I be like considering in terms of trade-offs? What do I get here? I I don't get here.

Yeah, I I would say the the developer experience at a high level is pretty similar. You write in Rust and you get an EVM proof. I think there the ZQVM trade-off space is quite highdimensional. So I think there are a number of places where we do differ. Um in terms of the VM architecture, I think it's pretty different. Um Jeremy would be the person to talk to about that. Um on the EVM verifier, we don't use Grath 16. uh we actually use uh Halo 2 verifier that does not have a circuit specific trusted setup. Um in terms of the way we handle VM extensions in Rust, it is actually quite different uh to risk zero. So ris I believe uses e- call

to do sis calls for pre-mpiles. Uh we use uh rust intrinsics and kernels to call out to actually new op codes that we're embedding in the risk 5 elf. Um, so this is parallel to how Rust handles SIMD intrinsics and calls to GPU kernels. So one feature that this enables is the kernels are allowed to not just run a single instruction that reads and writes to risk 5 memory, but actually operate on an address space that is not risk 5 typed. And so this enables us to have a feature to recursively verify an openVM proof from within an OpenVM program.

I'm sure there are many other differences, but I just want to call out some highlights. All right, I think we're about at time. Thank you for the question, and let's give a hand to Y up here for the talk.