Try out the Release (Available for X11 systems)
This is experimental software, intended for usage on testnets. It has not been audited.
Application for proving membership in an on-chain set of merkle tree leaves, without revealing which leaf is yours.
Creates, stores, and generates groth16 proofs for leaves. Reads data from tree smart contracts and sends transactions.
Can work for trees of fixed size, but the included example uses dynamic trees that expand as users add new leaves. Works for trees built with Keccak256 or SHA256.
Built using Godot Ethers, Godot Rust, and Godot 4.3 Beta.
- x86 architecture (currently only x86 computers can generate RISC Zero groth16 proofs)
- X11 (Linux) OS (the Godot application binary is currently only compiled for X11)
- Docker (necessary for generating proofs)
- RISC Zero groth16 Prover image (must be built and available for the application to work)
To build the groth16 prover image, first run git lfs clone https://github.com/risc0/risc0
, then follow these instructions.
RISC Zero is a general purpose zero knowledge virtual machine. Instead of creating a specialized ZK circuit for an application, it is instead possible to write programs in Rust that will behave like zero knowledge circuits. The outputs of these programs can be verified by the RISC Zero verifier, without knowing what the inputs were or even how the program is coded.
This is possible because every program has a unique "Image ID", which is essentially a snapshot of the program's state. To guarantee that Image IDs are generated deterministically, all RISC Zero programs must be built in a specific Docker container, where the snapshot can be taken under the same system conditions every time.
Groth16 proofs can be generated using a RISC Zero program, and submitted to an on-chain verifier along with the Image ID and a SHA256 hash of the program's output. Using just the ZK proof, the verifier can know whether the program tied to that Image ID produced the provided outputs.
For this application, the RISC Zero program does the following:
-
It receives a secret and nullifier, hashes each value, and then hashes the hashes together, to get the leaf hash the application is trying to prove.
-
It also receives a merkle path. It will check that the leaf hash is in the bottom layer of the path, and then proceed up the path to calculate the merkle root.
-
It also receives a recipient address, to ensure that only the specified address can use the proof.
The program's outputs are the address, the nullifier hash, and the calculated root. A proof is generated along with the outputs.
The three outputs are hashed on-chain, and checked by the RISC Zero Verifier against the proof and the on-chain Image ID. Since the secret half of the leaf hash is never publicly revealed, it is impossible for anyone to know which leaf was just proven.
The smart contract checks that the calculated root is in the root history (rejecting the proof if not), and records the nullifier hash so it can't be reused. It will finish the sequence by performing an action for the recipient address.
If you'd like to import the project into the Godot editor, make sure to open the gdextension folder and unzip the RISC0 library.