Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 113 additions & 140 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,203 +1,176 @@
# ProveKit
<div align="center">

A modular zero-knowledge proof toolkit optimized for mobile devices.
<img src="./assets/banner.png" alt="ProveKit" width="100%" />

## Requirements
[![CI](https://img.shields.io/badge/build-passing-2ea44f?style=flat-square&logo=github)](https://github.com/worldfnd/provekit/actions)
[![Rust](https://img.shields.io/badge/rust-nightly-e32828?style=flat-square&logo=rust)](https://rustup.rs/)
[![License](https://img.shields.io/badge/license-MIT%20%2F%20Apache_2.0-blue?style=flat-square)](./License.md)

This project makes use of Noir's `nargo` to compile circuits and generate test artifacts. Make sure to walk through the [Quick Start](https://noir-lang.org/docs/getting_started/quick_start#noir) section to install the noir toolchain. Note that we require a specific version of the toolchain, so make sure to override the version with the following command.
[Getting Started](#getting-started) · [Examples](./noir-examples/) · [Contributing](./CONTRIBUTING.md) · [Issues](https://github.com/worldfnd/provekit/issues)

```sh
noirup --version v1.0.0-beta.11
```
</div>

## Demo instructions
ProveKit lets you take a Noir circuit, compile it to R1CS, and generate a WHIR proof. It's built for mobile and constrained environments and ships with a custom BN254 hash engine ([Skyscraper](skyscraper/)), swap-to-disk memory management, and C FFI for iOS and Android. If you need on-chain verification, there's a gnark recursive verifier that wraps proofs in Groth16.

> _NOTE:_ The example below is being run for single example `poseidon-rounds`. You can use different example to run same commands.
---

Compile the Noir circuit:
## Architecture

```sh
cd noir-examples/poseidon-rounds
nargo compile
```
```mermaid
graph TD
subgraph Development
N[Noir .nr Source]
end

Prepare the Noir program (generates prover and verifier files):
subgraph ProveKit Pipeline
C{provekit-cli prepare}
PK(.pkp Proving Key)
VK(.pkv Verification Key)
P((Prover Engine))
V((Verifier Engine))
end

```sh
cargo run --release --bin provekit-cli prepare ./target/basic.json --pkp ./prover.pkp --pkv ./verifier.pkv
```
subgraph Integration
G[Gnark Recursive Verifier]
end

Generate the Noir Proof using the input Toml:
N -->|nargo| C
C --> PK
C --> VK

```sh
cargo run --release --bin provekit-cli prove ./prover.pkp ./Prover.toml -o ./proof.np
PK --> P
P -- proof.np --> V
VK --> V

V -->|Validates| G
```

Verify the Noir Proof:
### Crates

```sh
cargo run --release --bin provekit-cli verify ./verifier.pkv ./proof.np
```
| Layer | Crate | Description |
| :--- | :--- | :--- |
| CLI | `tooling/cli/` | `provekit-cli`: prepare, prove, verify, inspect |
| Prover / Verifier | `provekit/prover/`<br>`provekit/verifier/` | WHIR sumcheck, witness solving, commitment |
| Compiler | `provekit/r1cs-compiler/` | Noir ACIR → R1CS with constraint optimizations |
| Hash engine | `skyscraper/` | Custom BN254 hash with SIMD-accelerated field arithmetic |
| Interop | `tooling/provekit-gnark/`<br>`gnark-whir/` | Rust ↔ Go/gnark bridge for recursive verification |
| FFI | `tooling/provekit-ffi/` | C-compatible bindings for iOS, Android, and Python |

Generate inputs for Gnark circuit:
---

```sh
cargo run --release --bin provekit-cli generate-gnark-inputs ./prover.pkp ./proof.np
```
## Example

Analyze circuit statistics and R1CS complexity:
Here's [`noir-examples/basic-4`](./noir-examples/basic-4/), which proves knowledge of inputs `(a, b)` satisfying `(a + b) * (a - b) == result`:

```sh
cargo run --release --bin provekit-cli circuit_stats ./target/basic.json
```rust
fn main(a: Field, b: Field) -> pub Field {
let sum = a + b;
let diff = a - b;
sum * diff
}
```

Analyze PKP file size breakdown:

```sh
cargo run --release --bin provekit-cli analyze-pkp ./prover.pkp
cd noir-examples/basic-4
nargo compile
cargo run --release --bin provekit-cli prepare ./target/basic.json --pkp prover.pkp --pkv verifier.pkv
cargo run --release --bin provekit-cli prove prover.pkp Prover.toml -o proof.np
cargo run --release --bin provekit-cli verify verifier.pkv proof.np
```

Show public inputs with variable names:
---

```sh
cargo run --release --bin provekit-cli show-inputs ./verifier.pkv ./proof.np
```
## Getting Started

You need nargo `v1.0.0-beta.11` and Rust nightly. Toolchain is pinned in `rust-toolchain.toml`; rustup picks it up automatically.

Recursively verify in a Gnark proof:
<details>
<summary><strong>1. Install nargo</strong></summary><br>

```sh
cd ../../recursive-verifier
go run cmd/cli/main.go --config ../noir-examples/poseidon-rounds/params_for_recursive_verifier --r1cs ../noir-examples/poseidon-rounds/r1cs.json
noirup --version v1.0.0-beta.11
```
</details>

### Benchmarking
<details>
<summary><strong>2. Compile a circuit</strong></summary><br>

Benchmark against Barretenberg:

> _Note_: You can install Barretenberg from [here](https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/bbup/README.md).

> _Note_: You can install [hyperfine](https://github.com/sharkdp/hyperfine) using brew on OSX: `brew install hyperfine`.
The steps below use `poseidon-rounds` as the example circuit.

```sh
cd noir-examples/poseidon-rounds
nargo compile
cargo run --release --bin provekit-cli prepare ./target/basic.json --pkp ./prover.pkp --pkv ./verifier.pkv
hyperfine 'nargo execute && bb prove -b ./target/basic.json -w ./target/basic.gz -o ./target' '../../target/release/provekit-cli prove ./prover.pkp ./Prover.toml'
```
</details>

### Profiling

#### Custom built-in profile (Memory usage)

The `provekit-cli` application has written custom memory profiler that prints basic info about memory usage when application
runs. To run binary with profiling enabled run it with cargo `--features profiling` param or compile with it.
<details open>
<summary><strong>3. Prove and verify</strong></summary><br>

```sh
cargo run --release --bin provekit-cli --features profiling prove ./prover.pkp ./Prover.toml -o ./proof.np
```

#### Using tracy (CPU and Memory usage)

Tracy tool [website](https://github.com/wolfpld/tracy). To install tracy tool on OSX use brew: `brew install tracy`.

> **Important**: integration is done with `Tracy Profiler 0.11.1`. It is newest version available from brew. Newer
> version may require updating dependencies as tracy is using its own protocol between app and tracy tool that changes
> with each major version.

TLDR; Tracy is an interactive tool to profile application. There is integration plugin for rust that works with
standard tracing annotation. For now it is integrated into `provekit-cli` binary only. Collecting profiling data requires
tracy to run during application profiling. You may noticed that it makes application to run much longer but mostly
due to data transfer between the application and the tracy running along.

Usage:
# Generate a proof
cargo run --release --bin provekit-cli prove ./prover.pkp ./Prover.toml -o ./proof.np

1. Start tracy from command line
```sh
tracy
```
2. Leave all fields with defaults and just click `Connect` button. It will cause tracy to start listening on the
localhost for incoming data.
3. Compile `noir-r1cs-profiled` binary.
```sh
cargo build --release --bin provekit-cli --features profiling
```
4. (OSX only) If you want to check call stacks additional command needs to be run (base on tracy instruction). The
command must be run against each binary that is being profiled by tracy. This will create directory next to the
binary provided with `.dSYM` suffix (ex. `../../target/profiled-cli.dSYM`). Directory will contain the
debug symbols and paths extracted with different format that is compatible with tracy tool. It must be rerun after
each changes made to `provekit-cli` app.
```sh
dsymutil ../../target/release/provekit-cli
```
5. Now start the application to profile:
```sh
../../target/release/provekit-cli prove ./prover.pkp ./Prover.toml -o ./proof.np
# Verify locally
cargo run --release --bin provekit-cli verify ./verifier.pkv ./proof.np
```
6. Go back to tracy tool. You should see that it receives data. App is interactive.

#### Using samply (CPU usage)

Samply tool [website](https://github.com/mstange/samply/) with instructions to install. It will start local server and
open a webpage with interactive app to view results. This does not require to run binary
with profiling enabled.

**Recursive on-chain verification:**
```sh
samply record -r 10000 -- ./../../target/release/provekit-cli prove ./prover.pkp ./Prover.toml -o ./proof.np
cargo run --release --bin provekit-cli generate-gnark-inputs ./prover.pkp ./proof.np

cd ../../recursive-verifier
go run cmd/cli/main.go \
--config ../noir-examples/poseidon-rounds/params_for_recursive_verifier \
--r1cs ../noir-examples/poseidon-rounds/r1cs.json
```
</details>

#### Using instruments (Memory usage) - OSX only
<details>
<summary><strong>4. Benchmark</strong></summary><br>

Cargo instruments tool [website](https://crates.io/crates/cargo-instruments) with instructions to install. It will open
results using built-in Instruments app. Results are interactive.
Benchmark against [Barretenberg](https://github.com/AztecProtocol/aztec-packages/blob/master/barretenberg/bbup/README.md) with [hyperfine](https://github.com/sharkdp/hyperfine):

```sh
cargo instruments --template Allocations --release --bin provekit-cli prove ./prover.pkp ./Prover.toml -o ./proof.np
cd noir-examples/poseidon-rounds
cargo run --release --bin provekit-cli prepare ./target/basic.json --pkp ./prover.pkp --pkv ./verifier.pkv
hyperfine \
'nargo execute && bb prove -b ./target/basic.json -w ./target/basic.gz -o ./target' \
'../../target/release/provekit-cli prove ./prover.pkp ./Prover.toml'
```

Samply tool [website](https://github.com/mstange/samply/) with instructions to install. It will start local server and
open a webpage with interactive app to view results. This does not require to run binary
with profiling enabled.

Internal benchmark suite:
```sh
samply record -r 10000 -- ./../../target/release/provekit-cli prove ./prover.pkp ./Prover.toml -o ./proof.np
cargo test -p provekit-bench --bench bench
```
</details>

---

## Benchmarking
## Profiling

Run the benchmark suite:
| Tool | Measures | Command |
| :--- | :--- | :--- |
| Built-in allocator stats | Memory | `cargo run --release --features profiling --bin provekit-cli prove ...` |
| [Tracy](https://github.com/wolfpld/tracy) | CPU + memory (interactive GUI) | `cargo build --release --features profiling` then run the binary with Tracy listening. On macOS, run `dsymutil` on the binary first to get call stacks. |
| [Samply](https://github.com/mstange/samply) | CPU flamegraphs | `samply record -r 10000 -- ./target/release/provekit-cli prove ...` |
| [Instruments](https://crates.io/crates/cargo-instruments) | Allocations (macOS only) | `cargo instruments --template Allocations --release --bin provekit-cli prove ...` |

If you want to inspect without running a proof:
```sh
cargo test -p provekit-bench --bench bench
provekit-cli circuit_stats ./target/basic.json # constraint count and R1CS structure
provekit-cli analyze-pkp ./prover.pkp # proving key size breakdown
provekit-cli show-inputs ./verifier.pkv ./proof.np # public input names and values
```

## Architecture

ProveKit follows a modular architecture with clear separation of concerns:

### Core Modules
- **`provekit/common/`** - Shared utilities, core types, and R1CS abstractions
- **`provekit/r1cs-compiler/`** - R1CS compilation logic and Noir integration
- **`provekit/prover/`** - Proving functionality with witness generation
- **`provekit/verifier/`** - Verification functionality

### Tooling
- **`tooling/cli/`** - Command-line interface (`provekit-cli`)
- **`tooling/provekit-bench/`** - Benchmarking infrastructure
- **`tooling/provekit-gnark/`** - Gnark integration utilities
---

### High-Performance Components
- **`skyscraper/`** - Optimized field arithmetic for M31/CM31 fields
- **`playground/`** - Research and experimental implementations
## Acknowledgements

### Examples & Tests
- **`noir-examples/`** - Example circuits and test programs
- **`gnark-whir/`** - Go-based recursive verification using Gnark
- [**WHIR**](https://github.com/WizardOfMenlo/whir): the polynomial commitment scheme and sumcheck protocol the proof system is built on. `WhirR1CSScheme` wraps it for R1CS satisfiability over BN254.

## Dependencies
- [**Spongefish**](https://github.com/arkworks-rs/spongefish): Fiat-Shamir library from arkworks. All transcript construction and challenge derivation goes through its `DuplexSponge` API.

This project depends on the following libraries, which are developed in lockstep:
- [**gnark-skyscraper**](https://github.com/reilabs/gnark-skyscraper): Go implementation of the Skyscraper hash. The recursive verifier needs it to reproduce the same Merkle commitments as the Rust prover.

- [🌪️ WHIR](https://github.com/WizardOfMenlo/whir)
- [Spongefish](https://github.com/arkworks-rs/spongefish)
- [gnark-skyscraper](https://github.com/reilabs/gnark-skyscraper)
- [recursive-verifier](./recursive-verifier/README.md)
- [noir](https://github.com/noir-lang/noir)
- [**Noir**](https://github.com/noir-lang/noir): the ZK DSL we compile from. Write your circuit in Noir, run nargo to get ACIR, and ProveKit handles the rest.
Binary file added assets/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.