Skip to content

Commit

Permalink
feat: use the installed starknet-sierra-compile crate to compile
Browse files Browse the repository at this point in the history
  • Loading branch information
ArniStarkware committed Aug 6, 2024
1 parent 5a926bc commit 5fe2a9a
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/starknet_sierra_compile/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 0 additions & 4 deletions crates/starknet_sierra_compile/src/cairo_lang_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
48 changes: 48 additions & 0 deletions crates/starknet_sierra_compile/src/command_line_compiler.rs
Original file line number Diff line number Diff line change
@@ -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<CasmContractClass, CompilationUtilError> {
// 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::<CasmContractClass>(&compile_output.stdout)?)
}
}
40 changes: 32 additions & 8 deletions crates/starknet_sierra_compile/src/compile_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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(..)));
}
10 changes: 8 additions & 2 deletions crates/starknet_sierra_compile/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
5 changes: 5 additions & 0 deletions crates/starknet_sierra_compile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ 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;

#[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,
Expand Down

0 comments on commit 5fe2a9a

Please sign in to comment.