Skip to content

Commit

Permalink
Merge pull request #53 from zksecurity/dynamic-layout
Browse files Browse the repository at this point in the history
Add dynamic layout support for cairo0 programs
  • Loading branch information
mellowcroc authored Feb 12, 2025
2 parents a5937a6 + d0d003e commit b849781
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 99 deletions.
133 changes: 50 additions & 83 deletions src/cairo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,19 @@ pub fn run_cairo(
args: &ProveArgs,
tmp_dir: &tempfile::TempDir,
) -> Result<CairoRunResult, anyhow::Error> {
let filename = args.cairo_program.file_stem().unwrap().to_str().unwrap();

match args.cairo_version {
CairoVersion::cairo0 => run_cairo0(args, tmp_dir).map_err(Into::into),
CairoVersion::cairo1 => run_cairo1(args, tmp_dir),
CairoVersion::cairo0 => {
let runner = run_cairo0(args, tmp_dir)?;
let file_paths = write_to_files(&runner, tmp_dir, filename)?;
Ok(file_paths)
}
CairoVersion::cairo1 => {
let runner = run_cairo1(args, tmp_dir)?;
let file_paths = write_to_files(&runner, tmp_dir, filename)?;
Ok(file_paths)
}
}
}

Expand All @@ -113,14 +123,7 @@ pub fn run_cairo(
pub fn run_cairo0(
prove_args: &ProveArgs,
tmp_dir: &tempfile::TempDir,
) -> Result<CairoRunResult, anyhow::Error> {
let filename = prove_args
.cairo_program
.file_stem()
.unwrap()
.to_str()
.unwrap();

) -> Result<CairoRunner, anyhow::Error> {
let program = Program::from_file(&prove_args.cairo_program, Some("main"))?;
let program_input = if let Some(program_input_file) = prove_args.program_input_file.clone() {
let program_input_file_str = std::fs::read_to_string(program_input_file)?;
Expand Down Expand Up @@ -172,21 +175,39 @@ pub fn run_cairo0(
))),
);

let cairo_run_config = CairoRunConfig {
entrypoint: "main",
trace_enabled: true,
relocate_mem: true,
layout: get_layout(&prove_args.layout),
proof_mode: true,
secure_run: None,
disable_trace_padding: false,
allow_missing_builtins: None,
dynamic_layout_params: None,
let cairo_run_config = match &prove_args.layout {
LayoutName::dynamic | LayoutName::automatic => {
let cairo_layout_params_file = tmp_dir.path().join("cairo_layout_params_file.json");
std::fs::write(cairo_layout_params_file.clone(), DYNAMIC_LAYOUT)?;
CairoRunConfig {
entrypoint: "main",
trace_enabled: true,
relocate_mem: true,
layout: cairo_vm::types::layout_name::LayoutName::dynamic,
proof_mode: true,
secure_run: None,
disable_trace_padding: false,
allow_missing_builtins: None,
dynamic_layout_params: Some(CairoLayoutParams::from_file(
cairo_layout_params_file.as_path(),
)?),
}
}
layout => CairoRunConfig {
entrypoint: "main",
trace_enabled: true,
relocate_mem: true,
layout: get_layout(layout),
proof_mode: true,
secure_run: None,
disable_trace_padding: false,
allow_missing_builtins: None,
dynamic_layout_params: None,
},
};

let runner = cairo_run_program(&program, &cairo_run_config, &mut hint_processor)?;
let file_paths = write_to_files(&runner, tmp_dir, filename)?;
Ok(file_paths)
Ok(runner)
}

