Skip to content

Commit

Permalink
Merge pull request #146 from HerodotusDev/autogenerated_split
Browse files Browse the repository at this point in the history
Split verifier
  • Loading branch information
Okm165 authored Sep 28, 2024
2 parents 05fb716 + aa28d4d commit 53a9168
Show file tree
Hide file tree
Showing 175 changed files with 34,312 additions and 29,575 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*example_proof.json filter=lfs diff=lfs merge=lfs -text
24 changes: 8 additions & 16 deletions .github/workflows/proof_verification_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,24 @@ jobs:
strategy:
matrix:
cairo_version: ["cairo0", "cairo1"]
layout: ["dex", "recursive", "recursive_with_poseidon", "small", "starknet", "starknet_with_keccak"]
layout: ["recursive", "recursive_with_poseidon", "small", "dex", "starknet", "starknet_with_keccak"]
hash_function: ["keccak"]
hasher_bit_length: ["160_lsb"]
stone_version: ["stone5"]
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
lfs: true

- name: Setup Scarb
uses: software-mansion/setup-scarb@v1

- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.10'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Configure layout
run: python configure.py -l ${{ matrix.layout }} -s keccak

- name: Build project
run: scarb build
run: scarb build --no-default-features --features monolith,${{ matrix.layout }},${{ matrix.hash_function }}

- name: Run verification
run: cargo run --release --bin runner -- -p target/dev/cairo_verifier.sierra.json -c ${{ matrix.cairo_version }} < examples/proofs/${{ matrix.layout }}/${{ matrix.cairo_version }}_example_proof.json
run: cargo run --release --bin runner -- --program target/dev/cairo_verifier.sierra.json --cairo-version ${{ matrix.cairo_version }} --stone-version ${{ matrix.stone_version }} --hasher-bit-length ${{ matrix.hasher_bit_length }} < examples/proofs/${{ matrix.layout }}/${{ matrix.cairo_version }}_${{ matrix.stone_version }}_${{ matrix.hash_function }}_${{ matrix.hasher_bit_length }}_example_proof.json
3 changes: 0 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,3 @@ jobs:

- name: Run tests
run: scarb test

- name: Build fact registry
run: (cd fact_registry && scarb build)
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@
resources/

# Stone-prover repository
stone-prover
stone-prover

**/.DS_Store
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
scarb 2.6.3
starknet-foundry 0.24.0
scarb 2.8.2
starknet-foundry 0.30.0
26 changes: 13 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
[workspace]
resolver = "2"
members = ["runner", "benches", "examples/starknet"]
members = ["runner", "benches", "serializer"]

[workspace.package]
edition = "2021"
version = "0.1.0"

