This guest post is part of Building with S-two-a series showcasing what teams are building with the fastest prover in the world.
By Michel Abdalla, Senior Research Scientist, Nexus
At Nexus, we’re building a general-purpose zero-knowledge virtual machine (zkVM) designed for scalability, modularity, and developer usability. Our mission is to make verifiable computation truly programmable by abstracting away low-level cryptography while preserving performance and flexibility.
To realize this vision, our team brings deep expertise in cryptographic protocol design, systems engineering, and virtual machine architecture. We’ve been working to close the gap between powerful proving systems and general-purpose execution environments-so developers can build real-world applications in familiar languages and still benefit from verifiable computation.
Our aim is to make proofs an integral yet unobtrusive part of the development process, enabling efficient verification without requiring developers to grapple with the underlying constraint systems.
Achieving this balance between usability and rigor, requires careful architectural choices. What sets our approach apart in the zkVM space is our emphasis on performance without sacrificing modularity. Instead of designing our system to consolidate all program behavior into one large constraint system, we divide the system into distinct, well-defined components-such as memory management, instruction execution, and control flow logic-each with its own responsibilities and constraints.
Our zkVM design improves maintainability, simplifies debugging, and allows independent updates and optimizations to each subsystem. This allows us to scale proofs efficiently, support distributed proving in the future, and extend our system without needing to rewrite the entire constraint system or rework unrelated components.
To support this modular architecture in practice, we’ve built a zkVM that works seamlessly with existing tools and developer ecosystems. It supports standard languages like Rust and C, compiles to the RISC-V instruction set, and enables verifiable computation with minimal friction.
With zkVM 3.0, we’ve taken a significant step toward realizing this goal.
What we’re building with S-two
Our zkVM is built around the RISC-V 32-bit instruction set, chosen for its simplicity, wide adoption, and extensibility. We arithmetize this machine as a set of modular AIRs (Algebraic Intermediate Representations), where each AIR corresponds to a specific component of the system-instruction decode, register read/write, memory access, or arithmetic semantics. This modularity is key: it allows us to analyze, verify, and optimize each component-such as instruction decoding, memory handling, or arithmetic logic-individually and lays the groundwork for modular and parallel proofs.
To support this architecture, we’ve chosen S-two, a high-performance STARK prover developed by StarkWare, as the proving backend for zkVM 3.0. It provides a hash-based commitment scheme, is fully transparent (no trusted setup), and is well-suited for general-purpose proving systems like ours. Since S-two operates directly on AIRs, we reimplemented the zkVM’s arithmetization in this form-transitioning from our earlier R1CS-based representation to a structure better suited for S-two’s proving backend.
This integration also complements our focus on usability and developer experience. Developers can write programs in standard languages like Rust or C, compile them to RISC-V using familiar toolchains such as GCC or LLVM, and run them within our zkVM to generate proofs of correct execution. This workflow preserves existing development practices while opening the door to cryptographic verifiability with minimal disruption.
Building on this foundation, we’re particularly excited about the potential it unlocks for client-side proving. We envision a future where developers can embed lightweight provers directly into applications, whether web-based, mobile, or embedded. With the ability to compile the prover to WebAssembly (WASM) or mobile-native formats, we enable lightweight, local proof generation on end-user devices. This unlocks a wide range of privacy-preserving applications-where computation happens locally and verifiably, without relying on centralized infrastructure or disclosing private data.
Compared to alternatives like zkLLVM, which transform intermediate representations into constraints through complex pipelines, our approach starts directly from the instruction set. This results in a cleaner mapping to computation semantics and more efficient execution. In contrast to Cairo, our model supports mainstream languages and toolchains out of the box, avoiding the need to learn new domain-specific languages or retool development environments.
This strategy also strengthens the security and auditability of applications built on our zkVM. Since programs are authored in mature languages and compiled with established toolchains, they benefit from an ecosystem of debugging, analysis, and formal verification tools. Developers gain access to richer diagnostics, more robust testing capabilities, and a smoother transition from development to verifiable deployment.
Under the hood: The architecture of zkVM 3.0
zkVM 3.0 builds on the foundation established by earlier versions and features a redesigned architecture aimed at improving the performance and structural modularity of our proof system. One of our core architectural decisions was to adopt a two-pass execution model:
- In the first pass, the program is executed using a mostly traditional Harvard architecture. During this phase, we collect statistics on actual memory usage, which allows us to infer a concrete memory layout tailored to the specific input and execution path.
- In the second pass, the same program is executed again using this fixed memory layout, which enables trace generation with a fixed and predictable memory organization that is conducive to efficient proof construction. This second execution defines the behavior of the zkVM and produces the trace that is passed to our AIR system for constraint evaluation.
While the first pass is a usability optimization-helping reduce trace size and improve proving efficiency-it is not essential to correctness. It can be skipped in scenarios requiring fixed or privacy-preserving memory layouts.
Each component-CPU, register file, memory, execution logic-writes to a shared trace matrix. We partition the matrix into logical segments, ensuring that only relevant constraints are applied at each row. For example, ALU constraints are only active on rows corresponding to arithmetic instructions, while data memory constraints are only applied to load/store instructions.
An important change in zkVM 3.0 is our use of offline memory checking via logarithmic derivatives (LogUps). Rather than maintaining a full Merkle trie of memory contents, we maintain a digest of memory accesses and update it incrementally. Constraints ensure that the digest remains consistent and encodes valid read/write behavior. This saves significant space and enables stateless verification, especially useful in client-side or embedded contexts.
Our choice of STARKs stems from a strong belief in transparent, scalable, and post-quantum secure proof systems. To bring this vision to life, we needed a proving backend that could handle our architectural goals while supporting an efficient and ergonomic development workflow. S-two met these needs: its architecture aligned well with our new AIR system introduced in zkVM 3.0, and its tooling supported rapid development and flexible constraint authoring.
Writing AIRs for S-two felt natural. We appreciated the clear API boundaries and the flexibility to express constraints directly on trace values. The separation of trace construction and constraint evaluation allowed us to build clean, testable components, and we look forward to upstreaming many of our techniques and optimizations to the wider community. This compositionality will be critical as we continue evolving zkVM toward a more modular and distributed architecture.
Performance-wise, zkVM 3.0 delivers dramatic improvements over our previous implementations that were based on folding. Proofs are smaller, faster to generate, and more modular. We’ve observed promising performance characteristics in our early testing, though further benchmarking is needed to fully understand how prover performance scales with program complexity and size. As we modularize the trace and implement parallel proof generation, we expect additional performance gains, especially for applications involving larger programs or repeated subroutines.
What’s next for Nexus
Our long-term vision for zkVM includes a fully modular, composable architecture:
- Per-instruction AIRs: We want to isolate instructions like ADD, LOAD, and JUMP into individual trace segments that can be composed on demand.
- Distributed proving: Different parts of a large program can be proven on separate machines, enabling horizontal scalability.
- Pluggable components: Our modular design will enable integration of specialized features-such as custom precompiles or support for different guest programming languages-without breaking the zkVM’s core proving architecture.
This modular approach unlocks new use cases-from verifiable games to collaborative zk applications-where different participants may generate different subproofs. We see a future where our zkVM becomes a composable backend for zk rollups, identity protocols, confidential compute systems, and much more. We’re also building a complete developer toolkit:
- A Rust-based SDK to compile, run, and debug zkVM programs
- A visual trace debugger that shows register and memory state cycle by cycle
- CLI tools for trace inspection, proof generation, and verification
- WASM and mobile-native prover targets for local proving
As we move toward future iterations of our zkVM, we’ll focus on modular proof composition, selective trace loading, and tight integration with high-level languages and frameworks. We want zkVM to feel like just another backend-available wherever you write code, efficient enough to run locally, and powerful enough to scale globally. To try it out or follow our progress:
- š nexus.xyz
- š docs.nexus.xyz
- š§āš» github.com/nexus-xyz
We’re deeply grateful for the collaboration with the S-two team, and we’re excited to continue pushing the boundaries of what’s possible in general-purpose verifiable computing.