Skip to content

Commit

Permalink
migrate cli to extern crate (#598)
Browse files Browse the repository at this point in the history
* migrate cli to extern crate

* add clap4 for cli handling

* cargo fmt

* readme changes

* Add disclaimer readme

* Remove bit security text from cairo prover crate

* add compile option to makefile

* add compile and run all to makefile

* add example to readme

* cargo fmt

* add compile and prove to makefile

* better readme

* add quiet flag to makefile binaries

* reorganized readme

---------

Co-authored-by: Jmunoz <[email protected]>
Co-authored-by: Mariano A. Nicolini <[email protected]>
Co-authored-by: MauroFab <[email protected]>
  • Loading branch information
4 people authored Oct 12, 2023
1 parent 5a938e7 commit 50b9fbd
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 118 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo"]
members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo", "provers/cairo-prover-cli"]
exclude = ["ensure-no_std"]
resolver = "2"

Expand All @@ -15,6 +15,7 @@ lambdaworks-crypto = { path = "./crypto", version = "0.2.0" }
lambdaworks-gpu = { path = "./gpu", version = "0.2.0" }
lambdaworks-math = { path = "./math", version = "0.2.0" }
stark-platinum-prover = { path = "./provers/stark", version = "0.2.0" }
cairo-platinum-prover = { path = "./provers/cairo", version = "0.2.0" }

[profile.bench]
lto = true
Expand Down
13 changes: 4 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,16 @@ Zero-Knowledge and Validity Proofs have gained a lot of attention over the last

So, we decided to build our library, focusing on performance, with clear documentation and developer-focused. Our core team is a group of passionate people from different backgrounds and different strengths; we think that the whole is greater than just the addition of the parts. We don't want to be a compilation of every research result in the ZK space. We want this to be a library that can be used in production, not just in academic research. We want to offer developers the main building blocks and proof systems so that they can build their applications on top of this library.

## Provers and Polynomial Commitment Schemes using LambdaWorks

All provers are being migrated to Lambdaworks library

Right now Plonk prover is in this repo, you can find the others here:

- [Cairo STARK LambdaWorks prover](https://github.com/lambdaclass/lambdaworks_cairo_prover/tree/main)
- [CairoVM Trace Generation using LambdaWorks](https://github.com/lambdaclass/cairo-rs/pull/1184)
- [ABI compatible KZG commitment scheme - EIP-4844](https://github.com/lambdaclass/lambdaworks_kzg)

## Main crates

- [Math](https://github.com/lambdaclass/lambdaworks/tree/main/math)
- [Crypto primitives](https://github.com/lambdaclass/lambdaworks/tree/main/crypto)
- [Plonk Prover](https://github.com/lambdaclass/lambdaworks/tree/main/provers/plonk)
- [Cairo Prover](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo)
- [Cairo Prover CLI](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo-prover-cli)

If you are interested in proving Cairo programs, use the Cairo Prover CLI.

### Crypto
- [Elliptic curves](https://github.com/lambdaclass/lambdaworks/tree/main/math/src/elliptic_curve)
Expand Down
16 changes: 16 additions & 0 deletions provers/cairo-prover-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "cairo-platinum-prover-cli"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true

[[bin]]
name = "cairo-platinum-prover-cli"
path = "src/main.rs"

[dependencies]
lambdaworks-math = { workspace = true , features = ["lambdaworks-serde"] }
stark-platinum-prover = { workspace = true, features = ["wasm"] }
cairo-platinum-prover = { workspace = true}
clap = { version = "4.4.6", features = ["derive"] }
43 changes: 43 additions & 0 deletions provers/cairo-prover-cli/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.PHONY: test coverage clippy clean

ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

# Variable to give compiled Cairo programas a proper name. It extracts the file extension and adds
# the .json extension to it.
COMPILED_PROGRAM=$(basename $(PROGRAM_PATH)).json

build:
cargo build --release

docker_build_cairo_compiler:
docker build -f cairo_compile.Dockerfile -t cairo .

compile:
cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \
docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM)

prove:
cargo run --quiet --release prove $(PROGRAM_PATH) $(PROOF_PATH)

verify:
cargo run --quiet --release verify $(PROOF_PATH)

run_all:
cargo run --quiet --release prove-and-verify $(PROGRAM_PATH)

compile_and_prove:
@cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \
docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM)
@echo "Compiling done \n"
@cargo run --quiet --release prove $(COMPILED_PROGRAM) $(PROOF_PATH)
@rm $(COMPILED_PROGRAM)

compile_and_run_all:
@cairo-compile --proof_mode $(PROGRAM_PATH) > $(COMPILED_PROGRAM) 2>/dev/null || \
docker run -v $(ROOT_DIR):/pwd cairo --proof_mode /pwd/$(PROGRAM_PATH) > $(COMPILED_PROGRAM)
@echo "Compiling done \n"
@cargo run --quiet --release prove-and-verify $(COMPILED_PROGRAM) $(PROOF_PATH)
@rm $(COMPILED_PROGRAM)

clippy:
cargo clippy --workspace --all-targets -- -D warnings
107 changes: 107 additions & 0 deletions provers/cairo-prover-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<div align="center">

# Lambdaworks Cairo Platinum Prover CLI

</div>

## ⚠️ Disclaimer

This prover is still in development and may contain bugs. It is not intended to be used in production yet.

Please check issues under security label, and wait for them to be resolved if they are relevant your project.

Output builtin is finished, and range check is supported but it's not sound yet.

CLI currently runs with 100 bits of conjecturable security

## [Cairo Platinum Prover Docs](<[lambdaclass.github.io/lambdaworks/](https://github.com/lambdaclass/lambdaworks/blob/main/provers/cairo/README.md)>)

### Usage:

To prove programs Cairo has to be compiled. For compilation you need to have `cairo-lang` or `docker` installed.

When using Docker, start by creating the container image with:

```**bash**
make docker_build_cairo_compiler
```

Examples of Cairo 0 programs can be found [here](https://github.com/lambdaclass/lambdaworks/tree/main/provers/cairo/cairo_programs/cairo0)


**To compile and generate a proof you can use:**

```bash
make compile_and_prove PROGRAM_PATH=<program_path> PROOF_PATH=<output_proof_path>
```

For example:

```bash
make compile_and_prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo PROOF_PATH=cairo_programs/cairo0/fibonacci_5.proof
```


**To verify a proof you can use:**

```bash
make verify PROOF_PATH=<proof_path>
```

For example:

```bash
make verify PROOF_PATH=fibonacci_5.proof
```

**To compile Cairo:**

```bash
make compile PROGRAM_PATH=<uncompiled_program_path>
```

For example:

```bash
make compile PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo
```

**To prove a compiled program:**

```bash
make prove PROGRAM_PATH=<compiled_program_path> PROOF_PATH=<output_proof_path>
```

For example:

```bash
make prove PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json PROOF_PATH=program_proof.proof
```



**To prove and verify with a single command you can use:**

```bash
make run_all PROGRAM_PATH=<compiled_program_path>
```

For example:

```bash
make run_all PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.json
```



**To compile, proof, prove and verify at the same time you can use:**

```bash
make compile_and_run_all PROGRAM_PATH=<program_path>
```

For example:

```bash
make compile_and_run_all PROGRAM_PATH=cairo_programs/cairo0/fibonacci_5.cairo
```
11 changes: 11 additions & 0 deletions provers/cairo-prover-cli/cairo_compile.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM python:3.9-slim

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends g++ libgmp3-dev

COPY requirements.txt /

RUN pip install -r /requirements.txt

ENTRYPOINT ["cairo-compile"]
6 changes: 6 additions & 0 deletions provers/cairo-prover-cli/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ecdsa==0.18.0
bitarray==2.7.3
fastecdsa==2.2.3
sympy==1.11.1
typeguard==2.13.3
cairo-lang==0.11.0
105 changes: 56 additions & 49 deletions provers/cairo/src/main.rs → provers/cairo-prover-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,43 @@ use lambdaworks_math::traits::{Deserializable, Serializable};
use stark_platinum_prover::proof::options::{ProofOptions, SecurityLevel};
use stark_platinum_prover::proof::stark::StarkProof;

use std::env;
use std::time::Instant;

use clap::{Args, Parser, Subcommand};

#[derive(Parser, Debug)]
#[command(author = "Lambdaworks", version, about)]
struct ProverArgs {
#[clap(subcommand)]
entity: ProverEntity,
}

#[derive(Subcommand, Debug)]
enum ProverEntity {
#[clap(about = "Generate a proof for a given compiled cairo program")]
Prove(ProveArgs),
#[clap(about = "Verify a proof for a given compiled cairo program")]
Verify(VerifyArgs),
#[clap(about = "Generate and verify a proof for a given compiled cairo program")]
ProveAndVerify(ProveAndVerifyArgs),
}

#[derive(Args, Debug)]
struct ProveArgs {
program_path: String,
proof_path: String,
}

#[derive(Args, Debug)]
struct VerifyArgs {
proof_path: String,
}

#[derive(Args, Debug)]
struct ProveAndVerifyArgs {
program_path: String,
}

fn generate_proof(
input_path: &String,
proof_options: &ProofOptions,
Expand Down Expand Up @@ -68,31 +102,17 @@ fn verify_proof(
fn main() {
let proof_options = ProofOptions::new_secure(SecurityLevel::Conjecturable100Bits, 3);

let args: Vec<String> = env::args().collect();

if args.len() < 2 {
println!("Usage: cargo run <command> [arguments]");
return;
}

let command = &args[1];

match command.as_str() {
"prove" => {
if args.len() < 4 {
println!("Usage: cargo run prove <input_path> <output_path>");
return;
}

let input_path = &args[2];
let output_path = &args[3];

if input_path.contains(".cairo") {
let args: ProverArgs = ProverArgs::parse();
match args.entity {
ProverEntity::Prove(args) => {
// verify input file is .cairo
if args.program_path.contains(".cairo") {
println!("\nYou are trying to prove a non compiled Cairo program. Please compile it before sending it to the prover.\n");
return;
}

let Some((proof, pub_inputs)) = generate_proof(input_path, &proof_options) else {
let Some((proof, pub_inputs)) = generate_proof(&args.program_path, &proof_options)
else {
return;
};

Expand All @@ -102,62 +122,49 @@ fn main() {
bytes.extend(proof_bytes);
bytes.extend(pub_inputs.serialize());

let Ok(()) = std::fs::write(output_path, bytes) else {
println!("Error writing proof to file: {output_path}");
let Ok(()) = std::fs::write(&args.proof_path, bytes) else {
println!("Error writing proof to file: {}", args.proof_path);
return;
};
println!("Proof written to {output_path}");
println!("Proof written to {}", args.proof_path);
}
"verify" => {
if args.len() < 3 {
println!("Usage: cargo run verify <input_path>");
return;
}

let input_path = &args[2];
let Ok(program_content) = std::fs::read(input_path) else {
println!("Error opening {input_path} file");
ProverEntity::Verify(args) => {
let Ok(program_content) = std::fs::read(&args.proof_path) else {
println!("Error opening {} file", args.proof_path);
return;
};
let mut bytes = program_content.as_slice();
if bytes.len() < 8 {
println!("Error reading proof from file: {input_path}");
println!("Error reading proof from file: {}", args.proof_path);
return;
}

let proof_len = usize::from_be_bytes(bytes[0..8].try_into().unwrap());
bytes = &bytes[8..];
if bytes.len() < proof_len {
println!("Error reading proof from file: {input_path}");
println!("Error reading proof from file: {}", args.proof_path);
return;
}
let Ok(proof) = StarkProof::<Stark252PrimeField>::deserialize(&bytes[0..proof_len])
else {
println!("Error reading proof from file: {input_path}");
println!("Error reading proof from file: {}", args.proof_path);
return;
};
bytes = &bytes[proof_len..];

let Ok(pub_inputs) = PublicInputs::deserialize(bytes) else {
println!("Error reading proof from file: {input_path}");
println!("Error reading proof from file: {}", args.proof_path);
return;
};

verify_proof(proof, pub_inputs, &proof_options);
}
"prove_and_verify" => {
if args.len() < 3 {
println!("Usage: cargo run prove_and_verify <input_path>");
return;
}

let input_path = &args[2];
let Some((proof, pub_inputs)) = generate_proof(input_path, &proof_options) else {
ProverEntity::ProveAndVerify(args) => {
let Some((proof, pub_inputs)) = generate_proof(&args.program_path, &proof_options)
else {
return;
};
verify_proof(proof, pub_inputs, &proof_options);
}
_ => {
println!("Unknown command: {}", command);
}
}
}
Loading

0 comments on commit 50b9fbd

Please sign in to comment.