From a8c4ff3d73ab3af9b6a062fabca3940c6c2f12cf Mon Sep 17 00:00:00 2001 From: Arni Hod Date: Sun, 4 Aug 2024 09:54:57 +0300 Subject: [PATCH] feat: use the installed starknet-sierra-compile crate to compile --- Cargo.lock | 1 + crates/starknet_sierra_compile/Cargo.toml | 1 + .../src/cairo_lang_compiler.rs | 4 -- .../src/command_line_compiler.rs | 48 +++++++++++++++++++ .../src/compile_test.rs | 40 ++++++++++++---- crates/starknet_sierra_compile/src/errors.rs | 10 +++- crates/starknet_sierra_compile/src/lib.rs | 5 ++ 7 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 crates/starknet_sierra_compile/src/command_line_compiler.rs diff --git a/Cargo.lock b/Cargo.lock index 061872a97b..37f3879b84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9121,6 +9121,7 @@ dependencies = [ "serde_json", "starknet-types-core", "starknet_api", + "tempfile", "thiserror", "validator", ] diff --git a/crates/starknet_sierra_compile/Cargo.toml b/crates/starknet_sierra_compile/Cargo.toml index 9a711c69a1..45760ae5ef 100644 --- a/crates/starknet_sierra_compile/Cargo.toml +++ b/crates/starknet_sierra_compile/Cargo.toml @@ -17,6 +17,7 @@ serde.workspace = true serde_json.workspace = true starknet-types-core.workspace = true starknet_api.workspace = true +tempfile.workspace = true thiserror.workspace = true validator.workspace = true diff --git a/crates/starknet_sierra_compile/src/cairo_lang_compiler.rs b/crates/starknet_sierra_compile/src/cairo_lang_compiler.rs index 3bdd90eda9..0c5d417cf6 100644 --- a/crates/starknet_sierra_compile/src/cairo_lang_compiler.rs +++ b/crates/starknet_sierra_compile/src/cairo_lang_compiler.rs @@ -8,10 +8,6 @@ use crate::config::SierraToCasmCompilationConfig; use crate::errors::CompilationUtilError; use crate::SierraToCasmCompiler; -#[cfg(test)] -#[path = "compile_test.rs"] -pub mod compile_test; - /// A compiler that compiles Sierra programs to Casm. Uses the code from the /// `cairo_lang_starknet_classes` crate. #[derive(Clone)] diff --git a/crates/starknet_sierra_compile/src/command_line_compiler.rs b/crates/starknet_sierra_compile/src/command_line_compiler.rs new file mode 100644 index 0000000000..f454aabba1 --- /dev/null +++ b/crates/starknet_sierra_compile/src/command_line_compiler.rs @@ -0,0 +1,48 @@ +use std::io::Write; +use std::process::Command; + +use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; +use cairo_lang_starknet_classes::contract_class::ContractClass; +use tempfile::NamedTempFile; + +use crate::config::SierraToCasmCompilationConfig; +use crate::errors::CompilationUtilError; +use crate::SierraToCasmCompiler; + +#[derive(Clone)] +pub struct CommandLineCompiler { + pub config: SierraToCasmCompilationConfig, +} + +impl SierraToCasmCompiler for CommandLineCompiler { + fn compile_sierra_to_casm( + &self, + contract_class: ContractClass, + ) -> Result { + // Create a temporary file to store the Sierra contract class. + let serialized_contract_class = serde_json::to_string(&contract_class)?; + + let mut temp_file = NamedTempFile::new()?; + temp_file.write_all(serialized_contract_class.as_bytes())?; + let temp_file_path = temp_file.path().to_str().ok_or(CompilationUtilError::IoError( + std::io::Error::new(std::io::ErrorKind::NotFound, "Failed to get temporary file path"), + ))?; + + // Compile the Sierra contract class to Casm. + let mut command = Command::new("starknet-sierra-compile"); + command.arg(temp_file_path); + + command.arg("--add-pythonic-hints"); + command.args(["--max-bytecode-size", &self.config.max_bytecode_size.to_string()]); + + let compile_output = command.output()?; + + if !compile_output.status.success() { + let stderr_output = String::from_utf8(compile_output.stderr) + .unwrap_or("Failed to get stderr output".into()); + return Err(CompilationUtilError::CompilationError(stderr_output)); + }; + + Ok(serde_json::from_slice::(&compile_output.stdout)?) + } +} diff --git a/crates/starknet_sierra_compile/src/compile_test.rs b/crates/starknet_sierra_compile/src/compile_test.rs index a70b778877..ea42a946ed 100644 --- a/crates/starknet_sierra_compile/src/compile_test.rs +++ b/crates/starknet_sierra_compile/src/compile_test.rs @@ -4,20 +4,28 @@ use std::path::Path; use assert_matches::assert_matches; use cairo_lang_starknet_classes::allowed_libfuncs::AllowedLibfuncsError; use mempool_test_utils::{get_absolute_path, FAULTY_ACCOUNT_CLASS_FILE, TEST_FILES_FOLDER}; -use rstest::{fixture, rstest}; +use rstest::rstest; -use crate::cairo_lang_compiler::{CairoLangCompiler, CompilationUtilError}; +use crate::cairo_lang_compiler::CairoLangCompiler; +use crate::command_line_compiler::CommandLineCompiler; use crate::config::SierraToCasmCompilationConfig; +use crate::errors::CompilationUtilError; use crate::test_utils::contract_class_from_file; use crate::SierraToCasmCompiler; -#[fixture] -fn compiler() -> impl SierraToCasmCompiler { - CairoLangCompiler { config: SierraToCasmCompilationConfig { max_bytecode_size: 81920 } } -} +const SIERRA_TO_CASM_COMPILATION_CONFIG: SierraToCasmCompilationConfig = + SierraToCasmCompilationConfig { max_bytecode_size: 81920 }; + +const CAIRO_LANG_COMPILER: CairoLangCompiler = + CairoLangCompiler { config: SIERRA_TO_CASM_COMPILATION_CONFIG }; +const COMMAND_LINE_COMPILER: CommandLineCompiler = + CommandLineCompiler { config: SIERRA_TO_CASM_COMPILATION_CONFIG }; +// TODO: use the other compiler as well. #[rstest] -fn test_compile_sierra_to_casm(compiler: impl SierraToCasmCompiler) { +#[case::cairo_lang_compiler(&CAIRO_LANG_COMPILER)] +#[case::command_line_compiler(&COMMAND_LINE_COMPILER)] +fn test_compile_sierra_to_casm(#[case] compiler: &impl SierraToCasmCompiler) { env::set_current_dir(get_absolute_path(TEST_FILES_FOLDER)).expect("Failed to set current dir."); let sierra_path = Path::new(FAULTY_ACCOUNT_CLASS_FILE); let expected_casm_contract_length = 72304; @@ -31,7 +39,8 @@ fn test_compile_sierra_to_casm(compiler: impl SierraToCasmCompiler) { // TODO(Arni, 1/5/2024): Add a test for panic result test. #[rstest] -fn test_negative_flow_compile_sierra_to_casm(compiler: impl SierraToCasmCompiler) { +#[case::cairo_lang_compiler(&CAIRO_LANG_COMPILER)] +fn test_negative_flow_compile_sierra_to_casm(#[case] compiler: &impl SierraToCasmCompiler) { env::set_current_dir(get_absolute_path(TEST_FILES_FOLDER)).expect("Failed to set current dir."); let sierra_path = Path::new(FAULTY_ACCOUNT_CLASS_FILE); @@ -45,3 +54,18 @@ fn test_negative_flow_compile_sierra_to_casm(compiler: impl SierraToCasmCompiler Err(CompilationUtilError::AllowedLibfuncsError(AllowedLibfuncsError::SierraProgramError)) ); } + +// TODO(Arni, 1/5/2024): Add a test for panic result test. +#[rstest] +#[case::command_line_compiler(&COMMAND_LINE_COMPILER)] +fn test_negative_flow_compile_sierra_to_casm_2(#[case] compiler: &impl SierraToCasmCompiler) { + env::set_current_dir(get_absolute_path(TEST_FILES_FOLDER)).expect("Failed to set current dir."); + let sierra_path = Path::new(FAULTY_ACCOUNT_CLASS_FILE); + + let mut contract_class = contract_class_from_file(sierra_path); + // Truncate the sierra program to trigger an error. + contract_class.sierra_program = contract_class.sierra_program[..100].to_vec(); + + let result = compiler.compile_sierra_to_casm(contract_class); + assert_matches!(result, Err(CompilationUtilError::CompilationError(..))); +} diff --git a/crates/starknet_sierra_compile/src/errors.rs b/crates/starknet_sierra_compile/src/errors.rs index 2d3d2575fa..6d056a5d7e 100644 --- a/crates/starknet_sierra_compile/src/errors.rs +++ b/crates/starknet_sierra_compile/src/errors.rs @@ -6,8 +6,14 @@ use thiserror::Error; pub enum CompilationUtilError { #[error(transparent)] AllowedLibfuncsError(#[from] AllowedLibfuncsError), - #[error(transparent)] - StarknetSierraCompilationError(#[from] StarknetSierraCompilationError), + #[error("Starknet Sierra compilation error: {0}")] + CompilationError(String), #[error("Compilation panicked")] CompilationPanic, + #[error(transparent)] + IoError(#[from] std::io::Error), + #[error(transparent)] + SerdeError(#[from] serde_json::Error), + #[error(transparent)] + StarknetSierraCompilationError(#[from] StarknetSierraCompilationError), } diff --git a/crates/starknet_sierra_compile/src/lib.rs b/crates/starknet_sierra_compile/src/lib.rs index 1dc52b917c..f729341a2e 100644 --- a/crates/starknet_sierra_compile/src/lib.rs +++ b/crates/starknet_sierra_compile/src/lib.rs @@ -5,6 +5,7 @@ use cairo_lang_starknet_classes::contract_class::ContractClass; use crate::errors::CompilationUtilError; pub mod cairo_lang_compiler; +pub mod command_line_compiler; pub mod config; pub mod errors; pub mod utils; @@ -12,6 +13,10 @@ pub mod utils; #[cfg(test)] pub mod test_utils; +#[cfg(test)] +#[path = "compile_test.rs"] +pub mod compile_test; + pub trait SierraToCasmCompiler: Send + Sync { fn compile_sierra_to_casm( &self,