Library / SDK
risc0/risc0 avatar
risc0/risc0

RISC Zero: proving that RISC-V code ran correctly without revealing its inputs

RISC Zero is a zero-knowledge verifiable general computing platform based on zk-STARKs and the RISC-V microarchitecture.

2,202 stars738 forksC++Apache-2.0

At a glance

What is it?
RISC Zero wraps a small RISC-V machine in a zero-knowledge virtual machine so a prover can show that a program ran correctly and publish only its output. Here is how the receipt, the image ID and the journal fit together.
Who is it for?
RISC Zero fits a narrow and genuinely useful case: you need an outsider to check a computation whose inputs you cannot disclose, and you can afford the cost of proving it. It does not fit ordinary application code, because the whole value is in the receipt and a receipt nobody needs is pure overhead.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 45 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What a receipt proves and what it hides

The README sets out the claim precisely. A zero knowledge proof lets a prover convince a verifier that something is true without revealing the details. In RISC Zero's case the something is that a piece of code executed correctly, and what stays hidden is every input and all intermediate state. The verifier sees the output and nothing else.

That output comes from a specific place. Guest code can write to an append-only log called the journal, which the README calls the official output of the computation. Once the guest terminates correctly, a receipt is produced, and the receipt has exactly two parts: the journal and a blob of opaque cryptographic data called the seal. Verification checks both. Tamper with either and verification fails.

The privacy property is worth stating separately from the correctness property, because they are different claims and the README makes both. Correctness means it is cryptographically infeasible to produce a valid receipt unless the journal is exactly the correct output of some valid execution of the method whose image ID matches. Zero knowledge means the verifier cannot infer anything about execution details or host and guest data beyond what the journal implies.

One design constraint is easy to miss and shapes everything else. The host runs the zkVM and proves the method, but it cannot modify the execution of the guest in any way, or the proof becomes invalid. So the guest is not a function the host can call with arguments and inspect. Anything the computation depends on has to travel across the host and guest boundary, and anything the outside world needs has to come back out through the journal.

Image IDs bind a proof to a specific binary

Before any of that runs, code has to be compiled from its implementation language into what the README calls a method. A method is a RISC-V ELF file with a special entry point that runs the method's code. From that ELF you compute an image ID, described as a special type of cryptographic hash of the file, and the README states that it is required for verification.

That is the binding between a proof and the program that produced it. A receipt verifies against an image ID, so a verifier does not merely check that some valid execution happened, they check that a specific compiled artifact ran. This is the property you want when the prover is not trusted: recompiling the program with different behaviour produces a different image ID, and the old receipt no longer applies to the new binary.

It also means image ID management is a real operational task in your own project. Every time you recompile, the ID moves, and anything that pins an ID, a test fixture, a deployment manifest or an on-chain commitment, has to be updated in step. The README does not document a workflow for that, so it is worth looking for one on dev.risczero.com before you build a pipeline around it.

The language story is short. The zkVM emulates a small RISC-V computer, which means anything you can compile to RISC-V can in principle run, and the README says SDK support currently exists for Rust, C and C++.

Installing the toolchain through rzup

The setup path is a chain of small steps, and the README is explicit about each one. You need Rust installed first, then you install `rzup`, the RISC Zero toolchain installer, which in turn installs `cargo-risczero`. The installer itself is a single piped command:

bash
curl -L https://risczero.com/install | bash

After that, `rzup install` puts the toolchain in place:

bash
rzup install

The README then suggests confirming the installation worked before doing anything else, which is worth following because a toolchain that is half installed produces errors much later:

bash
cargo risczero --version

With that confirmed, `cargo risczero new` writes the initial boilerplate and the standard directory structure:

bash
cargo risczero new my_project

Further options for the tool live in the `cargo risczero` README rather than the top level one. One detail worth planning around is that `curl | bash` pulls from a URL rather than from the repository you are reading, so the installer script is not versioned alongside the code. The tree has an `rzup/` directory, so the installer source is in the repository too, and pinning to a tagged release rather than tracking the tip is the more predictable option.

A workspace on version 5.0.0 with a 3.0.6 release

The version numbers in this repository do not line up, and rather than pick one, it is worth laying them out. The workspace manifest declares `version = "5.0.0"` in its `[workspace.package]` section, and many member crates follow it, with entries like `risc0-binfmt = { version = "5.0.0" }`. The published releases, though, are v3.0.6 from 2026-07-17, v3.0.5 from 2026-02-03, and v5.0.0-rc.1 from 2026-01-15.

Both facts are in the repository. The newest tag with a final version number is 3.0.6, and the 5.0.0 line exists as a release candidate published before the 3.0.x patches, which means the release history interleaves two version lines rather than moving strictly forward. The most likely explanation is that 5.0 is in preparation on `main` while 3.0.x receives fixes, and the manifest on the development branch has already been moved to the future number. What the repository does not offer is a note saying so.

The README does address the general hazard, in an important callout at the very top: `main` is the development branch, and when building applications or running examples you should use the latest release instead. That instruction is the practical resolution of the mismatch. If you pin to a tag you get 3.0.6 and the manifest inside it agrees with the tag; if you work from `main` you are building an unreleased 5.0.0 line. The check to run before you start is therefore simple: look at what version your checkout's `Cargo.toml` declares and compare it against the tag you intended to use.

