diff --git a/crates/gateway/src/compilation.rs b/crates/gateway/src/compilation.rs index 18dd5819..1b868e52 100644 --- a/crates/gateway/src/compilation.rs +++ b/crates/gateway/src/compilation.rs @@ -1,4 +1,3 @@ -use std::panic; use std::sync::OnceLock; use blockifier::execution::contract_class::{ClassInfo, ContractClass, ContractClassV1}; @@ -8,7 +7,6 @@ use cairo_lang_starknet_classes::casm_contract_class::{ use starknet_api::core::CompiledClassHash; use starknet_api::rpc_transaction::RPCDeclareTransaction; use starknet_sierra_compile::compile::compile_sierra_to_casm; -use starknet_sierra_compile::errors::CompilationUtilError; use starknet_sierra_compile::utils::into_contract_class_for_compilation; use crate::config::GatewayCompilerConfig; @@ -39,15 +37,8 @@ impl GatewayCompiler { into_contract_class_for_compilation(starknet_api_contract_class); // Compile Sierra to Casm. - let catch_unwind_result = - panic::catch_unwind(|| compile_sierra_to_casm(cairo_lang_contract_class)); - let casm_contract_class = match catch_unwind_result { - Ok(compilation_result) => compilation_result?, - Err(_) => { - // TODO(Arni): Log the panic. - return Err(GatewayError::CompilationError(CompilationUtilError::CompilationPanic)); - } - }; + let casm_contract_class = compile_sierra_to_casm(cairo_lang_contract_class)?; + self.validate_casm_class(&casm_contract_class)?; let hash_result = CompiledClassHash(casm_contract_class.compiled_class_hash()); diff --git a/crates/gateway/src/compilation_test.rs b/crates/gateway/src/compilation_test.rs index 22e81d10..e5a957e5 100644 --- a/crates/gateway/src/compilation_test.rs +++ b/crates/gateway/src/compilation_test.rs @@ -1,6 +1,5 @@ use assert_matches::assert_matches; use blockifier::execution::contract_class::ContractClass; -use cairo_lang_starknet_classes::allowed_libfuncs::AllowedLibfuncsError; use mempool_test_utils::starknet_api_test_utils::declare_tx; use rstest::{fixture, rstest}; use starknet_api::core::CompiledClassHash; @@ -48,9 +47,10 @@ fn test_compile_contract_class_bad_sierra(gateway_compiler: GatewayCompiler) { let result = gateway_compiler.compile_contract_class(&declare_tx); assert_matches!( result.unwrap_err(), - GatewayError::CompilationError(CompilationUtilError::AllowedLibfuncsError( - AllowedLibfuncsError::SierraProgramError + GatewayError::CompilationError(CompilationUtilError::CompilationError( + string )) + if string.contains("Error: Invalid Sierra program.") ) } diff --git a/crates/starknet_sierra_compile/build.rs b/crates/starknet_sierra_compile/build.rs new file mode 100644 index 00000000..3f4d2601 --- /dev/null +++ b/crates/starknet_sierra_compile/build.rs @@ -0,0 +1,23 @@ +use std::process::Command; + +fn main() { + println!("cargo::rerun-if-changed=../../Cargo.lock"); + println!("cargo::rerun-if-changed=build.rs"); + install_starknet_sierra_compile(); +} + +fn install_starknet_sierra_compile() { + println!("Installing starknet-sierra-compile"); + let mut command = Command::new("cargo"); + command.arg("install"); + command.arg("--root"); + command.arg("tmp/cargo"); // TODO: Don't dup the path. + command.arg("starknet-sierra-compile"); + let compile_output = + command.output().unwrap_or_else(|e| panic!("Failed to execute command: {}", e)); + + if !compile_output.status.success() { + let stderr_output = String::from_utf8(compile_output.stderr).unwrap(); // TODO:handle error + panic!("Failed to compile Sierra code: {}", stderr_output); + }; +} diff --git a/crates/starknet_sierra_compile/src/compile.rs b/crates/starknet_sierra_compile/src/compile.rs index 23ac70ce..43c1f969 100644 --- a/crates/starknet_sierra_compile/src/compile.rs +++ b/crates/starknet_sierra_compile/src/compile.rs @@ -1,33 +1,71 @@ -use cairo_lang_starknet_classes::allowed_libfuncs::ListSelector; +use std::env; +use std::env::temp_dir; +use std::fs::File; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::process::Command; + use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use cairo_lang_starknet_classes::contract_class::ContractClass; use crate::errors::CompilationUtilError; +// Solve Code duplication. +pub fn get_absolute_path(relative_path: &str) -> PathBuf { + Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("../..").join(relative_path) +} + #[cfg(test)] #[path = "compile_test.rs"] pub mod compile_test; -pub struct SierraToCasmCompilationArgs { - list_selector: ListSelector, + +const STARKNET_SIERRA_COMPILE_EXE: &str = + "crates/starknet_sierra_compile/tmp/cargo/bin/starknet-sierra-compile"; + +struct SierraToCasmCompilationArgs { add_pythonic_hints: bool, max_bytecode_size: usize, } -/// This function may panic. +// TODO(Arni, 1/05/2024): Add the configurable parameters to the function. pub fn compile_sierra_to_casm( contract_class: ContractClass, ) -> Result { - let compilation_args = SierraToCasmCompilationArgs { - list_selector: ListSelector::DefaultList, - add_pythonic_hints: true, - max_bytecode_size: 1000000, - }; + env::set_current_dir(get_absolute_path("")).expect("Failed to set current dir."); + + let serialized_contract_class = serde_json::to_string(&contract_class).expect("number 1"); + + // Create a temporary file path + let mut temp_path = temp_dir(); + temp_path.push("temp_file.sierra.json"); - contract_class.validate_version_compatible(compilation_args.list_selector)?; + // Create and open the file + let mut file = File::create(&temp_path).expect("number 2"); + + // Write the content to the file + file.write_all(serialized_contract_class.as_bytes()).expect("number 3"); + + let compilation_args = + SierraToCasmCompilationArgs { add_pythonic_hints: true, max_bytecode_size: 180000 }; + let compiler_path = STARKNET_SIERRA_COMPILE_EXE; + + let mut command = Command::new(compiler_path); + command.arg(temp_path.to_str().expect("number 4")); + + // Add aditional arguments. + if compilation_args.add_pythonic_hints { + command.arg("--add-pythonic-hints"); + } + // TODO(Arni): use max-bytecode-size. + let _max_bytecode_size = compilation_args.max_bytecode_size; + + let compile_output = + command.output().unwrap_or_else(|e| panic!("Failed to execute command: {}", e)); + + if !compile_output.status.success() { + let stderr_output = String::from_utf8(compile_output.stderr).expect("number 5"); // TODO: handle error + return Err(CompilationUtilError::CompilationError(stderr_output)); + }; - Ok(CasmContractClass::from_contract_class( - contract_class, - compilation_args.add_pythonic_hints, - compilation_args.max_bytecode_size, - )?) + Ok(serde_json::from_slice::(&compile_output.stdout).expect("number 6")) } diff --git a/crates/starknet_sierra_compile/src/compile_test.rs b/crates/starknet_sierra_compile/src/compile_test.rs index 2afb5f3d..de36f6f8 100644 --- a/crates/starknet_sierra_compile/src/compile_test.rs +++ b/crates/starknet_sierra_compile/src/compile_test.rs @@ -2,7 +2,6 @@ use std::env; 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 crate::compile::{compile_sierra_to_casm, CompilationUtilError}; @@ -34,6 +33,7 @@ fn test_negative_flow_compile_sierra_to_casm() { let result = compile_sierra_to_casm(contract_class); assert_matches!( result, - Err(CompilationUtilError::AllowedLibfuncsError(AllowedLibfuncsError::SierraProgramError)) + Err(CompilationUtilError::CompilationError(string)) + if string.contains("Error: Invalid Sierra program.") ); } diff --git a/crates/starknet_sierra_compile/src/errors.rs b/crates/starknet_sierra_compile/src/errors.rs index 2d3d2575..26acfde0 100644 --- a/crates/starknet_sierra_compile/src/errors.rs +++ b/crates/starknet_sierra_compile/src/errors.rs @@ -1,13 +1,7 @@ -use cairo_lang_starknet_classes::allowed_libfuncs::AllowedLibfuncsError; -use cairo_lang_starknet_classes::casm_contract_class::StarknetSierraCompilationError; use thiserror::Error; #[derive(Debug, Error)] pub enum CompilationUtilError { - #[error(transparent)] - AllowedLibfuncsError(#[from] AllowedLibfuncsError), - #[error(transparent)] - StarknetSierraCompilationError(#[from] StarknetSierraCompilationError), - #[error("Compilation panicked")] - CompilationPanic, + #[error("Starknet Sierra compilation error: {0}")] + CompilationError(String), }