From e6b4eeb6639ac103901b50df691c232ef5960093 Mon Sep 17 00:00:00 2001 From: enitrat Date: Tue, 24 Sep 2024 20:19:17 +0200 Subject: [PATCH] use contract executor --- .gitignore | 2 + Cargo.lock | 78 +++++++++++- Cargo.toml | 4 +- .../src/evm_sequencer/sequencer/mod.rs | 8 +- crates/sequencer/src/native.rs | 113 +++--------------- 5 files changed, 98 insertions(+), 107 deletions(-) diff --git a/.gitignore b/.gitignore index 6b863e65..43451617 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ tmp* # Ignore the generated tests /crates/ef-testing/tests/* +/crates/ef-testing/native_cache/* + # Ignore the launch file launch.json diff --git a/Cargo.lock b/Cargo.lock index 046fd42d..f0c3bf7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1098,6 +1098,7 @@ dependencies = [ [[package]] name = "blockifier" version = "0.0.0" +source = "git+https://github.com/kkrt-labs/sequencer.git?branch=kkrt-native-2.8#575a104968f14d83341c0e4f82a6d945e043d6ae" dependencies = [ "anyhow", "ark-ec", @@ -1110,7 +1111,7 @@ dependencies = [ "cairo-lang-sierra", "cairo-lang-starknet-classes", "cairo-lang-utils", - "cairo-native", + "cairo-native 0.2.0 (git+https://github.com/enitrat/cairo_native.git?branch=feat/ef-test-compat)", "cairo-vm", "derive_more 0.99.18", "educe", @@ -1859,7 +1860,59 @@ dependencies = [ "cairo-lang-starknet-classes", "cairo-lang-test-plugin", "cairo-lang-utils", - "cairo-native-runtime", + "cairo-native-runtime 0.2.0", + "cc", + "clap", + "colored", + "educe", + "itertools 0.13.0", + "k256", + "keccak", + "lazy_static", + "libc", + "libloading", + "llvm-sys", + "melior", + "mlir-sys", + "num-bigint", + "num-traits 0.2.19", + "p256", + "sec1", + "serde", + "serde_json", + "sha2 0.10.8", + "starknet-types-core", + "stats_alloc", + "tempfile", + "thiserror", + "tracing", + "tracing-subscriber", + "utf8_iter", +] + +[[package]] +name = "cairo-native" +version = "0.2.0" +source = "git+https://github.com/enitrat/cairo_native.git?branch=feat/ef-test-compat#8727999cbf275cc2edb4aa696065e33f82a7f76f" +dependencies = [ + "anyhow", + "aquamarine", + "bumpalo", + "cairo-lang-compiler", + "cairo-lang-defs", + "cairo-lang-diagnostics", + "cairo-lang-filesystem", + "cairo-lang-runner", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-sierra-ap-change", + "cairo-lang-sierra-gas", + "cairo-lang-sierra-generator", + "cairo-lang-starknet", + "cairo-lang-starknet-classes", + "cairo-lang-test-plugin", + "cairo-lang-utils", + "cairo-native-runtime 0.2.0 (git+https://github.com/enitrat/cairo_native.git?branch=feat/ef-test-compat)", "cc", "clap", "colored", @@ -1901,6 +1954,19 @@ dependencies = [ "starknet-types-core", ] +[[package]] +name = "cairo-native-runtime" +version = "0.2.0" +source = "git+https://github.com/enitrat/cairo_native.git?branch=feat/ef-test-compat#8727999cbf275cc2edb4aa696065e33f82a7f76f" +dependencies = [ + "cairo-lang-sierra-gas", + "lazy_static", + "libc", + "rand", + "starknet-curve 0.5.1", + "starknet-types-core", +] + [[package]] name = "cairo-vm" version = "1.0.1" @@ -4489,7 +4555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -5337,6 +5403,7 @@ dependencies = [ [[package]] name = "papyrus_config" version = "0.0.0" +source = "git+https://github.com/kkrt-labs/sequencer.git?branch=kkrt-native-2.8#575a104968f14d83341c0e4f82a6d945e043d6ae" dependencies = [ "clap", "itertools 0.10.5", @@ -8205,7 +8272,7 @@ dependencies = [ "cached 0.53.1", "cairo-lang-sierra", "cairo-lang-starknet-classes", - "cairo-native", + "cairo-native 0.2.0", "eyre", "hashbrown 0.14.5", "lazy_static", @@ -8798,6 +8865,7 @@ dependencies = [ [[package]] name = "starknet_api" version = "0.0.0" +source = "git+https://github.com/kkrt-labs/sequencer.git?branch=kkrt-native-2.8#575a104968f14d83341c0e4f82a6d945e043d6ae" dependencies = [ "bitvec", "cairo-lang-starknet-classes", @@ -9915,7 +9983,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f9df89e2..9c312276 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,12 +44,12 @@ cairo-lang-starknet-classes = "2.8.0" cairo-lang-sierra = "2.8.0" cairo-native = {path = "/Users/msaug/deps/cairo_native"} cairo-vm = "1.0.1" -blockifier = { package = "blockifier", path = "../../deps/sequencer/crates/blockifier", default-features = false, features = [ +blockifier = { package = "blockifier", git = "https://github.com/kkrt-labs/sequencer.git", branch = "kkrt-native-2.8", default-features = false, features = [ "testing", ] } starknet = "0.12" starknet-crypto = "0.7" -starknet_api = { package = "starknet_api", path = "../../deps/sequencer/crates/starknet_api" } +starknet_api = { package = "starknet_api", git = "https://github.com/kkrt-labs/sequencer.git", branch = "kkrt-native-2.8" } # Other async-trait = "0.1" diff --git a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs index 21322ff6..98659cd7 100644 --- a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs @@ -236,17 +236,17 @@ lazy_static! { { #[cfg(feature = "native")] { - let account_json = CLASS_HASH_TO_JSON_CLASS.get(&ACCOUNT_CONTRACT_CLASS_HASH).unwrap(); let kakarot_json = CLASS_HASH_TO_JSON_CLASS.get(&KAKAROT_CLASS_HASH).unwrap(); + let account_json = CLASS_HASH_TO_JSON_CLASS.get(&ACCOUNT_CONTRACT_CLASS_HASH).unwrap(); let uninitialized_json = CLASS_HASH_TO_JSON_CLASS.get(&UNINITIALIZED_ACCOUNT_CLASS_HASH).unwrap(); - println!("Got account's json of length {}", account_json.len()); println!("Got kakarot's json of length {}", kakarot_json.len()); + println!("Got account's json of length {}", account_json.len()); println!("Got uninitialized's json of length {}", uninitialized_json.len()); - let account_class= class_from_json_str(account_json, *ACCOUNT_CONTRACT_CLASS_HASH).unwrap(); let kakarot_class= class_from_json_str(kakarot_json, *KAKAROT_CLASS_HASH).unwrap(); + let account_class= class_from_json_str(account_json, *ACCOUNT_CONTRACT_CLASS_HASH).unwrap(); let uninitialized_class= class_from_json_str(uninitialized_json, *UNINITIALIZED_ACCOUNT_CLASS_HASH).unwrap(); println!("Got class"); - (account_class, kakarot_class, uninitialized_class) + (kakarot_class, account_class, uninitialized_class) } #[cfg(not(feature = "native"))] { diff --git a/crates/sequencer/src/native.rs b/crates/sequencer/src/native.rs index d64f99ed..aa7fabad 100644 --- a/crates/sequencer/src/native.rs +++ b/crates/sequencer/src/native.rs @@ -8,8 +8,9 @@ use blockifier::{ ClassInfo as BlockifierClassInfo}, }; use cairo_lang_starknet_classes::abi::Contract; +use cairo_native::OptLevel; use cairo_native::{ - context::NativeContext, error::Error as NativeError, executor::AotNativeExecutor, + context::NativeContext, error::Error as NativeError, executor::AotContractExecutor, metadata::gas::GasMetadata, module::NativeModule, }; use cairo_lang_starknet_classes::contract_class::ContractClass as SierraContractClass; @@ -17,6 +18,7 @@ use libloading::Library; use starknet_api::core::ClassHash; use serde::{Deserialize, Serialize}; +use std::sync::Arc; use std::{ ffi::{c_char, c_uchar, c_void, CStr}, fs, @@ -41,36 +43,6 @@ fn generate_library_path(class_hash: ClassHash) -> PathBuf { path } -/// Compiles and load contract -/// -/// Modelled after [AotNativeExecutor::from_native_module]. -/// Needs a sierra_program to workaround limitations of NativeModule -fn persist_from_native_module( - mut native_module: NativeModule, - sierra_program: &Program, - library_output_path: &PathBuf, -) -> Result> { - let object_data = cairo_native::module_to_object(native_module.module(), Default::default()) - .map_err(|err| NativeError::LLVMCompileError(err.to_string()))?; // cairo native didn't include a from instance - - cairo_native::object_to_shared_lib(&object_data, library_output_path)?; - - let gas_metadata = native_module - .remove_metadata() - .expect("native_module should have set gas_metadata"); - - // Recreate the program registry as it can't be moved out of native module. - let program_registry = ProgramRegistry::new(sierra_program)?; - - let library = unsafe { Library::new(library_output_path)? }; - - Ok(AotNativeExecutor::new( - library, - program_registry, - gas_metadata, - )) -} - fn setup_native_cache_dir() -> PathBuf { let mut path: PathBuf = match std::env::var("NATIVE_CACHE_DIR") { Ok(path) => path.into(), @@ -84,42 +56,6 @@ fn setup_native_cache_dir() -> PathBuf { path } - -/// Load a contract that is already compiled. -/// -/// Returns None if the contract does not exist at the output_path. -/// -/// To compile and load a contract use [persist_from_native_module] instead. -fn load_compiled_contract( - sierra_program: &Program, - library_output_path: &PathBuf, -) -> Option>> { - fn load( - sierra_program: &Program, - library_output_path: &PathBuf, - ) -> Result> { - let has_gas_builtin = sierra_program - .type_declarations - .iter() - .any(|decl| decl.long_id.generic_id.0.as_str() == "GasBuiltin"); - let config = has_gas_builtin.then_some(Default::default()); - let gas_metadata = GasMetadata::new(sierra_program, config)?; - let program_registry = ProgramRegistry::new(sierra_program)?; - let library = unsafe { Library::new(library_output_path)? }; - Ok(AotNativeExecutor::new( - library, - program_registry, - gas_metadata, - )) - } - - library_output_path - .is_file() - .then_some(load(sierra_program, library_output_path)) -} - -/// Compiled Native contracts - /// Load a compiled native contract into memory /// /// Tries to load the compiled contract class from library_output_path if it @@ -129,40 +65,25 @@ fn native_try_from_json_string( raw_contract_class: &str, library_output_path: &PathBuf, ) -> Result> { - fn compile_and_load( - sierra_program: Program, - library_output_path: &PathBuf, - ) -> Result> { - println!("Compiling native contract"); - let native_context = NativeContext::new(); - // Ignore the debug names, that might cause conflicts when retrieving entrypoints upon execution of blockifier. - let native_module = native_context.compile(&sierra_program, false)?; - - persist_from_native_module(native_module, &sierra_program, library_output_path) - } - let sierra_contract_class: cairo_lang_starknet_classes::contract_class::ContractClass = - serde_json::from_str(raw_contract_class)?; - - // todo(rodro): we are having two instances of a sierra program, one it's object form - // and another in its felt encoded form. This can be avoided by either: - // 1. Having access to the encoding/decoding functions - // 2. Refactoring the code on the Cairo mono-repo + serde_json::from_str(raw_contract_class)?; let sierra_program = sierra_contract_class.extract_sierra_program()?; - // todo(xrvdg) lift this match out of the function once we do not need sierra_program anymore - let executor = match load_compiled_contract(&sierra_program, library_output_path) { - Some(executor) => { - println!("Loaded cached compiled contract from {:?}", library_output_path); - executor.or_else(|_err| compile_and_load(sierra_program, library_output_path)) - } - None => { - compile_and_load(sierra_program, library_output_path) - }, - }?; + let maybe_cached_executor = AotContractExecutor::load(library_output_path); + if let Ok(executor) = maybe_cached_executor { + println!("Loaded cached executor"); + let native_class = NativeContractClassV1::new(Arc::new(executor), sierra_contract_class)?; + return Ok(native_class); + } + + println!("Creating new executor"); + let mut executor = AotContractExecutor::new(&sierra_program, OptLevel::Default)?; + executor.save(library_output_path)?; + println!("Saved executor to {:?}", library_output_path); - Ok(NativeContractClassV1::new(executor, sierra_contract_class)?) + let native_class = NativeContractClassV1::new(Arc::new(executor), sierra_contract_class)?; + Ok(native_class) }