diff --git a/crates/cairo-program-runner-lib/Cargo.toml b/crates/cairo-program-runner-lib/Cargo.toml index fbda2f02..3d2802fa 100644 --- a/crates/cairo-program-runner-lib/Cargo.toml +++ b/crates/cairo-program-runner-lib/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] +anyhow.workspace = true bincode.workspace = true cairo-vm.workspace = true cairo-lang-executable.workspace = true @@ -17,6 +18,7 @@ num-traits.workspace = true regex.workspace = true serde.workspace = true serde_json.workspace = true +sonic-rs.workspace = true starknet-crypto.workspace = true starknet-types-core.workspace = true thiserror.workspace = true diff --git a/crates/cairo-program-runner-lib/src/utils.rs b/crates/cairo-program-runner-lib/src/utils.rs index a39f0172..690771e6 100644 --- a/crates/cairo-program-runner-lib/src/utils.rs +++ b/crates/cairo-program-runner-lib/src/utils.rs @@ -9,6 +9,8 @@ use cairo_vm::{ errors::program_errors::ProgramError, layout::CairoLayoutParams, layout_name::LayoutName, program::Program, }, + vm::runners::cairo_runner::CairoRunner, + Felt252, }; use crate::types::RunMode; @@ -115,3 +117,18 @@ pub fn get_cairo_run_config( .create_config() }) } + +/// Write the program output to the specified output path as Felt252 values. +pub fn write_output_to_file(runner: &mut CairoRunner, output_path: PathBuf) -> anyhow::Result<()> { + let mut output_buffer = String::new(); + runner.vm.write_output(&mut output_buffer)?; + let output_lines = output_buffer + .lines() + .map(|line| { + Felt252::from_dec_str(line) + .map_err(|_| anyhow::anyhow!("Failed to parse output line as Felt decimal: {line}")) + }) + .collect::, anyhow::Error>>()?; + std::fs::write(&output_path, sonic_rs::to_string_pretty(&output_lines)?)?; + Ok(()) +} diff --git a/crates/cairo-program-runner/src/bin/cairo_program_runner/main.rs b/crates/cairo-program-runner/src/bin/cairo_program_runner/main.rs index 951ebeb6..bc60e7eb 100644 --- a/crates/cairo-program-runner/src/bin/cairo_program_runner/main.rs +++ b/crates/cairo-program-runner/src/bin/cairo_program_runner/main.rs @@ -4,12 +4,14 @@ use std::io::{self, Write}; use std::path::PathBuf; use bincode::enc::write::Writer; -use cairo_program_runner_lib::utils::{get_cairo_run_config, get_program, get_program_input}; +use cairo_program_runner_lib::utils::{ + get_cairo_run_config, get_program, get_program_input, write_output_to_file, +}; use cairo_vm::types::layout_name::LayoutName; use cairo_program_runner_lib::cairo_run_program; +use cairo_vm::cairo_run; use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; -use cairo_vm::{cairo_run, Felt252}; use clap::Parser; use tempfile::NamedTempFile; @@ -167,16 +169,7 @@ fn main() -> Result<(), Box> { // Handle program output file if specified if let Some(outputs_file) = args.outputs_file { - let mut output_buffer = String::new(); - runner.vm.write_output(&mut output_buffer)?; - let output_lines = output_buffer - .lines() - .map(|line| { - Felt252::from_dec_str(line) - .map_err(|_| format!("Failed to parse output line as Felt decimal: {line}")) - }) - .collect::, _>>()?; - std::fs::write(outputs_file, serde_json::to_string_pretty(&output_lines)?)?; + write_output_to_file(&mut runner, outputs_file)?; } // Handle execution resources file if specified diff --git a/crates/stwo_run_and_prove/src/main.rs b/crates/stwo_run_and_prove/src/main.rs index 74b8f604..3a4cd64a 100644 --- a/crates/stwo_run_and_prove/src/main.rs +++ b/crates/stwo_run_and_prove/src/main.rs @@ -1,14 +1,14 @@ use anyhow::Result; use cairo_air::utils::ProofFormat; use cairo_program_runner_lib::cairo_run_program; -use cairo_program_runner_lib::utils::{get_cairo_run_config, get_program, get_program_input}; -use cairo_vm::Felt252; +use cairo_program_runner_lib::utils::{ + get_cairo_run_config, get_program, get_program_input, write_output_to_file, +}; use cairo_vm::types::errors::program_errors::ProgramError; use cairo_vm::types::layout_name::LayoutName; use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; use cairo_vm::vm::errors::runner_errors::RunnerError; use cairo_vm::vm::errors::vm_errors::VirtualMachineError; -use cairo_vm::vm::runners::cairo_runner::CairoRunner; use clap::Parser; #[cfg(test)] use mockall::automock; @@ -87,8 +87,6 @@ enum StwoRunAndProveError { Serializing(#[from] sonic_rs::error::Error), #[error(transparent)] VM(#[from] VirtualMachineError), - #[error("Failed to parse output line as Felt decimal.")] - OutputParsing, #[error(transparent)] Anyhow(#[from] anyhow::Error), } @@ -167,7 +165,7 @@ fn stwo_run_and_prove( .map_err(|e| StwoRunAndProveError::Program(e, program_path))?; let program_input = get_program_input(&program_input) .map_err(|e| StwoRunAndProveError::PathIO(e, program_input.unwrap_or_default()))?; - let runner = cairo_run_program(&program, program_input, cairo_run_config)?; + let mut runner = cairo_run_program(&program, program_input, cairo_run_config)?; let prover_input = adapt(&runner)?; let result = prove(prover_input.clone(), prove_config, prover); @@ -187,7 +185,8 @@ fn stwo_run_and_prove( if let Some(output_path) = program_output && result.is_ok() { - write_output_to_file(runner, output_path)?; + info!("Saving program output to: {:?}", output_path); + write_output_to_file(&mut runner, output_path)?; } result @@ -262,28 +261,6 @@ impl ProverTrait for StwoProverEntryPoint { } } -/// Write the program output to the specified output path as Felt252 values. -fn write_output_to_file( - mut runner: CairoRunner, - output_path: PathBuf, -) -> Result<(), StwoRunAndProveError> { - info!("Saving program output to: {:?}", output_path); - // TODO(Nitsan): move this function to cairo_program_runner_lib or a new utils lib, - // and call it from here and from cairo_program_runner. - - let mut output_buffer = String::new(); - runner.vm.write_output(&mut output_buffer)?; - let output_lines = output_buffer - .lines() - .map(|line: &str| { - Felt252::from_dec_str(line).map_err(|_| StwoRunAndProveError::OutputParsing) - }) - .collect::, _>>()?; - std::fs::write(&output_path, sonic_rs::to_string_pretty(&output_lines)?) - .map_err(|e| StwoRunAndProveError::PathIO(e, output_path))?; - Ok(()) -} - fn file_empty(path: &PathBuf) -> std::io::Result { let metadata = fs::metadata(path)?; Ok(metadata.len() == 0) @@ -303,6 +280,7 @@ fn file_missing_or_empty(path: &PathBuf) -> std::io::Result { #[cfg(test)] mod tests { use super::*; + use cairo_vm::Felt252; use ctor::ctor; use serde_json::Value; use stwo_cairo_utils::logging_utils::init_logging;