diff --git a/Cargo.lock b/Cargo.lock index 594ba06c01..2a46eb4ea4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2224,9 +2224,9 @@ dependencies = [ [[package]] name = "cairo-native" -version = "0.2.2-alpha.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3fa21c1c95fd92e13478fcb3df66f9cdb048ac341f9f2a6c27729c2c4c88ca3" +checksum = "833170f422b08eec0e5ab116573bbb73c73f1601987d4b151cf71760836bd142" dependencies = [ "anyhow", "aquamarine", @@ -2278,9 +2278,9 @@ dependencies = [ [[package]] name = "cairo-native-runtime" -version = "0.2.2-alpha.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2afea1ee81ca6744fa4034479eb3ee5fcfeaaccc4107a4c94885c729bfa19321" +checksum = "7fa4ec78d0a6df2988b71838c330a5113f65a4db6ccff53d8d71465f6619a427" dependencies = [ "cairo-lang-sierra-gas", "itertools 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index 3a6def375f..730c9a1e8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,7 +103,7 @@ cairo-lang-sierra-to-casm = "2.9.0-dev.0" cairo-lang-starknet-classes = "2.9.0-dev.0" cairo-lang-utils = "2.9.0-dev.0" # Important: when updated, make sure to update the cairo-native submodule as well. -cairo-native = "0.2.2-alpha.0" +cairo-native = "0.2.3" cairo-vm = "=1.0.1" camelpaste = "0.1.0" chrono = "0.4.26" diff --git a/crates/bin/starknet-native-compile/Cargo.lock b/crates/bin/starknet-native-compile/Cargo.lock index ad4b23f882..b8bc1ad781 100644 --- a/crates/bin/starknet-native-compile/Cargo.lock +++ b/crates/bin/starknet-native-compile/Cargo.lock @@ -939,9 +939,9 @@ dependencies = [ [[package]] name = "cairo-native" -version = "0.2.1-alpha.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897182bfc00fa8c9a4c405daaef576cd044d3ce5df30e34b2909659bc34270e5" +checksum = "833170f422b08eec0e5ab116573bbb73c73f1601987d4b151cf71760836bd142" dependencies = [ "anyhow", "aquamarine", @@ -993,9 +993,9 @@ dependencies = [ [[package]] name = "cairo-native-runtime" -version = "0.2.1-alpha.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af9e9586d0e4c3cab5061cfcb9e024d5096ca7625bf2836976b32e76e0f2eb9" +checksum = "7fa4ec78d0a6df2988b71838c330a5113f65a4db6ccff53d8d71465f6619a427" dependencies = [ "cairo-lang-sierra-gas", "itertools 0.13.0", diff --git a/crates/bin/starknet-native-compile/Cargo.toml b/crates/bin/starknet-native-compile/Cargo.toml index 25deb266e3..477e8e429f 100644 --- a/crates/bin/starknet-native-compile/Cargo.toml +++ b/crates/bin/starknet-native-compile/Cargo.toml @@ -10,6 +10,6 @@ license = "Apache-2.0" # TODO(Avi, 01/02/2025): Check consistency with the blockifier. cairo-lang-sierra = "2.9.0-dev.0" cairo-lang-starknet-classes = "2.9.0-dev.0" -cairo-native = "0.2.1-alpha.0" +cairo-native = "0.2.3" clap = { version = "4.5.4", features = ["derive"] } serde_json = "1.0.116" diff --git a/crates/bin/starknet-native-compile/src/main.rs b/crates/bin/starknet-native-compile/src/main.rs index 1dfea39cb1..6e6990d421 100644 --- a/crates/bin/starknet-native-compile/src/main.rs +++ b/crates/bin/starknet-native-compile/src/main.rs @@ -1,11 +1,12 @@ -use crate::utils::load_sierra_program_from_file; -use cairo_native::executor::AotContractExecutor; -use cairo_native::OptLevel; use std::path::PathBuf; use std::process; +use cairo_native::executor::AotContractExecutor; +use cairo_native::OptLevel; use clap::Parser; +use crate::utils::load_sierra_program_from_file; + mod utils; #[derive(Parser, Debug)] @@ -23,14 +24,18 @@ fn main() { let path = args.path; let output = args.output; - let sierra_program = load_sierra_program_from_file(&path); + let (contract_class, sierra_program) = load_sierra_program_from_file(&path); // TODO(Avi, 01/12/2024): Test different optimization levels for best performance. - let mut contract_executor = AotContractExecutor::new(&sierra_program, OptLevel::default()) - .unwrap_or_else(|err| { - eprintln!("Error compiling Sierra program: {}", err); - process::exit(1); - }); + let mut contract_executor = AotContractExecutor::new( + &sierra_program, + &contract_class.entry_points_by_type, + OptLevel::default(), + ) + .unwrap_or_else(|err| { + eprintln!("Error compiling Sierra program: {}", err); + process::exit(1); + }); contract_executor.save(output.clone()).unwrap_or_else(|err| { eprintln!("Error saving compiled program: {}", err); process::exit(1); diff --git a/crates/bin/starknet-native-compile/src/utils.rs b/crates/bin/starknet-native-compile/src/utils.rs index 2f4f5e7803..728f547a01 100644 --- a/crates/bin/starknet-native-compile/src/utils.rs +++ b/crates/bin/starknet-native-compile/src/utils.rs @@ -1,11 +1,10 @@ -use cairo_lang_starknet_classes::contract_class::ContractClass; - -use cairo_lang_sierra::program::Program; - use std::path::PathBuf; use std::process; -pub(crate) fn load_sierra_program_from_file(path: &PathBuf) -> Program { +use cairo_lang_sierra::program::Program; +use cairo_lang_starknet_classes::contract_class::ContractClass; + +pub(crate) fn load_sierra_program_from_file(path: &PathBuf) -> (ContractClass, Program) { let raw_contract_class = std::fs::read_to_string(path).unwrap_or_else(|err| { eprintln!("Error reading Sierra file: {}", err); process::exit(1); @@ -15,8 +14,11 @@ pub(crate) fn load_sierra_program_from_file(path: &PathBuf) -> Program { eprintln!("Error deserializing Sierra file into contract class: {}", err); process::exit(1); }); - contract_class.extract_sierra_program().unwrap_or_else(|err| { - eprintln!("Error extracting Sierra program from contract class: {}", err); - process::exit(1); - }) + ( + contract_class.clone(), + contract_class.extract_sierra_program().unwrap_or_else(|err| { + eprintln!("Error extracting Sierra program from contract class: {}", err); + process::exit(1); + }), + ) } diff --git a/crates/blockifier/build.rs b/crates/blockifier/build.rs index 1a45e506bc..f23af037cf 100644 --- a/crates/blockifier/build.rs +++ b/crates/blockifier/build.rs @@ -38,7 +38,7 @@ fn compile_cairo_native_aot_runtime() { const RUNTIME_LIBRARY: &str = "CAIRO_NATIVE_RUNTIME_LIBRARY"; let runtime_expected_path = { let expected_path_env = - std::env::var(RUNTIME_LIBRARY).expect("Cairo Native rutime path variable is not set"); + std::env::var(RUNTIME_LIBRARY).expect("Cairo Native runtime path variable is not set"); let expected_path = PathBuf::from(&expected_path_env); if expected_path.is_absolute() { diff --git a/crates/blockifier/cairo_native b/crates/blockifier/cairo_native index 0bc6f40888..c9b0fb767d 160000 --- a/crates/blockifier/cairo_native +++ b/crates/blockifier/cairo_native @@ -1 +1 @@ -Subproject commit 0bc6f408884370e4fbbf421c4e8e109911c3d73e +Subproject commit c9b0fb767d5952053bfe978782a18a410713866a diff --git a/crates/blockifier/src/execution/native/syscall_handler.rs b/crates/blockifier/src/execution/native/syscall_handler.rs index 7d9651ff20..126e88d6d0 100644 --- a/crates/blockifier/src/execution/native/syscall_handler.rs +++ b/crates/blockifier/src/execution/native/syscall_handler.rs @@ -110,12 +110,10 @@ impl<'state> NativeSyscallHandler<'state> { fn execute_inner_call( &mut self, entry_point: CallEntryPoint, - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult { - let mut remaining_gas_u64 = - u64::try_from(*remaining_gas).expect("Failed to convert gas to u64."); let call_info = entry_point - .execute(self.state, self.resources, self.context, &mut remaining_gas_u64) + .execute(self.state, self.resources, self.context, remaining_gas) .map_err(|e| self.handle_error(remaining_gas, e.into()))?; let retdata = call_info.execution.retdata.clone(); @@ -124,10 +122,6 @@ impl<'state> NativeSyscallHandler<'state> { return Err(self.handle_error(remaining_gas, error)); } - // TODO(Noa, 1/11/2024): remove this once the gas type is u64. - // Change the remaining gas value. - *remaining_gas = u128::from(remaining_gas_u64); - self.inner_calls.push(call_info); Ok(retdata) @@ -137,7 +131,7 @@ impl<'state> NativeSyscallHandler<'state> { /// we need to explicitly call this method at the beginning of each syscall. fn pre_execute_syscall( &mut self, - remaining_gas: &mut u128, + remaining_gas: &mut u64, syscall_gas_cost: u64, ) -> SyscallResult<()> { if self.unrecoverable_error.is_some() { @@ -146,8 +140,7 @@ impl<'state> NativeSyscallHandler<'state> { return Err(vec![]); } // Refund `SYSCALL_BASE_GAS_COST` as it was pre-charged. - let required_gas = - u128::from(syscall_gas_cost - self.context.gas_costs().syscall_base_gas_cost); + let required_gas = syscall_gas_cost - self.context.gas_costs().syscall_base_gas_cost; if *remaining_gas < required_gas { // Out of gas failure. @@ -162,11 +155,7 @@ impl<'state> NativeSyscallHandler<'state> { Ok(()) } - fn handle_error( - &mut self, - remaining_gas: &mut u128, - error: SyscallExecutionError, - ) -> Vec { + fn handle_error(&mut self, remaining_gas: &mut u64, error: SyscallExecutionError) -> Vec { // In case of more than one inner call and because each inner call has their own // syscall handler, if there is an unrecoverable error at call `n` it will create a // `NativeExecutionError`. When rolling back, each call from `n-1` to `1` will also @@ -275,7 +264,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn get_block_hash( &mut self, block_number: u64, - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().get_block_hash_gas_cost)?; @@ -285,7 +274,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { } } - fn get_execution_info(&mut self, remaining_gas: &mut u128) -> SyscallResult { + fn get_execution_info(&mut self, remaining_gas: &mut u64) -> SyscallResult { self.pre_execute_syscall( remaining_gas, self.context.gas_costs().get_execution_info_gas_cost, @@ -303,7 +292,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn get_class_hash_at( &mut self, contract_address: Felt, - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult { self.pre_execute_syscall( remaining_gas, @@ -322,10 +311,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { Ok(class_hash.0) } - fn get_execution_info_v2( - &mut self, - remaining_gas: &mut u128, - ) -> SyscallResult { + fn get_execution_info_v2(&mut self, remaining_gas: &mut u64) -> SyscallResult { self.pre_execute_syscall( remaining_gas, self.context.gas_costs().get_execution_info_gas_cost, @@ -346,7 +332,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { contract_address_salt: Felt, calldata: &[Felt], deploy_from_zero: bool, - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult<(Felt, Vec)> { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().deploy_gas_cost)?; @@ -372,41 +358,23 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { caller_address: deployer_address, }; - let mut remaining_gas_u64 = - u64::try_from(*remaining_gas).expect("Failed to convert gas to u64."); - let call_info = execute_deployment( self.state, self.resources, self.context, ctor_context, calldata, - // Warning: converting of reference would create a new reference to different data, - // example: - // let mut a: u128 = 1; - // let a_ref: &mut u128 = &mut a; - // - // let mut b: u64 = u64::try_from(*a_ref).unwrap(); - // - // assert_eq!(b, 1); - // - // b += 1; - // - // assert_eq!(b, 2); - // assert_eq!(a, 1); - &mut remaining_gas_u64, + remaining_gas, ) .map_err(|err| self.handle_error(remaining_gas, err.into()))?; - *remaining_gas = u128::from(remaining_gas_u64); - let constructor_retdata = call_info.execution.retdata.0[..].to_vec(); self.inner_calls.push(call_info); Ok((Felt::from(deployed_contract_address), constructor_retdata)) } - fn replace_class(&mut self, class_hash: Felt, remaining_gas: &mut u128) -> SyscallResult<()> { + fn replace_class(&mut self, class_hash: Felt, remaining_gas: &mut u64) -> SyscallResult<()> { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().replace_class_gas_cost)?; let class_hash = ClassHash(class_hash); @@ -435,7 +403,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { class_hash: Felt, function_selector: Felt, calldata: &[Felt], - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult> { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().library_call_gas_cost)?; @@ -465,7 +433,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { address: Felt, entry_point_selector: Felt, calldata: &[Felt], - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult> { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().call_contract_gas_cost)?; @@ -503,7 +471,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, address_domain: u32, address: Felt, - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().storage_read_gas_cost)?; @@ -530,7 +498,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { address_domain: u32, address: Felt, value: Felt, - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult<()> { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().storage_write_gas_cost)?; @@ -554,7 +522,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, keys: &[Felt], data: &[Felt], - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult<()> { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().emit_event_gas_cost)?; @@ -581,7 +549,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, to_address: Felt, payload: &[Felt], - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult<()> { self.pre_execute_syscall( remaining_gas, @@ -601,7 +569,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { Ok(()) } - fn keccak(&mut self, input: &[u64], remaining_gas: &mut u128) -> SyscallResult { + fn keccak(&mut self, input: &[u64], remaining_gas: &mut u64) -> SyscallResult { self.pre_execute_syscall(remaining_gas, self.context.gas_costs().keccak_gas_cost)?; const KECCAK_FULL_RATE_IN_WORDS: usize = 17; @@ -620,9 +588,9 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { // TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion // works. - let n_rounds_as_u128 = u128::try_from(n_rounds).expect("Failed to convert usize to u128."); + let n_rounds_as_u128 = u64::try_from(n_rounds).expect("Failed to convert usize to u128."); let gas_cost = - n_rounds_as_u128 * u128::from(self.context.gas_costs().keccak_round_cost_gas_cost); + n_rounds_as_u128 * u64::from(self.context.gas_costs().keccak_round_cost_gas_cost); if gas_cost > *remaining_gas { return Err(self.handle_error( @@ -652,7 +620,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _x: U256, _y: U256, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult> { todo!("Implement secp256k1_new syscall."); } @@ -661,7 +629,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _p0: Secp256k1Point, _p1: Secp256k1Point, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult { todo!("Implement secp256k1_add syscall."); } @@ -670,7 +638,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _p: Secp256k1Point, _m: U256, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult { todo!("Implement secp256k1_mul syscall."); } @@ -679,7 +647,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _x: U256, _y_parity: bool, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult> { todo!("Implement secp256k1_get_point_from_x syscall."); } @@ -687,7 +655,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn secp256k1_get_xy( &mut self, _p: Secp256k1Point, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult<(U256, U256)> { todo!("Implement secp256k1_get_xy syscall."); } @@ -696,7 +664,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _x: U256, _y: U256, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult> { todo!("Implement secp256r1_new syscall."); } @@ -705,7 +673,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _p0: Secp256r1Point, _p1: Secp256r1Point, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult { todo!("Implement secp256r1_add syscall."); } @@ -714,7 +682,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _p: Secp256r1Point, _m: U256, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult { todo!("Implement secp256r1_mul syscall."); } @@ -723,7 +691,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, _x: U256, _y_parity: bool, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult> { todo!("Implement secp256r1_get_point_from_x syscall."); } @@ -731,7 +699,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn secp256r1_get_xy( &mut self, _p: Secp256r1Point, - _remaining_gas: &mut u128, + _remaining_gas: &mut u64, ) -> SyscallResult<(U256, U256)> { todo!("Implement secp256r1_get_xy syscall."); } @@ -740,7 +708,7 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { &mut self, prev_state: &mut [u32; 8], current_block: &[u32; 16], - remaining_gas: &mut u128, + remaining_gas: &mut u64, ) -> SyscallResult<()> { self.pre_execute_syscall( remaining_gas, diff --git a/crates/starknet_sierra_compile/build.rs b/crates/starknet_sierra_compile/build.rs index 0d19dda4ef..92e841cbc3 100644 --- a/crates/starknet_sierra_compile/build.rs +++ b/crates/starknet_sierra_compile/build.rs @@ -37,7 +37,8 @@ fn install_starknet_sierra_compile() { #[cfg(feature = "cairo_native")] fn install_starknet_native_compile() { // Set the runtime library path. This is required for Cairo native compilation. - let runtime_library_path = repo_root_dir().join("crates/blockifier/libcairo_native_runtime.a"); + let runtime_library_path = repo_root_dir() + .join("crates/blockifier/cairo_native/target/release/libcairo_native_runtime.a"); println!("cargo:rustc-env=CAIRO_NATIVE_RUNTIME_LIBRARY={}", runtime_library_path.display()); println!("cargo:rerun-if-env-changed=CAIRO_NATIVE_RUNTIME_LIBRARY");