The last push was on 2026-08-28 and the repository is not archived.

Three layers of recursion behind the security number

The security section is short but points at real structure. The README describes a three-layer recursive proof system based on the zk-STARK protocol and the Groth16 protocol. With default parameters, it claims perfect zero-knowledgeness and 98 bits of conjectured security.

Two things in that sentence deserve attention. The security figure is explicitly conjectured, which is normal for parameters derived from assumptions rather than proven bounds, and the word default matters because parameters are configurable. The deeper point is that recursion is what makes the system usable at all. A single STARK proving a whole program would grow to an unusable size, so the computation is broken into layers and each layer's proof becomes an input to the next, producing a fixed size proof for an arbitrarily long execution. The `bonsai/` directory and the `groth16_proof/` directory in the tree are the visible artefacts of that machinery, and the workspace members include dedicated crates for the recursion circuits, for Keccak, and for the `rv32im` instruction set.

The README also tells you how to inspect the assumptions yourself. There is a soundness and security calculator in the `soundness.rs` file, and to run it you set a debug log level:

bash
RUST_LOG=risc0_zkp=debug

The details of the STARK protocol are in a linked paper on Scalable, Transparent Arguments of RISC-V Integrity, and an overview of the cryptographic assumptions is on a separate security model page. That page, not the README, is where the assumptions are actually written down, and it is the document to read before the 98 bit figure means anything to you.

Where the README ends and the documentation site begins

The README is oriented at two audiences and serves the first one well. For someone evaluating the idea, it gives the protocol in four paragraphs, which is one of the clearer explanations of a zkVM's structure in the ecosystem. For someone trying to build, it gives you an install chain and points at the rest.

Everything else is elsewhere. SDK documentation for the zkVM crate is on docs.rs as risc0-zkvm, everything else is on dev.risczero.com, and the site source is in the `website/` directory of this repository if you want to check what a page claims. There is a Getting Started page for project structure guidance and a CONTRIBUTING file that the README sends you to twice, once for building from source and once for dependencies. Since building from source needs additional tools beyond the `rzup` path, expect to read that file before you attempt it.

The repository itself carries more signals than the README uses. The workspace manifest sets `edition = "2024"` and `resolver = "2"`, so this is a current Rust codebase, and the topics list cryptography, risc-v, rust, stark, virtual-machine and zero-knowledge, which matches a system that is mostly Rust with C++ components, since GitHub reports C++ as the primary language. `vendor/sppark` in the workspace means some dependencies are vendored in-tree, and there is a `license-check.py` script alongside `semver-baselines.lock`, a `_typos.toml` configuration and a `rust-toolchain.toml`, which together suggest the API surface is baselined for semver and dependencies are checked automatically.

On licensing, the records differ slightly and all three are visible. GitHub's license field reads Apache-2.0. The README badge describes the project as dual licensed under Apache-2.0 or MIT, the workspace manifest says `license = "Apache-2.0 OR MIT"`, and the tree carries both `LICENSE-APACHE` and `LICENSE-MIT`. Either way the permissive options are available and the choice between them is yours to make.

Editorial conclusion

RISC Zero fits a narrow and genuinely useful case: you need an outsider to check a computation whose inputs you cannot disclose, and you can afford the cost of proving it. It does not fit ordinary application code, because the whole value is in the receipt and a receipt nobody needs is pure overhead. The first thing to check in your own design is who the verifier is and what they are allowed to learn, because if the answer is that they may see everything then you want a normal test suite instead. Start from a tagged release rather than `main`, since the workspace manifest on the development branch already declares a version ahead of the newest published tag, and read the security model page on dev.risczero.com before you rely on the 98 bit figure, because that number is described as conjectured and depends on parameters the README does not enumerate.

Frequently asked questions

What does RISC Zero actually prove?

It proves that a specific program executed correctly, while revealing only the output the program wrote to the journal. Inputs and all intermediate state stay hidden, and the verifier learns nothing beyond what the journal implies.

What is an image ID in RISC Zero?

It is a cryptographic hash of the RISC-V ELF file that represents a compiled method, and it is required for verification. Because the ID binds the proof to one compiled binary, recompiling the program changes the ID and invalidates receipts that referenced the old one.

How do I install the RISC Zero toolchain?

Install Rust first, then run `curl -L https://risczero.com/install | bash` to install rzup, and run `rzup install` to put the toolchain in place. You can confirm with `cargo risczero --version` and scaffold a project with `cargo risczero new my_project`.

Can I write a RISC Zero guest program in languages other than Rust?

In principle any language with a compiler toolchain that targets RISC-V can run in the zkVM, since it emulates a small RISC-V computer. SDK support currently exists for Rust, C and C++, which is the documented set rather than the theoretical limit.

Should I build RISC Zero from the main branch?

The README says `main` is the development branch and to use the latest release when building applications or running examples. The workspace manifest on `main` declares version 5.0.0 while the newest published tag is v3.0.6, so building from the branch means building an unreleased line.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. risc0/risc0 on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/risc0-risc0.svg)](https://hysenlabs.com/projects/risc0-risc0)