This repository contains a full-stack example for an in-browser ZK proof verifier.
The stack:
- R0VM for ZK proving.
- Next.JS for the browser app.
- wasm-pack for building the verifier library to browser compatible JS.
The project is organized into two main directories:
browser_verifier/
├── rust/ # Rust code for generating and verifying proofs
│ ├── guest/ # R0VM guest code that gets executed and proven
│ ├── host/ # R0VM host code for generating proofs
│ └── verifier/ # WebAssembly-compatible proof verification library
└── web/ # Next.js web application for in-browser proof verification
cd web
npm run devOpen http://localhost:3000 to view the application.
The web/ directory contains a Next.js application that demonstrates in-browser proof verification:
- Loads the WebAssembly verifier module from pkg (see Building the Verifier).
- Fetches the proof and image ID from binary files.
- Provides UI for proof verification.
- Displays verification result and time it took.
- Displays a time comparison between direct calculation and proof verification.
The web interface allows users to:
- Calculate the 1000000th Fibonacci number directly in the browser.
- Verify a pre-generated proof of the calculation in a fraction of the time.
- Compare the performance difference between direct calculation and proof verification.
The rust/ directory contains the zero-knowledge proof system components:
The guest code contains the program that runs inside the R0VM (RISC Zero Virtual Machine). This is the computation that gets proven. In this project, it calculates the 1000000th Fibonacci number and commits the length of that number to the journal.
The host code is responsible for:
- Loading and executing the guest program in the R0VM
- Generating proofs of correct execution
- Serializing the proof and the imageID into binary files that can be used by the verifier in the browser.
The host serializes these into 'receipt.bin' and 'image_id.bin' in the web application's public folder.
💡 Tip: If you want to modify the example to run proving yourself
This example's host/guest use R0VM v2.0.2; if you want to run proving yourself, before following the instructions below, make sure to switch to the correct branch:git checkout release-2.0
To run the host yourself:
cd rust/
cargo run --releaseThis will overwrite the proof files in the web app which could cause failure. The proof data files are included directly in the repo, so you shouldn't need to do this unless you're modifying things. The host is set up to save the necessary files straight to the correct web/public/proof_data folder. After you run the proving, you can go ahead and run the web app again with npm run dev and click 'Verify a Proof'.
The verifier is a Rust library that:
- Takes the proof and image ID as input
- Verifies that the guest program was executed correctly
- Is compiled to WebAssembly for in-browser verification
- Exposes the
verify_prooffunction to JavaScript
The verifier library contains one function: verify_proof.
verify_proof:
- takes two
u8arrays as input;proof_bytesandimage_id_bytes. - using
risc0_zkvm::Receipt, the Receipt struct is built fromproof_bytes. - using
risc0_zkvm::sha::Digest, the image_id digest is built fromimage_id_bytes. - the receipt is verified using receipt.verify.
- the output is logged to the console using web_sys.
To compile the verifier library to WebAssembly:
cd rust/verifier
wasm-pack build --release --target web --out-dir ../../web/public/wasm/pkgThe output is in the wasm/pkg/ directory in the public folder for the web app.