[workspace.dependencies]
anyhow = "1"
cairo-felt = "0.9"
cairo-lang-casm = { git = "https://github.com/starkware-libs/cairo/", rev = "4471a55923663eb8150ea6cd636d5c1038b137d1"}
cairo-lang-runner = { git = "https://github.com/starkware-libs/cairo/", rev = "4471a55923663eb8150ea6cd636d5c1038b137d1"}
cairo-lang-sierra = { git = "https://github.com/starkware-libs/cairo/", rev = "4471a55923663eb8150ea6cd636d5c1038b137d1"}
cairo-lang-utils = { git = "https://github.com/starkware-libs/cairo/", rev = "4471a55923663eb8150ea6cd636d5c1038b137d1"}
anyhow = "1.0.89"
cairo-lang-casm = { git = "https://github.com/starkware-libs/cairo/", version = "~2.8.2"}
cairo-lang-runner = { git = "https://github.com/starkware-libs/cairo/", version = "~2.8.2"}
cairo-lang-sierra = { git = "https://github.com/starkware-libs/cairo/", version = "~2.8.2"}
cairo-lang-utils = { git = "https://github.com/starkware-libs/cairo/", version = "~2.8.2"}
cairo-vm = "1.0.1"
clap = { version = "4.5.2", features = ["derive"] }
clap = { version = "4.5.17", features = ["derive"] }
itertools = "0.13.0"
num-bigint = "0.4.4"
num-bigint = "0.4.6"
runner = { path = "runner" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
swiftness_proof_parser = { git = "https://github.com/iosis-tech/swiftness", rev = "a53d65ecbd7acf4611b0d587d815f4e9d4d493ed"}
thiserror = "1.0"
serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0.128"
starknet-types-core = "0.1.5"
swiftness_proof_parser = "0.1.0"
thiserror = "1.0.63"
152 changes: 124 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,66 +6,109 @@

[![Continuous Integration - proof verification tests](https://github.com/HerodotusDev/cairo-verifier/actions/workflows/proof_verification_tests.yml/badge.svg)](https://github.com/HerodotusDev/cairo-verifier/actions/workflows/proof_verification_tests.yml)

## Building the Verifier
## Table of contents

To build the Cairo Verifier, follow these steps:
- [Prerequisites](#prerequisites)
- [Using Verifier contracts on Starknet](#using-verifier-contracts-on-starknet)
- [Running locally](#running-locally)
- [Creating a Proof](#creating-a-proof)
- [Deployment](#deployment)
- [Split Verifier Architecture](#split-verifier-architecture)

1. Build the project by running the following command in your terminal:
## Prerequisites

To use the verifier with contracts deployed on Starknet, you need to have [Rust](https://www.rust-lang.org/tools/install) and [Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/getting-started/installation.html) installed. Also make sure to update [snfoundry.toml](./snfoundry.toml) file with appropriate `account` name and RPC `url`.

For running locally and development, you will need [scarb](https://docs.swmansion.com/scarb/) (we recommend using [asdf](https://asdf-vm.com/) version manager).

### Getting example proofs

Because of large size of proofs, we don't store example proofs directly in this repository, but rather in [Large File Storage](https://git-lfs.com/), so you need to have it installed and then run `git lfs pull` to get all example proofs.

## Using Verifier contracts on Starknet

Integrity verifier is deployed on Starknet and can be used for verifying proofs onchain. The intended way of using the verifier is through FactRegistry contract, which besides running the verification process, also stores data for all verified proofs. (For more information see [FactRegistry and Proxy contract](#factregistry-and-proxy-contract))

There are two ways of serializing proof into calldata: monolith and split proof. The former should be used if possible, because it's easier and more efficient. The latter should only be used if monolith proof did not fit in a single transaction, either because of calldata limit or steps limit.

### Monolith proof

Calldata for monolith proof can be generated with the following command:

```bash
scarb build
cargo run --release --bin proof_serializer < examples/proofs/recursive/cairo0_stone5_keccak_160_lsb_example_proof.json > examples/calldata
```

2. (Optional) Test the project to ensure everything works correctly:
After that, you can use `verify-on-starknet.sh` script to send the transaction to FactRegistry contract. Remember to select appropriate settings for your proof. For more information on supported settings, see [Configure Verifier](#configure-verifier).

For example, run:

```bash
scarb test
./verify-on-starknet.sh 0x1c74507b566047b76c625f75d6ea7987fb1e3b3f225c7dd7836bd7381f6ef44 examples/calldata recursive keccak_248_lsb stone5 cairo0
```

## Running the Verifier on Example Proof
This bash script internally calls `verify_proof_full_and_register_fact` function on FactRegistry contract.

### Split proof

### Local Proof Verification
To generate split calldata, please refer to [Calldata Generator README](https://github.com/HerodotusDev/integrity-calldata-generator/blob/main/README.md). This repository also provides script for automatic transaction sending (proof verification is split into multiple transactions, for more information see [Split Verifier Architecture](#split-verifier-architecture)).

For local proof verification, follow these steps:
## Running locally

1. Run the verifier locally using the following command on example proof, followed by the Cairo version (cairo0 or cairo1) used to generate the proof:
To run the verifier locally, first you need to build cairo project using:

```bash
cargo run --release --bin runner -- --program target/dev/cairo_verifier.sierra.json -c cairo0 < examples/proofs/recursive/cairo0_example_proof.json
cargo run --release --bin runner -- --program target/dev/cairo_verifier.sierra.json -c cairo1 < examples/proofs/recursive/cairo1_example_proof.json
scarb build
```

### Starknet Proof Verification
The verifier by default is configured in recursive layout and keccak hasher. If you want to build for other layouts, refer to [Configure Verifier](#configure-verifier)

To verify proofs on Starknet, proceed with the following steps:
### Running the Verifier on Example Proof

1. Prepare calldata of example proof for sncast:
You can use cairo runner to run the verifier on example proof:

```bash
cargo run --release --bin snfoundry_proof_serializer -- -c cairo0 < examples/proofs/recursive/cairo0_example_proof.json > examples/starknet/calldata
cargo run --release --bin runner -- \
--program target/dev/cairo_verifier.sierra.json \
--cairo-version cairo0 \
--stone-version stone5 \
--hasher-bit-length 160_lsb \
< examples/proofs/recursive/cairo0_stone5_keccak_160_lsb_example_proof.json
```

2. Call the function with calldata on the Starknet contract:
### Configure Verifier

By default, the verifier is configured for monolith version, recursive layout and keccak hash for verifier unfriendly commitment layers. You can easily change that by using scarb's features:

```bash
cd examples/starknet
./1-verify-proof.sh 0x274d8165a19590bdeaa94d1dd427e2034462d7611754ab3e15714a908c60df7 calldata
scarb build --no-default-features --features small,blake2s,monolith
```

[List of deployed Verifier Contracts](deployed_contracts.md)
`layout`: [`dex`, `recursive`, `recursive_with_poseidon`, `small`, `starknet`, `starknet_with_keccak`]<br />
hash functions: [`keccak`, `blake2s`]<br />
verifier types: [`monolith`, `split`]

There are also additional settings that can be configured at runtime:

`cairo_version`: [`cairo0`, `cairo1`]<br />
`stone_version`: [`stone5`, `stone6`]<br />
hasher bit length: [`160_lsb`, `248_lsb`]

Hash function and hasher bit length are combined into one setting:

`hasher`: [`keccak_160_lsb`, `blake2s_160`, `blake2s_248_lsb`]

## Configure Verifier
For `stone5` available `hasher`s are `keccak_160_lsb` and `blake2s_160`, for `stone6` - `keccak_160_lsb` and `blake2s_248_lsb`.

By default, the verifier is configured for recursive layout and keccak hash for verifier unfriendly commitment layers. You can easily change that by using the configure python script (this script is in Experimental stage):
### Running tests

To run tests, use the following command:

```bash
python configure.py -l recursive -s keccak
scarb test
```

layout types: [dex, recursive, recursive_with_poseidon, small, starknet, starknet_with_keccak]
hash types: [keccak, blake2s]

## Benchmarking
### Benchmarking

In order to launch benchmarking, just run this (it requires recursive layout configuration):

Expand All @@ -81,4 +124,57 @@ For detailed instructions and examples, refer to the Stone Prover [documentation

How to prove [Cairo0](https://github.com/starkware-libs/stone-prover?tab=readme-ov-file#creating-and-verifying-a-proof-of-a-cairozero-program) program with Stone Prover.

How to prove [Cairo1](https://github.com/starkware-libs/stone-prover?tab=readme-ov-file#creating-and-verifying-a-proof-of-a-cairo-program) program with Stone Prover.
How to prove [Cairo1](https://github.com/starkware-libs/stone-prover?tab=readme-ov-file#creating-and-verifying-a-proof-of-a-cairo-program) program with Stone Prover.

## Deployment

If you want to deploy the verifier yourself, please follow these steps:

1. Deploy FactRegistry contract

```bash
bash deployment/fact_registry/deploy.sh
```

2. (optional) Deploy Proxy contract

```bash
bash deployment/proxy/deploy.sh
bash deployment/proxy/set_fact_registry.sh
```

3. Deploy and register Verifier contracts

Make sure to replace `<layout>` and `<hasher>` with appropriate names.

```bash
sncast multicall run --fee-token eth --path deployment/verifiers/<layout>/<hasher>/deploy.toml
bash deployment/verifiers/<layout>/<hasher>/register.sh
```

## Split Verifier Architecture

### Background information

Because of great complexity of the verifier compared to standard starknet contracts, we encounter some limitations enforced by starknet. The most important ones are:

- Contract classhash size limit
- Transaction calldata limit
- Transaction steps limit

To overcome these limitations, we split the verifier into multiple contracts and transactions. The biggest part of classhash size is autogenerated (e.g. [recursive autogenerated](/src/air/layouts/recursive/autogenerated.cairo)), so we extracted that part into separate contract (or many contracts in case of `starknet_with_keccak` layout), which is called automatically by the main verifier contract. On the other hand the biggest part of calldata is fri witness, so user can send subsequent chunks of fri witness in separate step transactions.

### FactRegistry and Proxy contract

Since verifier can be configured in many ways and some parts of the logic changes with new stone versions, a contract which routes calls to the correct verifier is needed. This task is handled by FactRegistry contract that also stores data for all verified proofs.

After proof is verified, `FactRegistered` event is emitted which contains `fact_hash`, `verification_hash`, `security_bits` and `settings`. `fact_hash` is a value that represents proven program and its output (formally `fact_hash = poseidon_hash(program_hash, output_hash)`). Remember that registration of some `fact_hash` doesn't necessary mean that it has been verified by someone with secure enough proof. You always need to check `security_bits` and `settings` which is part of `verification_hash` (formally `verification_hash = poseidon_hash(fact_hash, security_bits, settings)`).

`FactRegistry` provides two methods for checking verified proofs:

- `get_verification(verification_hash)` - returns fact hash, security bits and settings for given `verification_hash`.
- `get_all_verifications_for_fact_hash(fact_hash)` - returns list of all verification hashes, security bits and settings for given `fact_hash`. This method is useful for checking if given program has been verified by someone with secure enough proof.

FactRegistry contract is trustless which means that the owner of the contract can't override or change any existing behavior, they can only add new verifiers. Proxy contract on the other hand is upgradable, so every function can be changed or removed. It has the advantage of having all future updates of the verifier logic without having to replace the address of FactRegistry contract.

TODO: how to read FactRegistered event
32 changes: 32 additions & 0 deletions Scarb.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
[package]
name = "cairo_verifier"
version = "0.1.0"

[dependencies]
starknet = "2.8.2"

[dev-dependencies]
cairo_test = "2.8.2"
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.27.0" }

[[target.starknet-contract]]
casm = true
# sierra = true

[lib]
sierra = true
casm = false

[features]

recursive = []
recursive_with_poseidon = []
dex = []
small = []
starknet = []
starknet_with_keccak = []

keccak = []
blake2s = []

monolith = []
split = []

default = ["recursive", "keccak", "monolith"]
1 change: 0 additions & 1 deletion benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ edition = "2021"

[dependencies]
anyhow.workspace = true
cairo-felt.workspace = true
cairo-lang-runner.workspace = true
cairo-lang-sierra.workspace = true
cairo-lang-utils.workspace = true
Expand Down
50 changes: 0 additions & 50 deletions configure.py

This file was deleted.

Loading

0 comments on commit 53a9168

Please sign in to comment.