diff --git a/crates/blockifier/src/execution/execution_utils.rs b/crates/blockifier/src/execution/execution_utils.rs index 261229fd51..6a1be4190c 100644 --- a/crates/blockifier/src/execution/execution_utils.rs +++ b/crates/blockifier/src/execution/execution_utils.rs @@ -34,6 +34,7 @@ use crate::execution::entry_point::{ EntryPointExecutionResult, }; use crate::execution::errors::PostExecutionError; +use crate::execution::native::entry_point_execution as native_entry_point_execution; use crate::execution::{deprecated_entry_point_execution, entry_point_execution}; use crate::state::errors::StateError; use crate::state::state_api::State; @@ -68,8 +69,14 @@ pub fn execute_entry_point_call( resources, context, ), - ContractClass::V1Native(_contract_class) => { - unimplemented!("Native contract entry point execution is not yet implemented.") + ContractClass::V1Native(contract_class) => { + native_entry_point_execution::execute_entry_point_call( + call, + contract_class, + state, + resources, + context, + ) } } } @@ -267,7 +274,7 @@ pub fn max_fee_for_execution_info(tx_info: &TransactionInfo) -> Felt { TransactionInfo::Current(_) => 0, TransactionInfo::Deprecated(tx_info) => tx_info.max_fee.0, } - .into() + .into() } pub fn format_panic_data(felts: &[Felt]) -> String { diff --git a/crates/blockifier/src/execution/native.rs b/crates/blockifier/src/execution/native.rs index 2cedb78c88..5843e98914 100644 --- a/crates/blockifier/src/execution/native.rs +++ b/crates/blockifier/src/execution/native.rs @@ -1,2 +1,3 @@ +pub mod entry_point_execution; pub mod syscall_handler; pub mod utils; diff --git a/crates/blockifier/src/execution/native/entry_point_execution.rs b/crates/blockifier/src/execution/native/entry_point_execution.rs new file mode 100644 index 0000000000..267fbc836c --- /dev/null +++ b/crates/blockifier/src/execution/native/entry_point_execution.rs @@ -0,0 +1,33 @@ +use cairo_vm::vm::runners::cairo_runner::ExecutionResources; + +use super::syscall_handler::NativeSyscallHandler; +use super::utils::run_native_executor; +use crate::execution::call_info::CallInfo; +use crate::execution::contract_class::NativeContractClassV1; +use crate::execution::entry_point::{ + CallEntryPoint, + EntryPointExecutionContext, + EntryPointExecutionResult, +}; +use crate::state::state_api::State; + +pub fn execute_entry_point_call( + call: CallEntryPoint, + contract_class: NativeContractClassV1, + state: &mut dyn State, + resources: &mut ExecutionResources, + context: &mut EntryPointExecutionContext, +) -> EntryPointExecutionResult { + let function_id = contract_class.get_entry_point(&call)?; + + let syscall_handler: NativeSyscallHandler<'_> = NativeSyscallHandler::new( + state, + call.caller_address, + call.storage_address, + call.entry_point_selector, + resources, + context, + ); + + run_native_executor(&contract_class.executor, function_id, call, syscall_handler) +} diff --git a/crates/blockifier/src/execution/native/utils.rs b/crates/blockifier/src/execution/native/utils.rs index b57ead7d32..0c4cf14d0d 100644 --- a/crates/blockifier/src/execution/native/utils.rs +++ b/crates/blockifier/src/execution/native/utils.rs @@ -1,18 +1,108 @@ +use std::collections::{HashMap, HashSet}; +use std::hash::RandomState; + +use cairo_lang_sierra::ids::FunctionId; use cairo_lang_starknet_classes::contract_class::ContractEntryPoint; -use num_traits::ToBytes; +use cairo_native::execution_result::ContractExecutionResult; +use cairo_native::executor::AotNativeExecutor; +use cairo_vm::vm::runners::cairo_runner::ExecutionResources; +use itertools::Itertools; use starknet_api::core::EntryPointSelector; +use starknet_api::state::StorageKey; use starknet_types_core::felt::Felt; +use crate::execution::call_info::{ + CallExecution, + CallInfo, + OrderedEvent, + OrderedL2ToL1Message, + Retdata, +}; +use crate::execution::entry_point::{CallEntryPoint, EntryPointExecutionResult}; +use crate::execution::errors::EntryPointExecutionError; +use crate::execution::native::syscall_handler::NativeSyscallHandler; + #[cfg(test)] #[path = "utils_test.rs"] pub mod test; +// An arbitrary number, chosen to avoid accidentally aligning with actually calculated gas +// To be deleted once cairo native gas handling can be used. +pub const NATIVE_GAS_PLACEHOLDER: u64 = 12; + pub fn contract_entrypoint_to_entrypoint_selector( entrypoint: &ContractEntryPoint, ) -> EntryPointSelector { EntryPointSelector(Felt::from(&entrypoint.selector)) } +pub fn run_native_executor( + native_executor: &AotNativeExecutor, + function_id: &FunctionId, + call: CallEntryPoint, + mut syscall_handler: NativeSyscallHandler<'_>, +) -> EntryPointExecutionResult { + let execution_result = native_executor.invoke_contract_dynamic( + function_id, + &call.calldata.0, + Some(call.initial_gas.into()), + &mut syscall_handler, + ); + + let run_result = match execution_result { + Err(runner_err) => { + Err(EntryPointExecutionError::NativeUnexpectedError { source: runner_err }) + } + Ok(res) if res.failure_flag => Err(EntryPointExecutionError::NativeExecutionError { + info: if !res.return_values.is_empty() { + decode_felts_as_str(&res.return_values) + } else { + String::from("Unknown error") + }, + }), + Ok(res) => Ok(res), + }?; + + Ok(create_callinfo( + call.clone(), + run_result, + syscall_handler.events, + syscall_handler.l2_to_l1_messages, + syscall_handler.inner_calls, + syscall_handler.storage_read_values, + syscall_handler.accessed_storage_keys, + )) +} + +pub fn create_callinfo( + call: CallEntryPoint, + run_result: ContractExecutionResult, + events: Vec, + l2_to_l1_messages: Vec, + inner_calls: Vec, + storage_read_values: Vec, + accessed_storage_keys: HashSet, +) -> CallInfo { + CallInfo { + call, + execution: CallExecution { + retdata: Retdata(run_result.return_values), + events, + l2_to_l1_messages, + failed: run_result.failure_flag, + gas_consumed: NATIVE_GAS_PLACEHOLDER, + }, + resources: ExecutionResources { + n_steps: 0, + n_memory_holes: 0, + builtin_instance_counter: HashMap::default(), + }, + inner_calls, + storage_read_values, + accessed_storage_keys, + } +} + pub fn encode_str_as_felts(msg: &str) -> Vec { const CHUNK_SIZE: usize = 32;