The Problem with General-Purpose zkVMs
Zero-knowledge virtual machines face a fundamental tension: traditional instruction set architectures were designed to maximize throughput on physical hardware, not to minimize the cost of cryptographic proving. This mismatch results in unnecessarily complex constraint systems and slower proof generation.
ZKIR takes a different approach. Rather than adapting an existing ISA, we designed one from first principles specifically for STARK-based proving systems.
Research Publication: The theoretical foundations and formal analysis of ZKIR are detailed in our peer-reviewed paper: ZKIR: A Novel ISA for Efficient Zero-Knowledge Computation
Core Design Principles
Principle 1: Constraint Minimization
Every instruction in ZKIR is designed to minimize the number of algebraic constraints required in the STARK proof. We achieve this through:
Uniform Instruction Encoding
All ZKIR instructions use an identical 32-bit format:
[opcode:6][rd:5][rs1:5][rs2:5][imm:11]
This uniformity eliminates the need for instruction decoding logic in the constraint system, saving approximately 20 constraints per instruction compared to variable-length encodings.
Constraint Counts by Instruction Class
| Instruction Type | ZKIR Constraints | RISC-V Constraints |
|---|---|---|
| ALU (add, sub, xor) | 5-6 | 12-15 |
| Memory Load | 8-10 | 18-22 |
| Memory Store | 7-9 | 16-20 |
| Branch | 12-14 | 25-30 |
Principle 2: Field-Native Arithmetic
ZKIR operates natively over the Baby Bear prime field (p = 2³¹ - 2²⁷ + 1), eliminating overflow handling and enabling efficient modular arithmetic:
Field characteristics:
- Prime: p = 2013265921
- 32-bit native representation
- Efficient Montgomery multiplication
- Two's complement compatible for signed operations
This design choice aligns perfectly with Plonky3's field requirements, minimizing conversion overhead.
Principle 3: Deterministic Execution
ZKIR eliminates all sources of non-determinism found in traditional architectures:
- No interrupts or exceptions during proving
- Deterministic memory allocation
- Fixed instruction timing (no caches or speculation)
- Bounded loop iterations
Register Architecture
ZKIR provides 32 general-purpose registers with a calling convention optimized for common cryptographic patterns:
r0 : Zero register (hardwired to 0)
r1-r8 : Argument/return registers
r9-r16 : Caller-saved temporaries
r17-r24 : Callee-saved registers
r25-r28 : Reserved for runtime
r29 (fp) : Frame pointer
r30 (lr) : Link register
r31 (sp) : Stack pointer
The Compilation Pipeline
ZKIR integrates with standard toolchains through our LLVM backend:
┌─────────────────┐
│ Source Code │ Rust, C, C++, Go
│ (High-level) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ LLVM IR │ Platform-independent
│ │ intermediate representation
└────────┬────────┘
│
▼
┌─────────────────┐
│ zkir-llvm │ Our custom LLVM backend
│ │
└────────┬────────┘
│
▼
┌─────────────────┐
│ ZKIR Bytecode │ Optimized for proving
│ │
└────────┬────────┘
│
▼
┌─────────────────┐
│ zkir-prover │ Plonky3-based proof generation
│ │
└────────┬────────┘
│
▼
┌─────────────────┐
│ STARK Proof │ Succinct, verifiable proof
└─────────────────┘
Performance Benchmarks
We benchmarked ZKIR against leading zkVM implementations on standard cryptographic workloads:
| Benchmark | ZKIR | SP1 | RISC Zero |
|---|---|---|---|
| SHA-256 (1KB) | 1.0x | 1.3x | 1.6x |
| Keccak-256 (1KB) | 1.0x | 1.4x | 1.7x |
| ECDSA Verify | 1.0x | 1.2x | 1.4x |
| Merkle Proof (depth 20) | 1.0x | 1.5x | 1.8x |
Lower is better. ZKIR normalized to 1.0x.
Proof Size Comparison
| System | Proof Size | Verification Time |
|---|---|---|
| ZKIR | ~100 KB | 12ms |
| SP1 | ~150 KB | 18ms |
| RISC Zero | ~200 KB | 25ms |
Implementation Details
Memory Model
ZKIR uses a word-addressed memory model with separate instruction and data regions:
- Instruction Memory: Read-only, loaded at initialization
- Data Memory: Read-write, initialized to zero
- Stack: Grows downward from high addresses
- Heap: Grows upward from low addresses
Cryptographic Precompiles
For performance-critical operations, ZKIR provides native precompiled functions:
// Native hash computation (single constraint)
let hash = zkir::precompile::sha256(data);
// Native field arithmetic
let result = zkir::precompile::field_mul(a, b);
Getting Started
Explore ZKIR through our open-source repositories:
- zkir - ISA specification, VM implementation, and documentation
- zkir-llvm - LLVM backend for compiling high-level languages
- zkir-prover - Plonky3-based proving system
For the complete theoretical analysis and security proofs, refer to our research publication.