/risc0

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

Primary LanguageC++Apache License 2.0Apache-2.0

Crates.io MIT licensed Build Status Discord chat Twitter

WARNING: This software is still experimental, we do not recommend it for production use (see Security section).

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

A zero knowledge proof allows one party (the prover) to convince another party (the verifier) that something is true without revealing all the details. In the case of RISC Zero, the prover can show they correctly executed some code (known to both parties), while only revealing to the verifier the output of the code, not any of its inputs or any state during execution.

The code runs in a special virtual machine, called a zkVM. The RISC Zero zkVM emulates a small RISC-V computer, allowing it to run arbitrary code in any language, so long as a compiler toolchain exists that targets RISC-V. Currently, SDK support exists for Rust, C, and C++.

Protocol overview and terminology

First, the code to be proven must be compiled from its implementation language into a method. A method is represented by a RISC-V ELF file with a special entry point that runs the code of the method. Additionally, one can compute for a given method its image ID which is a special type of cryptographic hash of the ELF file, and is required for verification.

Next, the prover runs the method inside the zkVM. The logical RISC-V machine running inside the zkVM is called the guest and the prover running the zkVM is called the host. The guest and the host can communicate with each other during the execution of the method, but the host cannot modify the execution of the guest in any way, or the proof being generated will be invalid. During execution, the guest code can write to a special append-only log called the journal that represents the official output of the computation.

Presuming the method terminated correctly, a receipt is produced, which provides the proof of correct execution. This receipt consists of 2 parts: the journal written during execution and a blob of opaque cryptographic data called the seal.

The verifier can then verify the receipt and examine the log. If any tampering was done to the journal or the seal, the receipt will fail to verify. Additionally, it is cryptographically infeasible to generate a valid receipt unless the output of the journal is the exactly correct output for some valid execution of the method whose image ID matches the receipt. In summary, the receipt acts as a zero knowledge proof of correct execution.

Because the protocol is zero knowledge, the verifier cannot infer anything about the details of the execution or any data passed between the host and the guest (aside from what is implied by the data written to the journal and the correct execution of the code).

Security

This code is based on the well studied zk-STARK protocol, which has been proven secure under the random oracle model, with the only assumption being the security of the cryptographic hash used. Our implementation uses SHA-256 for that hash and targets 100 bits of security.

That said, this code is still under heavy development and has not been audited. There may be bugs in the zk-STARK implementation, the arithmetic circuit used to instantiate the RISC-V zkVM, or any other element of the code's implementation. Such bugs may impact the security of receipts, leak information, or cause any other manner of problems. Caveat emptor.

Getting Started

To get started building applications using the zkVM in Rust, we provide a starter template and a number of working examples.

Example

Add a methods crate, which will act as a container for code that runs within the zkVM. This crate will be configured with a special build-script to enable cross-compilation of RISC-V code. The resulting ELF binary will be embedded within this crate so that it can be referenced as a dependency in your application.

cargo new --lib methods

Adjust methods/Cargo.toml to include:

[build-dependencies]
risc0-build = "0.13"

[package.metadata.risc0]
methods = ["guest"]

Adjust methods/src/lib.rs so that its contents are:

include!(concat!(env!("OUT_DIR"), "/methods.rs"));

Add a methods/build.rs build script with these contents:

fn main() {
  risc0_build::embed_methods();
}

Within the methods crate, create a guest crate. Rename the main.rs to something more appropriate.

cargo new --bin methods/guest
mv methods/guest/main.rs methods/guest/example.rs

Add risc0-zkvm to the methods/guest/Cargo.toml file:

[dependencies]
risc0-zkvm = { version = "0.13", default-features = false }

Edit the code in methods/guest/src/example.rs:

#![no_main]
#![no_std]

risc0_zkvm::guest::entry!(main);

pub fn main() {
    // TODO: Implement your guest code here
}

Add risc0-zkvm and the methods crate to your dependencies:

[dependencies]
methods = { path = "methods" }
risc0-zkvm = "0.13"

Call the prover from your application:

use methods::{EXAMPLE_ELF, EXAMPLE_ID};
use risc0_zkvm::Prover;

fn main() {
  let mut prover = Prover::new(EXAMPLE_ELF, EXAMPLE_ID).unwrap();
  let receipt = prover.run().unwrap();

  // The receipt can be sent to another party, where they can:

  receipt.verify(EXAMPLE_ID).unwrap();
}

Rust Binaries

crate crates.io
risc0-r0vm x
risc0-tools x

Rust Libraries

crate crates.io docs.rs
risc0-build x
risc0-build-kernel x
risc0-circuit-rv32im x
risc0-core x
risc0-sys x
risc0-zeroio x
risc0-zeroio-derive x
risc0-zkp x
risc0-zkvm x
risc0-zkvm-platform x

License

This project is licensed under the Apache2 license. See LICENSE.