diff --git a/src/execution/execution_entry_point.rs b/src/execution/execution_entry_point.rs index 1069f2d9a..7b7e993a7 100644 --- a/src/execution/execution_entry_point.rs +++ b/src/execution/execution_entry_point.rs @@ -159,7 +159,7 @@ impl ExecutionEntryPoint { #[cfg(feature = "cairo-native")] CompiledClass::Casm { sierra: Some(sierra_program_and_entrypoints), - .. + casm, } => { let mut transactional_state = state.create_transactional()?; @@ -189,6 +189,36 @@ impl ExecutionEntryPoint { n_reverted_steps: 0, }) } + Err(TransactionError::SandboxError(_e)) => { + match self._execute( + state, + resources_manager, + block_context, + tx_execution_context, + casm, + class_hash, + support_reverted, + ) { + Ok(call_info) => Ok(ExecutionResult { + call_info: Some(call_info), + revert_error: None, + n_reverted_steps: 0, + }), + Err(e) => { + if !support_reverted { + return Err(e); + } + + let n_reverted_steps = + (max_steps as usize) - resources_manager.cairo_usage.n_steps; + Ok(ExecutionResult { + call_info: None, + revert_error: Some(e.to_string()), + n_reverted_steps, + }) + } + } + } Err(e) => { if !support_reverted { state.apply_state_update(&StateDiff::from_cached_state( @@ -822,3 +852,138 @@ impl ExecutionEntryPoint { }) } } + +#[cfg(test)] +#[cfg(feature = "cairo-native")] +mod tests { + use std::process::Command; + + use super::*; + #[test] + fn fallback_procedure_sandbox_kill_test() { + let path = std::path::Path::new("starknet_programs/cairo2/fibonacci.cairo"); + + let casm_contract_class_data = + std::fs::read_to_string(path.with_extension("casm")).unwrap(); + let sierra_contract_class_data = + std::fs::read_to_string(path.with_extension("sierra")).unwrap(); + + let casm_contract_class: CasmContractClass = + serde_json::from_str(&casm_contract_class_data).unwrap(); + let sierra_contract_class: cairo_lang_starknet::contract_class::ContractClass = + serde_json::from_str(&sierra_contract_class_data).unwrap(); + + let casm_contract_class = Arc::new(casm_contract_class); + let sierra_contract_class = Arc::new(( + sierra_contract_class.extract_sierra_program().unwrap(), + sierra_contract_class.entry_points_by_type, + )); + + let mut state_reader = crate::state::in_memory_state_reader::InMemoryStateReader::default(); + let cache = crate::state::contract_class_cache::PermanentContractClassCache::default(); + + let class_hash = ClassHash([1; 32]); + let caller_address = Address(1.into()); + let callee_address = Address(1.into()); + + cache.set_contract_class( + class_hash, + CompiledClass::Casm { + casm: casm_contract_class, + sierra: Some(sierra_contract_class), + }, + ); + + state_reader + .address_to_class_hash_mut() + .insert(caller_address.clone(), class_hash); + state_reader + .address_to_nonce_mut() + .insert(callee_address.clone(), Felt252::default()); + + let mut state = CachedState::new(Arc::new(state_reader), Arc::new(cache)); + + state.cache_mut().storage_initial_values_mut().insert( + ( + Address(Felt252::ONE), + crate::utils::felt_to_hash(&10.into()).0, + ), + Felt252::from_bytes_be(&[5; 32]), + ); + + let class_hash = *state + .state_reader + .address_to_class_hash + .get(&caller_address) + .unwrap(); + + let mut block_context = BlockContext::default(); + block_context.block_info_mut().block_number = 30; + + let executor_path = std::env::var("CAIRO_NATIVE_EXECUTOR_PATH") + .map(std::path::PathBuf::from) + .unwrap_or_else(|_| { + std::env::current_dir() + .unwrap() + .join("target/debug/cairo_native_executor") + }); + let mut sandbox = IsolatedExecutor::new(executor_path.as_path()).unwrap(); + + let check_sandbox_pid_before = Command::new("lsof") + .arg("-p") + .arg(sandbox.proc.id().to_string()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .output() + .unwrap(); + + sandbox.kill(); + + let execution_result_native = ExecutionEntryPoint::new( + callee_address.clone(), + vec![1.into(), 1.into(), 11.into()], + Felt252::from_hex("0x112e35f48499939272000bd72eb840e502ca4c3aefa8800992e8defb746e0c9") + .unwrap(), + caller_address.clone(), + crate::EntryPointType::External, + Some(CallType::Delegate), + Some(class_hash), + u128::MAX, + ) + .execute( + &mut state, + &block_context, + &mut ExecutionResourcesManager::default(), + &mut TransactionExecutionContext::new( + Address(Felt252::default()), + Felt252::default(), + Vec::default(), + Default::default(), + 10.into(), + block_context.invoke_tx_max_n_steps(), + *crate::definitions::constants::TRANSACTION_VERSION, + ), + false, + block_context.invoke_tx_max_n_steps(), + None, + Some(&sandbox), + ) + .unwrap(); + + let check_sandbox_pid_after: std::process::Output = Command::new("lsof") + .arg("-p") + .arg(sandbox.proc.id().to_string()) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .output() + .unwrap(); + assert_ne!( + String::from_utf8_lossy(&check_sandbox_pid_after.stderr), + String::from_utf8_lossy(&check_sandbox_pid_before.stdout) + ); + assert_eq!( + execution_result_native.call_info.unwrap().retdata, + vec![Felt252::from(144)] + ); + } +} diff --git a/src/sandboxing/mod.rs b/src/sandboxing/mod.rs index 7730fedd3..b52f42e06 100644 --- a/src/sandboxing/mod.rs +++ b/src/sandboxing/mod.rs @@ -433,6 +433,12 @@ impl IsolatedExecutor { } } } + + #[cfg(test)] + pub(crate) fn kill(&mut self) { + let _ = self.sender.send(Message::Kill.wrap().unwrap()); + let _ = self.proc.kill(); + } } impl Drop for IsolatedExecutor {