Skip to content

Commit

Permalink
feat(blockifier): add unrecoverable error handling for native
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigo-pino committed Nov 12, 2024
1 parent 3c61872 commit d90688f
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 14 deletions.
5 changes: 5 additions & 0 deletions crates/blockifier/src/execution/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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<SyscallExecutionError>),
#[error(transparent)]
PostExecutionError(#[from] PostExecutionError),
#[error(transparent)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
43 changes: 29 additions & 14 deletions crates/blockifier/src/execution/native/syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -35,6 +34,9 @@ pub struct NativeSyscallHandler<'state> {
// Additional information gathered during execution.
pub read_values: Vec<Felt>,
pub accessed_keys: HashSet<StorageKey, RandomState>,

// It is set if an unrecoverable error happens during syscall execution
pub unrecoverable_error: Option<SyscallExecutionError>,
}

impl<'state> NativeSyscallHandler<'state> {
Expand All @@ -54,6 +56,7 @@ impl<'state> NativeSyscallHandler<'state> {
inner_calls: Vec::new(),
read_values: Vec::new(),
accessed_keys: HashSet::new(),
unrecoverable_error: None,
}
}

Expand Down Expand Up @@ -84,25 +87,18 @@ impl<'state> NativeSyscallHandler<'state> {
Ok(retdata)
}

fn handle_error(
&mut self,
_remaining_gas: &mut u128,
error: SyscallExecutionError,
) -> Vec<Felt> {
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);
Expand All @@ -119,6 +115,25 @@ impl<'state> NativeSyscallHandler<'state> {

Ok(())
}

fn handle_error(
&mut self,
remaining_gas: &mut u128,
error: SyscallExecutionError,
) -> Vec<Felt> {
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> {
Expand Down

0 comments on commit d90688f

Please sign in to comment.