diff --git a/vm/rust/Cargo.lock b/vm/rust/Cargo.lock index 6bc0208f8c..b7c768f122 100644 --- a/vm/rust/Cargo.lock +++ b/vm/rust/Cargo.lock @@ -450,7 +450,7 @@ dependencies = [ [[package]] name = "blockifier" version = "0.0.0" -source = "git+https://github.com/NethermindEth/sequencer?branch=native2.8.x#398a608a1d2a6be03d7cf7f34a60d4824ab72b9b" +source = "git+https://github.com/NethermindEth/sequencer?rev=de05be2f904cf23cfc25eeaa68bf89546298577d#de05be2f904cf23cfc25eeaa68bf89546298577d" dependencies = [ "anyhow", "ark-ec", @@ -469,6 +469,7 @@ dependencies = [ "indexmap 2.4.0", "itertools 0.10.5", "keccak", + "lazy_static", "log", "num-bigint", "num-integer", @@ -483,8 +484,8 @@ dependencies = [ "sha3", "starknet-types-core", "starknet_api", - "strum 0.25.0", - "strum_macros 0.25.3", + "strum", + "strum_macros", "tempfile", "thiserror", "toml", @@ -1129,7 +1130,7 @@ dependencies = [ [[package]] name = "cairo-native" version = "0.2.0" -source = "git+https://github.com/lambdaclass/cairo_native?rev=4355357697e9ab57ab88ae3a4282aac61455619e#4355357697e9ab57ab88ae3a4282aac61455619e" +source = "git+https://github.com/lambdaclass/cairo_native?rev=a478e89b749bf0b596a7e63afd14e834c08a84e3#a478e89b749bf0b596a7e63afd14e834c08a84e3" dependencies = [ "anyhow", "aquamarine", @@ -1166,6 +1167,8 @@ dependencies = [ "num-traits 0.2.19", "p256", "sec1", + "serde", + "serde_json", "sha2", "starknet-types-core", "stats_alloc", @@ -1178,7 +1181,7 @@ dependencies = [ [[package]] name = "cairo-native-runtime" version = "0.2.0" -source = "git+https://github.com/lambdaclass/cairo_native?rev=4355357697e9ab57ab88ae3a4282aac61455619e#4355357697e9ab57ab88ae3a4282aac61455619e" +source = "git+https://github.com/lambdaclass/cairo_native?rev=a478e89b749bf0b596a7e63afd14e834c08a84e3#a478e89b749bf0b596a7e63afd14e834c08a84e3" dependencies = [ "cairo-lang-sierra-gas", "lazy_static", @@ -3123,13 +3126,13 @@ dependencies = [ [[package]] name = "papyrus_config" version = "0.0.0" -source = "git+https://github.com/NethermindEth/sequencer?branch=native2.8.x#398a608a1d2a6be03d7cf7f34a60d4824ab72b9b" +source = "git+https://github.com/NethermindEth/sequencer?rev=de05be2f904cf23cfc25eeaa68bf89546298577d#de05be2f904cf23cfc25eeaa68bf89546298577d" dependencies = [ "clap", "itertools 0.10.5", "serde", "serde_json", - "strum_macros 0.25.3", + "strum_macros", "thiserror", "validator", ] @@ -4348,22 +4351,22 @@ dependencies = [ [[package]] name = "starknet_api" version = "0.0.0" -source = "git+https://github.com/NethermindEth/sequencer?branch=native2.8.x#398a608a1d2a6be03d7cf7f34a60d4824ab72b9b" +source = "git+https://github.com/NethermindEth/sequencer?rev=de05be2f904cf23cfc25eeaa68bf89546298577d#de05be2f904cf23cfc25eeaa68bf89546298577d" dependencies = [ "bitvec", "cairo-lang-starknet-classes", "derive_more", "hex", "indexmap 2.4.0", - "itertools 0.12.1", + "itertools 0.10.5", "primitive-types", "serde", "serde_json", "sha3", "starknet-crypto 0.5.2", "starknet-types-core", - "strum 0.24.1", - "strum_macros 0.24.3", + "strum", + "strum_macros", "thiserror", ] @@ -4404,31 +4407,12 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - [[package]] name = "strum" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - [[package]] name = "strum_macros" version = "0.25.3" diff --git a/vm/rust/Cargo.toml b/vm/rust/Cargo.toml index 8f35283049..ae502860d2 100644 --- a/vm/rust/Cargo.toml +++ b/vm/rust/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" [dependencies] serde = "1.0.171" serde_json = { version = "1.0.96", features = ["raw_value"] } -blockifier = { git = "https://github.com/NethermindEth/sequencer", branch = "native2.8.x" } -starknet_api = { git = "https://github.com/NethermindEth/sequencer", branch = "native2.8.x" } +blockifier = { git = "https://github.com/NethermindEth/sequencer", rev = "de05be2f904cf23cfc25eeaa68bf89546298577d" } +starknet_api = { git = "https://github.com/NethermindEth/sequencer", rev = "de05be2f904cf23cfc25eeaa68bf89546298577d" } cairo-lang-sierra = "2.8.0" cairo-lang-starknet = "2.8.0" cairo-lang-starknet-classes = "2.8.0" @@ -18,7 +18,7 @@ starknet-types-core = { version = "0.1.5", features = [ "prime-bigint", "serde", ] } -cairo-native = { git = "https://github.com/lambdaclass/cairo_native", rev = "4355357697e9ab57ab88ae3a4282aac61455619e" } +cairo-native = { git = "https://github.com/lambdaclass/cairo_native", rev = "a478e89b749bf0b596a7e63afd14e834c08a84e3" } cairo-vm = "1.0.0" indexmap = "2.1.0" cached = "0.46.1" @@ -30,7 +30,7 @@ libloading = "0.8.5" thiserror = "1.0.63" ciborium = "0.2.2" -# Trace block dependencies +# Trace block dependencies starknet-core = "0.11.1" starknet-providers = "0.11.0" tokio = { version = "1.38.1", features = ["rt", "macros"] } diff --git a/vm/rust/src/juno_state_reader.rs b/vm/rust/src/juno_state_reader.rs index 83ce8226e6..bdf5619bbf 100644 --- a/vm/rust/src/juno_state_reader.rs +++ b/vm/rust/src/juno_state_reader.rs @@ -7,18 +7,15 @@ use blockifier::{ state::state_api::{StateReader, StateResult}, }; use cached::{Cached, SizedCache}; -use cairo_lang_sierra::{program::Program, program_registry::ProgramRegistry}; -use cairo_native::{ - context::NativeContext, error::Error as NativeError, executor::AotNativeExecutor, - metadata::gas::GasMetadata, module::NativeModule, -}; -use libloading::Library; +use cairo_native::executor::contract::ContractExecutor; +use cairo_native::OptLevel; use once_cell::sync::Lazy; use serde::Deserialize; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::state::StorageKey; use starknet_types_core::felt::Felt; use std::cell::RefCell; +use std::sync::Arc; use std::{ ffi::{c_char, c_uchar, c_void, CStr}, fs, @@ -185,6 +182,7 @@ impl StateReader for JunoStateReader { /// Returns the contract class of the given class hash. fn get_compiled_contract_class(&self, class_hash: ClassHash) -> StateResult { println!("Juno State Reader(Rust): calling `get_compiled_contract_class` with class hash: {class_hash}"); + if let Some(cached_class) = CLASS_CACHE.lock().unwrap().cache_get(&class_hash) { // skip the cache if it comes from a height higher than ours. Class might be undefined on the height // that we are reading from right now. @@ -311,68 +309,16 @@ 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> { - let native_context = NativeContext::new(); - let native_module = native_context.compile(&sierra_program)?; - - 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 - 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) => { - executor.or_else(|_err| compile_and_load(sierra_program, library_output_path)) - } - None => compile_and_load(sierra_program, library_output_path), - }?; - - Ok(NativeContractClassV1::new(executor, sierra_contract_class)?) -} - -/// 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)) + let executor = ContractExecutor::load(library_output_path).or_else(|_| { + let executor = ContractExecutor::new(&sierra_program, OptLevel::Default)?; + executor.save(library_output_path)?; + Ok::>(executor) + })?; + let contract_executor = NativeContractClassV1::new(Arc::new(executor), sierra_contract_class)?; + Ok(contract_executor) } // todo(xrvdg) once [class_info_from_json_str] is part of JunoStateReader @@ -403,33 +349,3 @@ fn generate_library_path(class_hash: ClassHash) -> PathBuf { path.push(class_hash.to_string().trim_start_matches("0x")); 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, - )) -} diff --git a/vm/rust/src/lib.rs b/vm/rust/src/lib.rs index a075b07576..1ddc5f192e 100644 --- a/vm/rust/src/lib.rs +++ b/vm/rust/src/lib.rs @@ -159,7 +159,7 @@ pub extern "C" fn cairoVMCall( let mut state = CachedState::new(reader); let mut resources = ExecutionResources::default(); - let context = EntryPointExecutionContext::new_invoke( + let mut context = EntryPointExecutionContext::new_invoke( Arc::new(TransactionContext { block_context: build_block_context( &mut state, @@ -171,12 +171,8 @@ pub extern "C" fn cairoVMCall( }), false, ); - if let Err(e) = context { - report_error(reader_handle, e.to_string().as_str(), -1); - return; - } - match entry_point.execute(&mut state, &mut resources, &mut context.unwrap()) { + match entry_point.execute(&mut state, &mut resources, &mut context) { Err(e) => report_error(reader_handle, e.to_string().as_str(), -1), Ok(t) => { for data in t.execution.retdata.0 { @@ -339,7 +335,7 @@ fn cairo_vm_execute( }; if let Some(path) = JUNO_RECORD_DIR.clone() { - let mut args_path: PathBuf = path.into(); + let mut args_path: PathBuf = path; args_path.push(format!("{}.args.cbor", block_info.block_number)); let file_args = std::fs::File::create(args_path).unwrap(); @@ -401,7 +397,7 @@ fn cairo_vm_execute( } if let Some(path) = JUNO_RECORD_DIR.clone() { - let mut state_path: PathBuf = path.into(); + let mut state_path: PathBuf = path; state_path.push(format!("{}.state.cbor", block_info.block_number)); let state_file = File::create(state_path).unwrap(); @@ -461,9 +457,17 @@ pub fn execute_transaction( let minimal_l1_gas_amount_vector: Option; let res = match txn { Transaction::AccountTransaction(t) => { + let tx_context = block_context.to_tx_context(&t); fee_type = t.fee_type(); - minimal_l1_gas_amount_vector = - Some(gas_usage::estimate_minimal_gas_vector(block_context, &t).unwrap()); + minimal_l1_gas_amount_vector = Some( + gas_usage::estimate_minimal_gas_vector( + block_context, + &t, + &tx_context.get_gas_vector_computation_mode(), + ) + .unwrap(), + ); + t.execute(txn_state, block_context, charge_fee, validate) } Transaction::L1HandlerTransaction(t) => { @@ -619,11 +623,11 @@ fn build_block_context( gas_to_nzu128(block_info.data_gas_price_wei), gas_to_nzu128(block_info.data_gas_price_fri), VersionedConstants::latest_constants() - .l1_to_l2_gas_price_conversion(felt_to_u128(block_info.gas_price_wei)) + .convert_l1_to_l2_gas(felt_to_u128(block_info.gas_price_wei)) .try_into() .expect("gas price wei is zero :O"), VersionedConstants::latest_constants() - .l1_to_l2_gas_price_conversion(felt_to_u128(block_info.gas_price_fri)) + .convert_l1_to_l2_gas(felt_to_u128(block_info.gas_price_fri)) .try_into() .expect("gas price fri is zero :O"), ),