A fully working STARK-based zkVM in Rust. No trusted setup. Pure hash-based cryptography. Runs on stable Rust.
# Build
cargo build --release
# Run fibonacci(10) — prove and verify
cargo run --release -- run fibonacci 10
# Run 5!
cargo run --release -- run factorial 5
# Run sum(1..50)
cargo run --release -- run sum 50
# Run all built-in examples
cargo run --release -- run-all
# Benchmark
cargo run --release -- bench
# Show system parameters
cargo run --release -- info
# Run ALL tests (51 unit tests)
cargo testProgram : fibonacci(10)
[ 1/4 ] Executing VM ... done in 30.42us
Steps : 66
Trace rows : 128 (padded to power of 2)
r0 (result) : 55
Expected : 55
[ 2/4 ] Checking constraints ... ALL SATISFIED
[ 3/4 ] Generating STARK proof ... done in 11.29ms
FRI layers : 6
FRI queries : 30
Trace cols : 11
OOD evals : 22
Proof size : ~71 KB (rough estimate)
[ 4/4 ] Verifying proof ... VALID (1.49ms)
Proof generation: 11.29ms
Proof verification: 1.50ms
Total: 13.06ms
Program : 5!
[ 1/4 ] Executing VM ... done in 15.50us
Steps : 25
Trace rows : 32 (padded to power of 2)
r0 (result) : 120
Expected : 120
[ 2/4 ] Checking constraints ... ALL SATISFIED
[ 3/4 ] Generating STARK proof ... done in 3.91ms
FRI layers : 4
FRI queries : 30
Trace cols : 11
OOD evals : 22
Proof size : ~69 KB (rough estimate)
[ 4/4 ] Verifying proof ... VALID (2.02ms)
Proof generation: 3.91ms
Proof verification: 2.02ms
Total: 6.04ms
All benchmarks run on release builds (cargo run --release -- bench).
| Program | Trace Length | Prove | Verify | Ratio |
|---|---|---|---|---|
| fibonacci(5) | 64 | 4,432 us | 1,384 us | 3.2x |
| fibonacci(10) | 128 | 18,396 us | 2,694 us | 6.8x |
| fibonacci(15) | 128 | 15,785 us | 2,418 us | 6.5x |
| factorial(5) | 32 | 3,231 us | 1,293 us | 2.5x |
| factorial(7) | 64 | 6,135 us | 1,618 us | 3.8x |
| sum(20) | 128 | 11,194 us | 1,615 us | 6.9x |
| sum(50) | 256 | 20,885 us | 1,870 us | 11.2x |
Verification is consistently 3-11x faster than proving. Proof generation scales roughly linearly with trace length.
All 10 built-in programs prove and verify successfully:
fibonacci(0) PASS
fibonacci(1) PASS
fibonacci(10) PASS
fibonacci(15) PASS
factorial(1) PASS
factorial(5) PASS
factorial(7) PASS
sum(10) PASS
sum(50) PASS
memory roundtrip PASS
Results: 10 passed, 0 failed
51 unit tests covering every module. All passing.
cargo test
running 51 tests
test channel::tests::test_absorb_resets_squeeze ... ok
test channel::tests::test_absorb_changes_output ... ok
test channel::tests::test_deterministic ... ok
test channel::tests::test_different_input_different_output ... ok
test channel::tests::test_sequential_squeezings_differ ... ok
test constraints::tests::test_boundary_initial_state ... ok
test constraints::tests::test_factorial_constraints ... ok
test constraints::tests::test_fibonacci_constraints ... ok
test constraints::tests::test_sum_constraints ... ok
test field::tests::test_add_wrap ... ok
test field::tests::test_field_laws ... ok
test field::tests::test_half ... ok
test field::tests::test_inv ... ok
test field::tests::test_mul_2_32 ... ok
test field::tests::test_mul_basic ... ok
test field::tests::test_pow ... ok
test field::tests::test_reduce_known ... ok
test field::tests::test_root_of_unity ... ok
test field::tests::test_root_of_unity_order ... ok
test field::tests::test_sub_wrap ... ok
test fri::tests::test_fold_correctness ... ok
test fri::tests::test_fold_domain_consistency ... ok
test fri::tests::test_fri_commit_verify_low_degree ... ok
test fri::tests::test_fri_multiple_polys ... ok
test merkle::tests::test_large_tree ... ok
test merkle::tests::test_open_and_verify_all_leaves ... ok
test merkle::tests::test_root_changes_with_leaf ... ok
test merkle::tests::test_root_deterministic ... ok
test merkle::tests::test_wrong_leaf_fails ... ok
test poly::tests::test_divide_by_vanishing ... ok
test poly::tests::test_domain_powers ... ok
test poly::tests::test_eval_poly ... ok
test poly::tests::test_interpolate_eval_consistency ... ok
test poly::tests::test_lde_consistent_with_poly ... ok
test poly::tests::test_mul_poly ... ok
test poly::tests::test_ntt_intt_roundtrip ... ok
test poly::tests::test_ntt_known_values ... ok
test prover::tests::test_prover_runs_without_panic ... ok
test trace::tests::test_column_extraction ... ok
test trace::tests::test_trace_length_power_of_two ... ok
test trace::tests::test_trace_selector_column ... ok
test verifier::tests::test_verify_factorial_5 ... ok
test verifier::tests::test_verify_fibonacci_5 ... ok
test verifier::tests::test_verify_fibonacci_10 ... ok
test verifier::tests::test_verify_sum_10 ... ok
test vm::tests::test_factorial ... ok
test vm::tests::test_fibonacci ... ok
test vm::tests::test_jnz ... ok
test vm::tests::test_mem_roundtrip ... ok
test vm::tests::test_sum ... ok
test result: ok. 51 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Program (assembly)
|
v
+-------------------------------------------------------+
| VM Execution (vm.rs) |
| 8 registers x Felt, 11 opcodes, linear memory |
| Records every state transition |
+------------------------+------------------------------+
| Execution Trace (trace.rs)
v
+----------------------------------+
| Trace Matrix T[row][col] | n x 11
| Padded to next power of 2 |
+--------------+-------------------+
| NTT interpolation (poly.rs)
v
+----------------------------------+
| Trace polynomials T_j(x) | deg n-1
+--------------+-------------------+
| LDE x4 (poly.rs)
v
+----------------------------------+
| LDE evaluations + Merkle trees | (merkle.rs)
| Committed via Blake3 |
+--------------+-------------------+
| AIR (constraints.rs)
v
+----------------------------------+
| Constraint polynomial C(x) |
| Quotient Q(x) = C(x)/Z(x) |
+--------------+-------------------+
| DEEP-ALI (prover.rs)
v
+----------------------------------+
| Composition polynomial |
| FRI low-degree proof (fri.rs) |
+--------------+-------------------+
|
v
StarkProof
|
v
+----------------------------------+
| Verifier (verifier.rs) |
| Replays transcript |
| Checks Merkle + FRI |
+----------------------------------+
zkvm/
├── Cargo.toml
├── src/
│ ├── lib.rs re-exports all modules
│ ├── main.rs CLI (cargo run -- run fibonacci 10)
│ ├── field.rs Goldilocks field (p = 2^64 - 2^32 + 1)
│ ├── vm.rs ISA + execution engine
│ ├── trace.rs Execution trace recording + padding
│ ├── constraints.rs AIR constraint system
│ ├── poly.rs NTT, iNTT, LDE, polynomial evaluation
│ ├── merkle.rs Binary Merkle tree + proof
│ ├── channel.rs Fiat-Shamir transcript (Blake3)
│ ├── fri.rs FRI commit + verify
│ ├── prover.rs Full STARK prover
│ └── verifier.rs Full STARK verifier
└── examples/
├── fibonacci.zkasm
├── factorial.zkasm
└── sum.zkasm
| Opcode | Semantics |
|---|---|
CONST rd, imm |
rd = imm |
ADD rd, rs1, rs2 |
rd = rs1 + rs2 |
SUB rd, rs1, rs2 |
rd = rs1 - rs2 |
MUL rd, rs1, rs2 |
rd = rs1 * rs2 |
JMP addr |
pc = addr |
JZ rs, addr |
if rs == 0: pc = addr |
JNZ rs, addr |
if rs != 0: pc = addr |
COPY rd, rs |
rd = rs |
LOAD rd, addr |
rd = mem[addr] |
STORE rs, addr |
mem[addr] = rs |
HALT |
stop |
All values live in F_p (Goldilocks field, p = 2^64 - 2^32 + 1).
| Parameter | Value | Notes |
|---|---|---|
| Field | Goldilocks | p = 2^64 - 2^32 + 1 |
| Hash | Blake3 | 256-bit, no trusted setup |
| LDE blowup | 4x | fri.rs: BLOWUP_FACTOR |
| FRI queries | 30 | fri.rs: NUM_QUERIES |
| Trace width | 11 | 8 regs + pc + sel + opcode |
| Post-quantum | Yes | hash-based only, no elliptic curves |
| Trusted setup | None | transparent |
| Security | ~30 bits | increase NUM_QUERIES for production |
cargo test # all 51 tests
cargo test test_field # only field arithmetic tests
cargo test test_fri # only FRI tests
cargo test test_verify # only verifier tests
cargo test -- --nocapture # show println outputuse zkvm_lib::{
vm::Instruction,
field::Felt,
trace::generate_trace,
constraints::ConstraintSystem,
prover::prove,
verifier::verify,
};
fn main() {
// Program: compute 3 * 4 = 12
let program = vec![
Instruction::Const(0, Felt::new(3)),
Instruction::Const(1, Felt::new(4)),
Instruction::Mul(2, 0, 1),
Instruction::Halt,
];
// Execute and record trace
let (vm, trace) = generate_trace(&program, 16);
println!("Result: r2 = {}", vm.regs[2].0); // 12
// Prove
let cs = ConstraintSystem::new(program, vec![vm.regs[2]]);
let proof = prove(&trace, &cs, vec![vm.regs[2]]);
// Verify
match verify(&proof) {
Ok(()) => println!("Proof VALID"),
Err(msg) => println!("Proof INVALID: {msg}"),
}
}- No trusted setup -- all randomness derived from Blake3 (Fiat-Shamir)
- Post-quantum -- only hash functions, no elliptic curves
- FRI soundness -- cheating prover is caught with probability >= 1 - (1/|F|)^30 per query
- Completeness -- honest prover always convinces verifier
- Anatomy of a STARK -- best tutorial
- STARK paper (Ben-Sasson et al.)
- FRI paper
- Winterfell -- production STARK in Rust
- RISC Zero -- zkVM for full RISC-V
MIT