diff --git a/crates/blockifier/src/execution/errors.rs b/crates/blockifier/src/execution/errors.rs index 3c7d79d4de..5377f33fe6 100644 --- a/crates/blockifier/src/execution/errors.rs +++ b/crates/blockifier/src/execution/errors.rs @@ -16,6 +16,8 @@ use thiserror::Error; use crate::execution::entry_point::ConstructorContext; use crate::execution::stack_trace::Cairo1RevertStack; +#[cfg(feature = "cairo_native")] +use crate::execution::syscalls::hint_processor::SyscallExecutionError; use crate::state::errors::StateError; // TODO(AlonH, 21/12/2022): Implement Display for all types that appear in errors. @@ -91,6 +93,9 @@ pub enum EntryPointExecutionError { #[cfg(feature = "cairo_native")] #[error(transparent)] NativeUnexpectedError(#[from] NativeError), + #[cfg(feature = "cairo_native")] + #[error(transparent)] + NativeExecutionError(#[from] Box), #[error(transparent)] PostExecutionError(#[from] PostExecutionError), #[error(transparent)] diff --git a/crates/blockifier/src/execution/native/entry_point_execution.rs b/crates/blockifier/src/execution/native/entry_point_execution.rs index 2b1d22b19d..7b23d278ea 100644 --- a/crates/blockifier/src/execution/native/entry_point_execution.rs +++ b/crates/blockifier/src/execution/native/entry_point_execution.rs @@ -35,6 +35,11 @@ pub fn execute_entry_point_call( ); let call_result = execution_result.map_err(EntryPointExecutionError::NativeUnexpectedError)?; + + if let Some(error) = syscall_handler.unrecoverable_error { + return Err(EntryPointExecutionError::NativeExecutionError(Box::new(error))); + } + create_callinfo(call_result, syscall_handler) } diff --git a/crates/blockifier/src/execution/native/syscall_handler.rs b/crates/blockifier/src/execution/native/syscall_handler.rs index 3de786bc26..c40dbbbf7c 100644 --- a/crates/blockifier/src/execution/native/syscall_handler.rs +++ b/crates/blockifier/src/execution/native/syscall_handler.rs @@ -10,7 +10,6 @@ use cairo_native::starknet::{ SyscallResult, U256, }; -use cairo_native::starknet_stub::encode_str_as_felts; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use starknet_api::state::StorageKey; use starknet_types_core::felt::Felt; @@ -35,6 +34,9 @@ pub struct NativeSyscallHandler<'state> { // Additional information gathered during execution. pub read_values: Vec, pub accessed_keys: HashSet, + + // It is set if an unrecoverable error happens during syscall execution + pub unrecoverable_error: Option, } impl<'state> NativeSyscallHandler<'state> { @@ -54,6 +56,7 @@ impl<'state> NativeSyscallHandler<'state> { inner_calls: Vec::new(), read_values: Vec::new(), accessed_keys: HashSet::new(), + unrecoverable_error: None, } } @@ -84,25 +87,18 @@ impl<'state> NativeSyscallHandler<'state> { Ok(retdata) } - fn handle_error( - &mut self, - _remaining_gas: &mut u128, - error: SyscallExecutionError, - ) -> Vec { - match error { - SyscallExecutionError::SyscallError { error_data } => error_data, - // unrecoverable errors are yet to be implemented - _ => encode_str_as_felts(&error.to_string()), - } - } - - /// Handles all gas-related logics. In native, + /// Handles all gas-related logics and perform additional checks. In native, /// we need to explicitly call this method at the beginning of each syscall. fn pre_execute_syscall( &mut self, remaining_gas: &mut u128, syscall_gas_cost: u64, ) -> SyscallResult<()> { + if self.unrecoverable_error.is_some() { + // An unrecoverable error was found in a previous syscall, we return immediatly to + // accelerate the end of the execution. The returned data is not important + 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); @@ -119,6 +115,25 @@ impl<'state> NativeSyscallHandler<'state> { Ok(()) } + + fn handle_error( + &mut self, + remaining_gas: &mut u128, + error: SyscallExecutionError, + ) -> Vec { + match error { + SyscallExecutionError::SyscallError { error_data } => error_data, + _ => { + assert!( + self.unrecoverable_error.is_none(), + "Trying to set an unrecoverable error twice in Native Syscall Handler" + ); + self.unrecoverable_error = Some(error); + *remaining_gas = 0; + vec![] + } + } + } } impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> {