RiscZero
RiscZero is a Zero-Knowledge Proof system designed to enable efficient and scalable construction of computational proofs based on the RISC-V architecture. It is Groth16-based and works over the BN254 elliptic curve.
Garaga provides the tools and makes it possible to verify such proofs on-chain in a Starknet/Cairo smart contract.
A Zero-Knowledge proof is a mathematical construct that guarantees that a given value is the output of a predefined computation where some of the inputs are private and must not be disclosed.
This is achieved in two steps:
1- A Prover performs the computation and constructs the proof artifact. The proof artifact contains the computational journal which is, in simple terms, the list of public inputs and the output value. The proof artifact attests the integrity of the computation, which means the prover ran the computation properly and the output value registered in the journal corresponds to the result of such computation given the public inputs, also registered in the jornal, an some undisclosed private inputs. Here the Prover is a RiscZero user-defined program that implements the desired computation and is augmented to produce the desired proof artifact.
2- Given the proof artifact, a Verifier must check its integrity before processing the output as valid. Here the Verifier is a Starknet smart contract written in Cairo and Garaga acts as a library to which the verification is delegated to.
Setting up the development environment
Before starting development we need to install all the software prerequisites for building either or both the Prover and Verifier components.
Below we provide general installation instructions for a Linux-based system. Depending on your setup you may already have some of the software installed, in which case you can skip the associated sections. But if you need additional help for a specific set up, please follow the links provided. In order to implement the Prover one needs to install the tooling required by RiscZero:
Install Rust/Cargo using
rustup
(default version 1.8.3)
Install the RiscZero tool-chain using
rzup
(default version 1.2.0)
Important: Make sure the RiscZero version installed matches the version supported by Garaga. For RiscZero 1.2.0 use Garaga 0.15.3. For RiscZero 1.1.3 use Garaga 0.14.0.
Install RiscZero additional/custom dependencies
A C compiler, such as gcc
, pkg-config
and OpenSSL development libraries (libssl-dev)
are necessary to build a RiscZero project. You should refer to your system documentation on how to install those. Here is a quick reference for Debian compatible systems
Optionally, if you intend to have the Prover generate the contract call data explicitly, Garaga requires that Python is available in your environment. If necessary, check their documentation for installation instructions for your system. Again, here is a quick reference for Debian compatible systems
In order to implement the Verifier one needs to install the tooling for Cairo development and Garaga:
Install the Starknet/Cairo bundler tool
scarb
(default version 2.9.1)
Install Starknet Foundry using
snfoundryup
(default version 1.35.1)
Create or configure the RiscZero project
If you are setting up a new RiscZero project, run the command below, it will create a new project folder and define the Guest program name. The Guest program is the program that is compiled to and will run in the RiscZero VM. The project setup also creates a Host program that runs outside the RiscZero VM and interacts with the Guest, providing inputs and collecting outputs, to produce the ZK proof. Here we set up a sample project called
fibonacci_prover
with a Guest calledfibonacci_guest
(for reference, the complete RiscZero app presented here is available in Garaga's GitHub repository)
If you already have a RiscZero project set up, make sure the RiscZero version configured as dependencies is consistent with the RiscZero toolchain installed in the previous steps.
Next we need to modify the RiscZero Host program to output the proof artifact in the desired JSON format. Add the following dependencies to
host/Cargo.toml
Optionally, if you intend to explicitly generate and handle the call-data, also add the following dependency to host/Cargo.toml
. Make sure to use a Garaga version tag that is consistent with your setup.
Then we modify the Host program host/src/main.rs
to generate the JSON file containing the proof artifact. We start by adding the required imports
Optionally, if you intend to generate the call-data explicitly, add the following imports
Next we need to modify the Host main function.
If you are starting a fresh RiscZero project, you will need to setup the environment for the computation. This is basically the set of inputs that will be used by the Guest program to perform the computation.
Below is an example for the fibonacci_prover
. In this example, we want to compute the number at position n
of the Fibonacci sequence. However we do not want to reveal n
, but instead show that n
lies in a given interval defined by a lower bound l
and an upper bound u
.
As a note, the sample app provided here exists only to demonstrate how to setup a ZK project using Garaga/RiscZero. It is clear that datatype u32
is not appropriate datatype to host a secret Fibonacci number as it can be easily discovered by brute force checking all possibilities between the bounds.
Next we modify the default Prover setup to explicitly use Groth16
Finally, as the last step of the Host program, we extract and print the proof artifact JSON to the standard output
Optionally, if you also intend to handle the call-data explicitly, it can be computed and output as a JSON as well. This produces a large array that encodes the full RiscZero proof wih hints
Now we need to set up the Guest program that performs the computation required by our use case.
If you started a fresh RiscZero project, then you will need to write the Guest program that performs the computation. It is done by modifying the main function of the Guest source file at methods/guest/src/main.rs
In our example, here is what the Guest code looks like for the fibonacci_guest
RiscZero Proof Generation
RiscZero provides some options when it comes to proof generation. Please refer to their documentation in case you need to in depth information on that. The easiest and most convenient way is to use the provided Bonsai service, which works fine for many purposes. In that case, an API key for the service is required.
It is important to note that, if your computation has private inputs, you should definitely protect them from being exposed to external services like Bonsai by performing the proof generation locally.
Here is the command to run the Prover via Bonsai
Developing the RiscZero Verifier smart contract
There are different ways one can choose to develop a Cairo smart contract, we recommend using Staknet Foundry. A fresh new project can be created by issuing the following command
This will output a template for a smart contract along with the necessary tooling configuration to build and test it. In this case we are creating a contract called fibonacci_sequencer
, that will process and update its state with a new number in the Fibonacci sequence that is guaranteed to have an index n
in the sequence that is higher than the last one currently registered by the contract, although that exact index n
is never revealed publicly.
Garaga already provides a smart contract to verify RiscZero proofs. To make use of that functionality, one just has to call a predefined library function from the client smart contract. In order to do that, one needs to declare the interface of the RiscZero verifying library function in src/lib.cairo
:
The verify_groth16_proof_bn254
function takes the call data that encodes the proof with hints as a list of integers of type felt252
and returns the journal (as a list of bytes) on proof verification success, or nothing if the verification fails.
Here is how to verify the RiscZero proof and update the smart contract state for our Fibonacci sequencer example:
Along with the verify_and_submit_fibonacci_number
contract method, we need to define the RiscZero Verifier class hash, which can be obtained here
The contract state which stores the current lower bound which gets updated whenever a new Fibonacci number is submitted
And also the helper function used to decode the journal values
For completeness, we also provide the definition of the events emitted by the operation
It is important to note that the verify_and_submit_fibonacci_number
function defined in this sample contract has a signature that takes a single argument: the proof artifact. This is useful because we can then submit the transaction to the blockchain directly, simply using the Garaga CLI passing along the JSON file output by the RiscZero Host program. This avoids the need to encode the proof as a customized call data. It also spares us from dealing with the transaction submission details which is handled internally by the Garaga CLI.
This is an approach that makes sense when all the information required to validate and update the smart contract state can be extracted from the journal, exempting us from the need of passing additional parameters to the function which would deem it incompatible with the interface expected by the CLI. The CLI also requires the contract method processing the proof (referred to as endpoint) to have the word verify
as part of it.
Once the Cairo smart contract is ready, it can be deployed in three steps:
Declare
This will declare the smart contract class and return its hash.
Deploy
This will deploy the smart contract instance and return its address.
Verify (Optional)
This will match the deployed code with the smart contract source code and make it available on Starknet block explorers.
Before running any of the commands above, one has to configure foundry to add the desired profile name. That is achieved by editing the snfoundry.toml
file. Here is a sample configuration as reference
This requires an accounts.json
file. One such a way to generate it is using the following command
One can setup an ArgentX or Braavos wallet, fund it, and export its private key.
Submitting the proof to the blockchain using the Garaga CLI
Once the smart contract is published on the blockchain network, users can interact with it. In our case, one such interaction would be to perform a computation off-chain with RiscZero and submit it to the smart contract.
As mentioned before, the JSON proof artifact generated by the RiscZero execution can be submitted to the blockchain using Garaga CLI:
In order to run the Garaga verify-onchain
command you will need to provide a .secrets
file in the current folder, or elsewhere using the --env-file
option. Here is the format for the .secrets
file
Please make sure to provide RPC endpoints that supports version 0.7 of the Starknet JSON API
Last updated