/// Runs a Cairo 1 program and generates the necessary outputs for proving
Expand All @@ -206,14 +227,7 @@ pub fn run_cairo0(
pub fn run_cairo1(
prove_args: &ProveArgs,
tmp_dir: &tempfile::TempDir,
) -> Result<CairoRunResult, anyhow::Error> {
let filename = prove_args
.cairo_program
.file_stem()
.unwrap()
.to_str()
.unwrap();

) -> Result<CairoRunner, anyhow::Error> {
let args = if let Some(program_input_file) = &prove_args.program_input_file {
let file_content = std::fs::read_to_string(program_input_file)?;
process_args(&file_content).unwrap()
Expand Down Expand Up @@ -285,8 +299,7 @@ pub fn run_cairo1(
cairo_run_program_cairo1(&sierra_program, cairo_run_config)?;
println!("Cairo1 program output: {:?}", serialized_output);

let file_paths = write_to_files(&runner, tmp_dir, filename)?;
Ok(file_paths)
Ok(runner)
}

pub fn get_cairo_runner(
Expand All @@ -304,60 +317,14 @@ pub fn get_cairo_runner(
// write to "cairo_layout_params_file.json"
std::fs::write(cairo_layout_params_file.clone(), DYNAMIC_LAYOUT)?;

let args = if let Some(program_input_file) = &prove_args.program_input_file {
let file_content = std::fs::read_to_string(program_input_file)?;
process_args(&file_content).unwrap()
} else {
prove_args.program_input.clone()
};
let cairo_run_config = Cairo1RunConfig {
proof_mode: true,
serialize_output: true,
relocate_mem: true,
layout: cairo_vm::types::layout_name::LayoutName::dynamic,
trace_enabled: true,
args: &args.0,
finalize_builtins: true,
append_return_values: true,
dynamic_layout_params: Some(CairoLayoutParams::from_file(
cairo_layout_params_file.as_path(),
)?),
};

// Try to parse the file as a sierra program
let file = std::fs::read(&prove_args.cairo_program)?;
let sierra_program = match serde_json::from_slice(&file) {
Ok(program) => program,
Err(_) => {
// If it fails, try to compile it as a cairo program
let compiler_config = CompilerConfig {
replace_ids: true,
..CompilerConfig::default()
};
let mut db = RootDatabase::builder()
.skip_auto_withdraw_gas()
.build()
.unwrap();
println!("Running Cairo again to get dynamic params...");

let config: Config = serde_json::from_str(CONFIG).expect("Failed to parse config file");
let download_dir = Path::new(env!("HOME")).join(&config.download_dir);
let corelib_dir = download_dir.join("corelib");
if !corelib_dir.exists() {
anyhow::bail!("Corelib directory does not exist: {:?}", corelib_dir);
}
init_dev_corelib(&mut db, corelib_dir.join("src"));
let main_crate_ids = setup_project(&mut db, &prove_args.cairo_program).unwrap();
let sierra_program_with_dbg =
compile_prepared_db(&db, main_crate_ids, compiler_config).unwrap();

sierra_program_with_dbg.program
}
let runner = if prove_args.cairo_version == CairoVersion::cairo1 {
run_cairo1(prove_args, tmp_dir).unwrap()
} else {
run_cairo0(prove_args, tmp_dir).unwrap()
};

let (runner, _, serialized_output) =
cairo_run_program_cairo1(&sierra_program, cairo_run_config)?;
println!("Cairo1 program output: {:?}", serialized_output);

Ok(runner)
}

Expand Down
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn main() -> anyhow::Result<()> {
});
match result {
Ok(_) => {
println!("Created proof at {:?}", args.output);
cleanup_tmp_files(&tmp_dir);
Ok(())
}
Expand Down Expand Up @@ -61,6 +62,7 @@ fn main() -> anyhow::Result<()> {
});
match result {
Ok(_) => {
println!("Created proof at {:?}", args.output);
cleanup_tmp_files(&tmp_dir);
Ok(())
}
Expand Down
24 changes: 8 additions & 16 deletions tests/test_run.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rstest::{fixture, rstest};
use serde::{Deserialize, Serialize};
use std::{path::Path, str::FromStr};
use stone_cli::cairo::run_cairo;
use stone_cli::utils::process_args;
use stone_cli::utils::FuncArgs;
use stone_cli::{
Expand All @@ -9,7 +10,6 @@ use stone_cli::{
SerializeArgs, StoneVersion, VerifyArgs,
},
bootloader::run_bootloader,
cairo::{run_cairo0, run_cairo1},
config::{ProverConfig, ProverParametersConfig},
prover::run_stone_prover,
serialize::serialize_proof,
Expand Down Expand Up @@ -202,7 +202,7 @@ fn test_run_cairo0_success(
bench_memory: None,
};

match run_cairo0(&prove_args, &tmp_dir) {
match run_cairo(&prove_args, &tmp_dir) {
Ok(_) => {
println!("Successfully ran cairo0");
}
Expand Down Expand Up @@ -240,7 +240,7 @@ fn test_run_cairo1_fail(
stone_version: StoneVersion::V6,
bench_memory: None,
};
match run_cairo1(&prove_args, &tmp_dir) {
match run_cairo(&prove_args, &tmp_dir) {
Ok(result) => panic!(
"Expected an error but got a successful result: {:?}",
result
Expand Down Expand Up @@ -316,7 +316,7 @@ fn test_run_cairo1_success(
stone_version: StoneVersion::V6,
bench_memory: None,
};
match run_cairo1(&prove_args, &tmp_dir) {
match run_cairo(&prove_args, &tmp_dir) {
Ok(result) => println!("Successfully ran cairo1: {:?}", result),
Err(e) => panic!("Expected a successful result but got an error: {:?}", e),
}
Expand Down Expand Up @@ -364,7 +364,7 @@ fn test_run_cairo1_with_input_file(
bench_memory: None,
};

match run_cairo1(&prove_args, &tmp_dir) {
match run_cairo(&prove_args, &tmp_dir) {
Ok(_) => {
println!("Successfully ran cairo1 with input file");
}
Expand Down Expand Up @@ -407,7 +407,7 @@ fn test_run_cairo1_with_inputs(
bench_memory: None,
};

match run_cairo1(&prove_args, &tmp_dir) {
match run_cairo(&prove_args, &tmp_dir) {
Ok(_) => {
println!("Successfully ran cairo1 with input file");
}
Expand Down Expand Up @@ -458,11 +458,7 @@ fn test_run_cairo_e2e_linux(
stone_version: StoneVersion::V6,
};

match cairo_version {
CairoVersion::cairo0 => run_cairo0(&prove_args, &tmp_dir).expect("Failed to run cairo0"),
CairoVersion::cairo1 => run_cairo1(&prove_args, &tmp_dir).expect("Failed to run cairo1"),
};

run_cairo(&prove_args, &tmp_dir).expect("Failed to run cairo");
let filename = program_file.file_stem().unwrap().to_str().unwrap();
let air_public_input = tmp_dir
.path()
Expand Down Expand Up @@ -554,11 +550,7 @@ fn test_run_cairo_e2e_macos(
stone_version,
};

match cairo_version {
CairoVersion::cairo0 => run_cairo0(&prove_args, &tmp_dir).expect("Failed to run cairo0"),
CairoVersion::cairo1 => run_cairo1(&prove_args, &tmp_dir).expect("Failed to run cairo1"),
};

run_cairo(&prove_args, &tmp_dir).expect("Failed to run cairo");
// Skip proving on macOS as it takes too long
run_stone_verifier(verify_args).expect("Failed to run stone verifier");
check_tmp_files(&tmp_dir, &program_file);
Expand Down

0 comments on commit b849781

Please sign in to comment.