Skip to content

Commit

Permalink
Added vm-runner, wrapping cairo-vm and Stwo-adapter (starkware-libs#91)
Browse files Browse the repository at this point in the history
* Added vm-runner, wrapping cairo-vm and Stwo-adapter

* Removed TODOs and temp logs
  • Loading branch information
yuvalsw authored Oct 6, 2024
1 parent 61a2645 commit f43f285
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 296 deletions.
286 changes: 57 additions & 229 deletions stwo_cairo_prover/Cargo.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions stwo_cairo_prover/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["crates/prover", "crates/adapted_prover"]
members = ["crates/adapted_prover", "crates/prover", "crates/vm_runner"]
resolver = "2"

[workspace.package]
Expand All @@ -9,7 +9,8 @@ edition = "2021"
[workspace.dependencies]
bytemuck = { version = "1.16.3", features = ["derive"] }
cairo-lang-casm = "2.7.1"
cairo-vm = "1.0.1"
# TODO(yuval): Use an official version, not a specific commit.
cairo-vm = { git = "https://github.com/lambdaclass/cairo-vm", rev = "3fb0344c", features = ["mod_builtin"]}
clap = { version = "4.3.10", features = ["derive"] }
hex = "0.4.3"
itertools = "0.12.0"
Expand Down
56 changes: 1 addition & 55 deletions stwo_cairo_prover/crates/prover/Cargo.lock

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

18 changes: 8 additions & 10 deletions stwo_cairo_prover/crates/prover/src/input/plain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use itertools::Itertools;
use super::instructions::Instructions;
use super::mem::{MemConfig, MemoryBuilder};
use super::range_check_unit::RangeCheckUnitInput;
use super::vm_import::{MemEntry, TraceEntry};
use super::vm_import::MemEntry;
use super::{CairoInput, SegmentAddrs};

pub fn input_from_plain_casm(casm: Vec<cairo_lang_casm::instructions::Instruction>) -> CairoInput {
Expand All @@ -33,21 +33,23 @@ pub fn input_from_plain_casm(casm: Vec<cairo_lang_casm::instructions::Instructio
)
.expect("Program creation failed");

let mut runner =
CairoRunner::new(&program, LayoutName::plain, true, true).expect("Runner creation failed");
let mut runner = CairoRunner::new(&program, LayoutName::plain, None, true, true)
.expect("Runner creation failed");
runner.initialize(true).expect("Initialization failed");
runner
.run_until_pc(
(runner.program_base.unwrap() + program_len).unwrap(),
&mut BuiltinHintProcessor::new_empty(),
)
.expect("Run failed");
runner.relocate(true).unwrap();
input_from_finished_runner(runner)
}

pub fn input_from_finished_runner(mut runner: CairoRunner) -> CairoInput {
// TODO(yuval): consider returning a result instead of panicking...
/// Assumes memory and trace are already relocated. Otherwise panics.
pub fn input_from_finished_runner(runner: CairoRunner) -> CairoInput {
let program_len = runner.get_program().iter_data().count();
runner.relocate(true).expect("Relocation failed");
let mem = runner
.relocated_memory
.iter()
Expand All @@ -59,11 +61,7 @@ pub fn input_from_finished_runner(mut runner: CairoRunner) -> CairoInput {
})
});
let trace = runner.relocated_trace.unwrap();
let trace = trace.iter().map(|t| TraceEntry {
pc: t.pc as u64,
ap: t.ap as u64,
fp: t.fp as u64,
});
let trace = trace.iter().map(|t| t.clone().into());

let mut range_check9 = RangeCheckUnitInput::new();
let mem_config = MemConfig::default();
Expand Down
11 changes: 11 additions & 0 deletions stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::io::Read;
use std::path::Path;

use bytemuck::{bytes_of_mut, Pod, Zeroable};
use cairo_vm::vm::trace::trace_entry::RelocatedTraceEntry;
use json::{PrivateInput, PublicInput};
use thiserror::Error;

Expand Down Expand Up @@ -77,6 +78,16 @@ pub struct TraceEntry {
pub pc: u64,
}

impl From<RelocatedTraceEntry> for TraceEntry {
fn from(value: RelocatedTraceEntry) -> Self {
Self {
ap: value.ap as u64,
fp: value.fp as u64,
pc: value.pc as u64,
}
}
}

pub struct TraceIter<'a, R: Read>(pub &'a mut R);
impl<'a, R: Read> Iterator for TraceIter<'a, R> {
type Item = TraceEntry;
Expand Down
3 changes: 3 additions & 0 deletions stwo_cairo_prover/crates/vm_runner/Cargo.lock

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

16 changes: 16 additions & 0 deletions stwo_cairo_prover/crates/vm_runner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "stwo_vm_runner"
version = "0.1.0"
edition = "2021"

[dependencies]
cairo-vm.workspace = true
itertools.workspace = true
num-traits.workspace = true
serde.workspace = true
thiserror.workspace = true
clap.workspace = true
stwo_cairo_prover = { path = "../prover", version = "~0.1.0" }
# 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" }
133 changes: 133 additions & 0 deletions stwo_cairo_prover/crates/vm_runner/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use std::path::PathBuf;
use std::process::ExitCode;

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 stwo_cairo_prover::input::plain::input_from_finished_runner;
use stwo_cairo_prover::input::CairoInput;
use thiserror::Error;

// This struct is copied-then-modified from cairo-vm repo.
/// Command line arguments for stwo_vm_runner.
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
#[clap(value_parser, value_hint=ValueHint::FilePath)]
filename: PathBuf,
#[clap(long = "trace_file", value_parser)]
trace_file: Option<PathBuf>,
#[structopt(long = "print_output")]
print_output: bool,
#[structopt(long = "entrypoint", default_value = "main")]
entrypoint: String,
#[structopt(long = "memory_file")]
memory_file: Option<PathBuf>,
#[structopt(long = "proof_mode")]
proof_mode: bool,
#[structopt(long = "secure_run")]
secure_run: Option<bool>,
#[clap(long = "air_public_input", requires = "proof_mode")]
air_public_input: Option<String>,
#[clap(
long = "air_private_input",
requires_all = ["proof_mode", "trace_file", "memory_file"]
)]
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"]
)]
cairo_pie_output: Option<String>,
#[structopt(long = "allow_missing_builtins")]
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"]
)]
run_from_cairo_pie: bool,
}

#[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("The cairo program execution failed")]
Runner(#[from] CairoRunError),
}

fn main() -> ExitCode {
match run(std::env::args()) {
Ok(_) => {
println!("VM runner succeeded");
ExitCode::SUCCESS
}
Err(error) => {
println!("VM runner failed: {error}");
ExitCode::FAILURE
}
}
}

fn run(args: impl Iterator<Item = String>) -> Result<CairoInput, Error> {
let args = Args::try_parse_from(args)?;
let cairo_runner = run_vm(&args)?;
let cairo_input = adapt_vm_output_to_stwo(cairo_runner);
// TODO(yuval): serialize (here or in an outer function).

Ok(cairo_input)
}

// 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).
fn run_vm(args: &Args) -> Result<CairoRunner, Error> {
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(Error::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(Error::Runner(error));
}
};

Ok(cairo_runner)
}

/// Adapts the Cairo VM output to the input of Stwo.
/// Assumes memory and trace are already relocated. Otherwise panics.
fn adapt_vm_output_to_stwo(runner: CairoRunner) -> CairoInput {
input_from_finished_runner(runner)
}

0 comments on commit f43f285

Please sign in to comment.