diff --git a/Cargo.lock b/Cargo.lock index e5e17e7e231..a4219acc9f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1943,6 +1943,7 @@ dependencies = [ "starknet-types-core", "starknet_api", "thiserror 1.0.69", + "tokio", ] [[package]] @@ -12116,6 +12117,7 @@ name = "starknet_os" version = "0.15.0-rc.2" dependencies = [ "apollo_infra_utils", + "apollo_starknet_os_program", "ark-bls12-381", "ark-ff 0.4.2", "ark-poly 0.4.2", diff --git a/crates/apollo_starknet_os_program/Cargo.toml b/crates/apollo_starknet_os_program/Cargo.toml index 89f363497e7..51c9d1f578c 100644 --- a/crates/apollo_starknet_os_program/Cargo.toml +++ b/crates/apollo_starknet_os_program/Cargo.toml @@ -9,6 +9,7 @@ build = "build/main.rs" [features] dump_source_files = [] +test_programs = [] [lints] workspace = true @@ -24,6 +25,7 @@ thiserror.workspace = true [build-dependencies] apollo_infra_utils.workspace = true serde_json.workspace = true +tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } [dev-dependencies] apollo_infra_utils = { workspace = true, features = ["testing"] } diff --git a/crates/apollo_starknet_os_program/build/compile_program.rs b/crates/apollo_starknet_os_program/build/compile_program.rs index 987b7a8d3ac..dc65ab5eb86 100644 --- a/crates/apollo_starknet_os_program/build/compile_program.rs +++ b/crates/apollo_starknet_os_program/build/compile_program.rs @@ -3,8 +3,16 @@ use std::path::PathBuf; use apollo_infra_utils::cairo0_compiler::{compile_cairo0_program, Cairo0CompilerError}; use apollo_infra_utils::compile_time_cargo_manifest_dir; -fn compile_program(path_to_main_file: PathBuf) -> Vec { - match compile_cairo0_program(path_to_main_file, cairo_root_path()) { +pub async fn compile_and_output_program( + out_dir: PathBuf, + path_to_main_file_from_cairo_root: &str, + program_name: &str, +) { + println!("cargo::warning=Compiling {program_name} program..."); + let bytes = match compile_cairo0_program( + cairo_root_path().join(path_to_main_file_from_cairo_root), + cairo_root_path(), + ) { Ok(bytes) => bytes, Err(Cairo0CompilerError::Cairo0CompilerVersion(error)) => { panic!( @@ -15,19 +23,29 @@ fn compile_program(path_to_main_file: PathBuf) -> Vec { ) } Err(other_error) => { - panic!("Failed to compile the program. Error:\n{other_error}.") + panic!("Failed to compile the {program_name} program. Error:\n{other_error}.") } - } + }; + println!( + "cargo::warning=Done compiling {program_name}. Writing compiled bytes to output directory." + ); + let bytes_path = out_dir.join(format!("{program_name}_bytes")); + std::fs::write(&bytes_path, &bytes).unwrap_or_else(|error| { + panic!("Failed to write the compiled {program_name} bytes to {bytes_path:?}: {error}.") + }); } -fn cairo_root_path() -> PathBuf { - PathBuf::from(compile_time_cargo_manifest_dir!()).join("src/cairo") -} - -pub fn compile_starknet_os() -> Vec { - compile_program(cairo_root_path().join("starkware/starknet/core/os/os.cairo")) +#[cfg(feature = "test_programs")] +pub async fn compile_test_contracts(out_dir: PathBuf) { + let mut task_set = tokio::task::JoinSet::new(); + task_set.spawn(compile_and_output_program( + out_dir, + "starkware/starknet/core/os/state/aliases_test.cairo", + "aliases_test", + )); + task_set.join_all().await; } -pub fn compile_starknet_aggregator() -> Vec { - compile_program(cairo_root_path().join("starkware/starknet/core/aggregator/main.cairo")) +fn cairo_root_path() -> PathBuf { + PathBuf::from(compile_time_cargo_manifest_dir!()).join("src/cairo") } diff --git a/crates/apollo_starknet_os_program/build/main.rs b/crates/apollo_starknet_os_program/build/main.rs index bee35be5fed..446ea86aa5f 100644 --- a/crates/apollo_starknet_os_program/build/main.rs +++ b/crates/apollo_starknet_os_program/build/main.rs @@ -7,23 +7,25 @@ mod dump_source; /// Build script for the `apollo_starknet_os_program` crate. /// Recompiles the OS program if the source files change. /// Optionally, also exposes all source cairo files in a mapping from file path to contents. -fn main() { +#[tokio::main] +async fn main() { let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR not set.")); #[cfg(feature = "dump_source_files")] dump_source::dump_source_files(&out_dir.join("cairo_files_map.json")); - println!("cargo::warning=Compiling Starknet OS program..."); - let starknet_os_bytes = compile_program::compile_starknet_os(); - println!("cargo::warning=Done. Writing compiled bytes to output directory."); - let starknet_os_bytes_path = out_dir.join("starknet_os_bytes"); - std::fs::write(&starknet_os_bytes_path, &starknet_os_bytes) - .expect("Failed to write the compiled OS bytes to the output directory."); - - println!("cargo::warning=Compiling Starknet aggregator program..."); - let starknet_aggregator_bytes = compile_program::compile_starknet_aggregator(); - println!("cargo::warning=Done. Writing compiled bytes to output directory."); - let starknet_aggregator_bytes_path = out_dir.join("starknet_aggregator_bytes"); - std::fs::write(&starknet_aggregator_bytes_path, &starknet_aggregator_bytes) - .expect("Failed to write the compiled aggregator bytes to the output directory."); + let mut task_set = tokio::task::JoinSet::new(); + #[cfg(feature = "test_programs")] + task_set.spawn(compile_program::compile_test_contracts(out_dir.clone())); + task_set.spawn(compile_program::compile_and_output_program( + out_dir.clone(), + "starkware/starknet/core/os/os.cairo", + "starknet_os", + )); + task_set.spawn(compile_program::compile_and_output_program( + out_dir, + "starkware/starknet/core/aggregator/main.cairo", + "starknet_aggregator", + )); + task_set.join_all().await; } diff --git a/crates/apollo_starknet_os_program/src/lib.rs b/crates/apollo_starknet_os_program/src/lib.rs index e8e02cbd11f..4f2aac72579 100644 --- a/crates/apollo_starknet_os_program/src/lib.rs +++ b/crates/apollo_starknet_os_program/src/lib.rs @@ -9,6 +9,8 @@ use crate::program_hash::ProgramHashes; #[cfg(test)] mod constants_test; pub mod program_hash; +#[cfg(feature = "test_programs")] +pub mod test_programs; #[cfg(feature = "dump_source_files")] pub static CAIRO_FILES_MAP: LazyLock> = LazyLock::new(|| { diff --git a/crates/apollo_starknet_os_program/src/test_programs.rs b/crates/apollo_starknet_os_program/src/test_programs.rs new file mode 100644 index 00000000000..9bafd1de0e8 --- /dev/null +++ b/crates/apollo_starknet_os_program/src/test_programs.rs @@ -0,0 +1,2 @@ +pub const ALIASES_TEST_BYTES: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/aliases_test_bytes")); diff --git a/crates/starknet_committer_and_os_cli/Cargo.toml b/crates/starknet_committer_and_os_cli/Cargo.toml index 710eb9d91ea..f9d71211989 100644 --- a/crates/starknet_committer_and_os_cli/Cargo.toml +++ b/crates/starknet_committer_and_os_cli/Cargo.toml @@ -18,8 +18,9 @@ tempfile.workspace = true # TODO(Amos): Add `testing` feature and move Python test dependencies under it. [dependencies] -# The 'dump_source_files' feature should be moved under `testing` feature, when it exists. -apollo_starknet_os_program = { workspace = true, features = ["dump_source_files"] } +# The 'dump_source_files' and 'test_programs' features should be moved under `testing` feature, when +# it exists. +apollo_starknet_os_program = { workspace = true, features = ["dump_source_files", "test_programs"] } blake2s.workspace = true cairo-lang-starknet-classes.workspace = true cairo-vm = { workspace = true, features = [ diff --git a/crates/starknet_committer_and_os_cli/src/os_cli/commands.rs b/crates/starknet_committer_and_os_cli/src/os_cli/commands.rs index e0eeea03e81..c819f98ae6e 100644 --- a/crates/starknet_committer_and_os_cli/src/os_cli/commands.rs +++ b/crates/starknet_committer_and_os_cli/src/os_cli/commands.rs @@ -1,6 +1,6 @@ -use std::fs; use std::path::Path; +use apollo_starknet_os_program::test_programs::ALIASES_TEST_BYTES; use apollo_starknet_os_program::{ AGGREGATOR_PROGRAM_BYTES, CAIRO_FILES_MAP, @@ -25,9 +25,6 @@ use crate::shared_utils::read::{load_input, write_to_file}; #[derive(Deserialize, Debug)] /// Input to the os runner. pub(crate) struct Input { - // A path to a compiled program that its hint set should be a subset of those defined in - // starknet-os. - pub compiled_os_path: String, pub layout: LayoutName, pub os_hints: OsHints, pub cairo_pie_zip_path: String, @@ -76,15 +73,11 @@ pub fn validate_input(os_input: &StarknetOsInput) { } pub fn parse_and_run_os(input_path: String, output_path: String) { - let Input { compiled_os_path, layout, os_hints, cairo_pie_zip_path } = load_input(input_path); + let Input { layout, os_hints, cairo_pie_zip_path } = load_input(input_path); validate_input(&os_hints.os_input); - // Load the compiled_os from the compiled_os_path. - let compiled_os = - fs::read(Path::new(&compiled_os_path)).expect("Failed to read compiled_os file"); - let StarknetOsRunnerOutput { os_output, cairo_pie, unused_hints } = - run_os_stateless(&compiled_os, layout, os_hints) + run_os_stateless(layout, os_hints) .unwrap_or_else(|err| panic!("OS run failed. Error: {}", err)); serialize_os_runner_output( &OsCliOutput { os_output, unused_hints }, @@ -115,6 +108,7 @@ pub(crate) fn dump_source_files(output_path: String) { pub(crate) fn dump_program(output_path: String, program: ProgramToDump) { let bytes = match program { ProgramToDump::Aggregator => AGGREGATOR_PROGRAM_BYTES, + ProgramToDump::AliasesTest => ALIASES_TEST_BYTES, ProgramToDump::Os => OS_PROGRAM_BYTES, }; // Dumping the `Program` struct won't work - it is not deserializable via cairo-lang's Program diff --git a/crates/starknet_committer_and_os_cli/src/os_cli/run_os_cli.rs b/crates/starknet_committer_and_os_cli/src/os_cli/run_os_cli.rs index a4c50835f0f..02b9841d2d1 100644 --- a/crates/starknet_committer_and_os_cli/src/os_cli/run_os_cli.rs +++ b/crates/starknet_committer_and_os_cli/src/os_cli/run_os_cli.rs @@ -28,6 +28,7 @@ pub struct OsCliCommand { #[serde(rename_all = "kebab-case")] pub enum ProgramToDump { Aggregator, + AliasesTest, Os, } diff --git a/crates/starknet_os/Cargo.toml b/crates/starknet_os/Cargo.toml index 9177e1db6af..a8f09659749 100644 --- a/crates/starknet_os/Cargo.toml +++ b/crates/starknet_os/Cargo.toml @@ -17,6 +17,7 @@ testing = ["blockifier/testing", "starknet_patricia/testing"] [dependencies] apollo_infra_utils.workspace = true +apollo_starknet_os_program.workspace = true ark-bls12-381.workspace = true ark-ff.workspace = true ark-poly.workspace = true diff --git a/crates/starknet_os/src/hints/enum_definition.rs b/crates/starknet_os/src/hints/enum_definition.rs index bb4fad4dc68..29e29cb14b4 100644 --- a/crates/starknet_os/src/hints/enum_definition.rs +++ b/crates/starknet_os/src/hints/enum_definition.rs @@ -1081,6 +1081,7 @@ segments.write_arg(ids.sha256_ptr_end, padding)"#} indoc! {r#" if execution_helper.debug_mode: # Validate the predicted gas cost. + # TODO(Yoni, 1/1/2025): remove this check once Cairo 0 is not supported. actual = ids.remaining_gas - ids.entry_point_return_values.gas_builtin predicted = execution_helper.call_info.gas_consumed if execution_helper.call_info.tracked_resource.is_sierra_gas(): @@ -1408,6 +1409,7 @@ segments.write_arg(ids.sha256_ptr_end, padding)"#} onchain_data_start = ids.da_start onchain_data_size = ids.output_ptr - onchain_data_start + # TODO(Yoni,20/07/2023): Take from input. max_page_size = 3800 n_pages = div_ceil(onchain_data_size, max_page_size) for i in range(n_pages): diff --git a/crates/starknet_os/src/runner.rs b/crates/starknet_os/src/runner.rs index db795b11110..c764869e577 100644 --- a/crates/starknet_os/src/runner.rs +++ b/crates/starknet_os/src/runner.rs @@ -1,7 +1,7 @@ +use apollo_starknet_os_program::OS_PROGRAM; use blockifier::state::state_api::StateReader; use cairo_vm::cairo_run::CairoRunConfig; use cairo_vm::types::layout_name::LayoutName; -use cairo_vm::types::program::Program; use cairo_vm::vm::errors::vm_exception::VmException; use cairo_vm::vm::runners::cairo_runner::CairoRunner; @@ -17,7 +17,6 @@ use crate::io::os_output::{get_run_output, StarknetOsRunnerOutput}; #[allow(clippy::result_large_err)] pub fn run_os( - compiled_os: &[u8], layout: LayoutName, OsHints { os_hints_config, @@ -36,12 +35,9 @@ pub fn run_os( CairoRunConfig { layout, relocate_mem: true, trace_enabled: true, ..Default::default() }; let allow_missing_builtins = cairo_run_config.allow_missing_builtins.unwrap_or(false); - // Load the Starknet OS Program. - let os_program = Program::from_bytes(compiled_os, Some(cairo_run_config.entrypoint))?; - // Init cairo runner. let mut cairo_runner = CairoRunner::new( - &os_program, + &OS_PROGRAM, cairo_run_config.layout, cairo_run_config.dynamic_layout_params, cairo_run_config.proof_mode, @@ -58,7 +54,7 @@ pub fn run_os( // Create the hint processor. let mut snos_hint_processor = SnosHintProcessor::new( - &os_program, + &OS_PROGRAM, os_hints_config, os_block_inputs.iter().collect(), cached_state_inputs, @@ -112,10 +108,9 @@ pub fn run_os( /// not pre-loaded as part of the input. #[allow(clippy::result_large_err)] pub fn run_os_stateless( - compiled_os: &[u8], layout: LayoutName, os_hints: OsHints, ) -> Result { let n_blocks = os_hints.os_input.os_block_inputs.len(); - run_os(compiled_os, layout, os_hints, vec![PanickingStateReader; n_blocks]) + run_os(layout, os_hints, vec![PanickingStateReader; n_blocks]) }