Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate cli to extern crate #598

Merged
merged 16 commits into from
Oct 12, 2023
Merged
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
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