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

Added run_and_prove binary #227

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
28 changes: 20 additions & 8 deletions stwo_cairo_prover/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions stwo_cairo_prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ members = [
"crates/adapted_prover",
"crates/prover",
"crates/utils",
"crates/run_and_prove",
"crates/vm_runner",
"crates/prover_types",
]
Expand All @@ -29,6 +30,8 @@ rand = "0.8.5"
serde = "1.0.207"
serde_json = "1.0.1"
sonic-rs = "0.3.10"
stwo_cairo_prover = { path = "crates/prover", version = "~0.1.0" }
stwo_cairo_utils = { path = "crates/utils", version = "~0.1.0" }
# TODO(ShaharS): take stwo version from the source repository.
stwo-prover = { git = "https://github.com/starkware-libs/stwo", rev = "6e7d2aa6", features = [
"parallel",
Expand All @@ -39,6 +42,9 @@ tracing-subscriber = "0.3.18"
paste = "1.0"
starknet-ff = "0.3.7"
ruint = "1.12.3"
# Pin wasm-bindgen version to the version pinned by lambdaclass/cairo-vm/vm
# TODO(yuval): remove the pin once the pinning in lambdaclass/cairo-vm/vm is removed.
wasm-bindgen = { version = "= 0.2.92" }

[profile.bench]
codegen-units = 1
Expand Down
5 changes: 2 additions & 3 deletions stwo_cairo_prover/crates/adapted_prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ edition = "2021"
[dependencies]
clap.workspace = true
log.workspace = true
serde.workspace = true
serde_json.workspace = true
stwo_cairo_prover = { path = "../prover", version = "~0.1.0" }
stwo_cairo_utils = { path = "../utils", version = "~0.1.0" }
stwo_cairo_prover.workspace = true
stwo_cairo_utils.workspace = true
stwo-prover.workspace = true
thiserror.workspace = true
tracing.workspace = true
17 changes: 2 additions & 15 deletions stwo_cairo_prover/crates/adapted_prover/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use stwo_cairo_prover::cairo_air::air::CairoProof;
use stwo_cairo_prover::cairo_air::prove_cairo;
use stwo_cairo_prover::input::vm_import::{import_from_vm_output, VmImportError};
use stwo_cairo_prover::input::CairoInput;
use stwo_cairo_utils::logging_utils::init_logging;
use stwo_cairo_utils::binary_utils::run_binary;
use stwo_prover::core::prover::ProvingError;
use stwo_prover::core::vcs::blake2_merkle::Blake2sMerkleHasher;
use thiserror::Error;
Expand Down Expand Up @@ -43,18 +43,7 @@ enum Error {
}

fn main() -> ExitCode {
// TODO(yuval): allow control on log levels through args.
init_logging(log::LevelFilter::Info);
match run(std::env::args()) {
Ok(_) => {
log::info!("Adapted prover succeeded");
ExitCode::SUCCESS
}
Err(error) => {
log::info!("Adapted prover failed: {error}");
ExitCode::FAILURE
}
}
run_binary(run)
}

fn run(args: impl Iterator<Item = String>) -> Result<CairoProof<Blake2sMerkleHasher>, Error> {
Expand All @@ -69,8 +58,6 @@ fn run(args: impl Iterator<Item = String>) -> Result<CairoProof<Blake2sMerkleHas

let proof = prove_cairo(vm_output)?;

// TODO(yuval): This is just some serialization for the sake of serialization. Find the right
// way to serialize the proof.
std::fs::write(args.proof_path, serde_json::to_string(&proof)?)?;

Ok(proof)
Expand Down
14 changes: 14 additions & 0 deletions stwo_cairo_prover/crates/run_and_prove/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "run_and_prove"
version = "0.1.0"
edition = "2021"

[dependencies]
clap.workspace = true
log.workspace = true
serde_json.workspace = true
stwo_cairo_prover.workspace = true
stwo_cairo_utils.workspace = true
stwo-prover.workspace = true
thiserror.workspace = true
tracing.workspace = true
65 changes: 65 additions & 0 deletions stwo_cairo_prover/crates/run_and_prove/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::path::PathBuf;
use std::process::ExitCode;

use clap::Parser;
use stwo_cairo_prover::cairo_air::air::CairoProof;
use stwo_cairo_prover::cairo_air::prove_cairo;
use stwo_cairo_prover::input::vm_import::VmImportError;
use stwo_cairo_utils::adapter_utils::adapt_vm_output_to_stwo;
use stwo_cairo_utils::binary_utils::run_binary;
use stwo_cairo_utils::vm_utils::{run_vm, VmArgs, VmError};
use stwo_prover::core::prover::ProvingError;
use stwo_prover::core::vcs::blake2_merkle::Blake2sMerkleHasher;
use thiserror::Error;
use tracing::{span, Level};

/// Command line arguments for run_and_prove.
/// Example command line (use absolute paths):
/// ```
/// cargo run -r --bin run_and_prove -- --run_from_cairo_pie
/// --proof_path path/to/proof --secure_run=true path/to/cairo/pie
/// ```
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
#[command(flatten)]
vm_args: VmArgs,
#[structopt(long = "proof_path")]
proof_path: PathBuf,
}

#[derive(Debug, Error)]
enum Error {
#[error("Invalid arguments")]
Cli(#[from] clap::Error),
#[error("Failed to interact with the file system")]
IO(#[from] std::io::Error),
#[error("VM run failed: {0}")]
Vm(#[from] VmError),
#[error("Serialization failed: {0}")]
Serde(#[from] serde_json::error::Error),
#[error("VM import failed: {0}")]
VmImport(#[from] VmImportError),
#[error("Proving failed: {0}")]
Proving(#[from] ProvingError),
}

fn main() -> ExitCode {
run_binary(run)
}

fn run(args: impl Iterator<Item = String>) -> Result<CairoProof<Blake2sMerkleHasher>, Error> {
let _span = span!(Level::INFO, "run").entered();
let args = Args::try_parse_from(args)?;
let cairo_runner = run_vm(&args.vm_args)?;
let cairo_input = adapt_vm_output_to_stwo(cairo_runner);

let casm_states_by_opcode_count = &cairo_input.state_transitions.casm_states_by_opcode.counts();
log::info!("Casm states by opcode count: {casm_states_by_opcode_count:?}");

let proof = prove_cairo(cairo_input)?;

std::fs::write(args.proof_path, serde_json::to_string(&proof)?)?;

Ok(proof)
}
4 changes: 4 additions & 0 deletions stwo_cairo_prover/crates/utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ version = "0.1.0"
edition = "2021"

[dependencies]
cairo-vm.workspace = true
clap.workspace = true
env_logger.workspace = true
log.workspace = true
stwo_cairo_prover.workspace = true
thiserror.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
12 changes: 12 additions & 0 deletions stwo_cairo_prover/crates/utils/src/adapter_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use cairo_vm::vm::runners::cairo_runner::CairoRunner;
use stwo_cairo_prover::input::plain::input_from_finished_runner;
use stwo_cairo_prover::input::CairoInput;

// TODO(yuval): consider directly calling `input_from_finished_runner` (and add `span` there) and
// removing this function+module.
/// Adapts the Cairo VM output to the input of Stwo.
/// Assumes memory and trace are already relocated. Otherwise panics.
pub fn adapt_vm_output_to_stwo(runner: CairoRunner) -> CairoInput {
let _span = tracing::info_span!("adapt_vm_output_to_stwo").entered();
input_from_finished_runner(runner, false)
}
20 changes: 20 additions & 0 deletions stwo_cairo_prover/crates/utils/src/binary_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::env::Args;
use std::fmt::Display;
use std::process::ExitCode;

use crate::logging_utils::init_logging;

pub fn run_binary<T, E: Display>(run_function: fn(Args) -> Result<T, E>) -> ExitCode {
// TODO(yuval): allow control on log levels through args.
init_logging(log::LevelFilter::Info);
match run_function(std::env::args()) {
Ok(_) => {
log::info!("run_and_prove succeeded");
ExitCode::SUCCESS
}
Err(error) => {
log::info!("run_and_prove failed: {error}");
ExitCode::FAILURE
}
}
}
3 changes: 3 additions & 0 deletions stwo_cairo_prover/crates/utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
pub mod adapter_utils;
pub mod binary_utils;
pub mod logging_utils;
pub mod vm_utils;
101 changes: 101 additions & 0 deletions stwo_cairo_prover/crates/utils/src/vm_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::path::PathBuf;

use cairo_vm::cairo_run;
use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor;
use cairo_vm::types::layout_name::LayoutName;
use cairo_vm::vm::errors::cairo_run_errors::CairoRunError;
use cairo_vm::vm::runners::cairo_pie::CairoPie;
use cairo_vm::vm::runners::cairo_runner::{CairoRunner, RunResources};
use clap::{Parser, ValueHint};
use thiserror::Error;
use tracing::span;

// This struct is copied-then-modified from cairo-vm repo.
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct VmArgs {
#[clap(value_parser, value_hint=ValueHint::FilePath)]
pub filename: PathBuf,
#[clap(long = "trace_file", value_parser)]
pub trace_file: Option<PathBuf>,
#[structopt(long = "print_output")]
pub print_output: bool,
#[structopt(long = "entrypoint", default_value = "main")]
pub entrypoint: String,
#[structopt(long = "memory_file")]
pub memory_file: Option<PathBuf>,
#[structopt(long = "proof_mode")]
pub proof_mode: bool,
#[structopt(long = "secure_run")]
pub secure_run: Option<bool>,
#[clap(long = "air_public_input", requires = "proof_mode")]
pub air_public_input: Option<String>,
#[clap(
long = "air_private_input",
requires_all = ["proof_mode", "trace_file", "memory_file"]
)]
pub air_private_input: Option<String>,
#[clap(
long = "cairo_pie_output",
// We need to add these air_private_input & air_public_input or else
// passing cairo_pie_output + either of these without proof_mode will not fail
conflicts_with_all = ["proof_mode", "air_private_input", "air_public_input"]
)]
pub cairo_pie_output: Option<String>,
#[structopt(long = "allow_missing_builtins")]
pub allow_missing_builtins: Option<bool>,
#[structopt(
long = "run_from_cairo_pie",
// We need to add these air_private_input & air_public_input or else
// passing run_from_cairo_pie + either of these without proof_mode will not fail
conflicts_with_all = ["proof_mode", "air_private_input", "air_public_input"]
)]
pub run_from_cairo_pie: bool,
}

#[derive(Debug, Error)]
pub enum VmError {
#[error("Failed to interact with the file system")]
IO(#[from] std::io::Error),
#[error("The cairo program execution failed")]
Runner(#[from] CairoRunError),
}

// This function's logic is copied-then-modified from cairo-vm-cli/src/main.rs:run in cairo-vm repo.
/// Runs the Cairo VM according to the given arguments (which are subset of the cairo-vm arguments).
pub fn run_vm(args: &VmArgs) -> Result<CairoRunner, VmError> {
let _span = span!(tracing::Level::INFO, "run_vm").entered();
let cairo_run_config = cairo_run::CairoRunConfig {
entrypoint: &args.entrypoint,
trace_enabled: true,
relocate_mem: true,
layout: LayoutName::all_cairo,
proof_mode: args.proof_mode,
secure_run: args.secure_run,
allow_missing_builtins: args.allow_missing_builtins,
..Default::default()
};

let cairo_runner_result = if args.run_from_cairo_pie {
let pie = CairoPie::read_zip_file(&args.filename)?;
let mut hint_processor = BuiltinHintProcessor::new(
Default::default(),
RunResources::new(pie.execution_resources.n_steps),
);
cairo_run::cairo_run_pie(&pie, &cairo_run_config, &mut hint_processor)
} else {
let program_content = std::fs::read(args.filename.clone()).map_err(VmError::IO)?;
let mut hint_processor = BuiltinHintProcessor::new_empty();
cairo_run::cairo_run(&program_content, &cairo_run_config, &mut hint_processor)
};

let cairo_runner = match cairo_runner_result {
Ok(runner) => runner,
Err(error) => {
eprintln!("{error}");
return Err(VmError::Runner(error));
}
};

Ok(cairo_runner)
}
Loading
Loading