Skip to content

Commit

Permalink
feat: entry point execution logic
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigo-pino committed Oct 6, 2024
1 parent 7ed3efe commit 3e3c038
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 5 deletions.
8 changes: 8 additions & 0 deletions crates/blockifier/src/execution/errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashSet;

use cairo_native::error::Error as NativeRunnerError;
use cairo_vm::types::builtin_name::BuiltinName;
use cairo_vm::types::errors::math_errors::MathError;
use cairo_vm::vm::errors::cairo_run_errors::CairoRunError;
Expand Down Expand Up @@ -87,6 +88,13 @@ pub enum EntryPointExecutionError {
InternalError(String),
#[error("Invalid input: {input_descriptor}; {info}")]
InvalidExecutionInput { input_descriptor: String, info: String },
#[error("Native execution error: {info}")]
NativeExecutionError { info: String },
#[error("Native unexpected error: {source}")]
NativeUnexpectedError {
#[source]
source: NativeRunnerError,
},
#[error(transparent)]
PostExecutionError(#[from] PostExecutionError),
#[error(transparent)]
Expand Down
16 changes: 11 additions & 5 deletions crates/blockifier/src/execution/execution_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ use starknet_api::deprecated_contract_class::Program as DeprecatedProgram;
use starknet_api::transaction::Calldata;
use starknet_types_core::felt::Felt;

use super::entry_point::ConstructorEntryPointExecutionResult;
use super::errors::ConstructorEntryPointExecutionError;
use crate::execution::call_info::{CallInfo, Retdata};
use crate::execution::contract_class::{ContractClass, TrackedResource};
use crate::execution::entry_point::{
execute_constructor_entry_point,
CallEntryPoint,
ConstructorContext,
ConstructorEntryPointExecutionResult,
EntryPointExecutionContext,
EntryPointExecutionResult,
};
use crate::execution::errors::PostExecutionError;
use crate::execution::errors::{ConstructorEntryPointExecutionError, 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;
Expand Down Expand Up @@ -93,8 +93,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,
)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/blockifier/src/execution/native.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod entry_point_execution;
pub mod syscall_handler;
pub mod utils;

Expand Down
111 changes: 111 additions & 0 deletions crates/blockifier/src/execution/native/entry_point_execution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use std::collections::HashMap;

use cairo_lang_sierra::ids::FunctionId;
use cairo_native::execution_result::ContractExecutionResult;
use cairo_native::executor::AotNativeExecutor;
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;

use super::utils::decode_felts_as_str;
// use c::utils::run_native_executor;
use crate::execution::call_info::{CallExecution, CallInfo, Retdata};
use crate::execution::contract_class::{NativeContractClassV1, TrackedResource};
use crate::execution::entry_point::{
CallEntryPoint,
EntryPointExecutionContext,
EntryPointExecutionResult,
};
use crate::execution::errors::EntryPointExecutionError;
use crate::execution::native::syscall_handler::NativeSyscallHandler;
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<CallInfo> {
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)
}

fn run_native_executor(
native_executor: &AotNativeExecutor,
function_id: &FunctionId,
call: CallEntryPoint,
mut syscall_handler: NativeSyscallHandler<'_>,
) -> EntryPointExecutionResult<CallInfo> {
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),
}?;

create_callinfo(call.clone(), run_result, syscall_handler)
}

fn create_callinfo(
call: CallEntryPoint,
run_result: ContractExecutionResult,
syscall_handler: NativeSyscallHandler<'_>,
) -> Result<CallInfo, EntryPointExecutionError> {
let gas_consumed = {
// We can use `.unwrap()` directly in both cases because the most significant bit is could
// be only 63 here (128 = 64 + 64).
let low: u64 = (run_result.remaining_gas & ((1u128 << 64) - 1)).try_into().unwrap();
let high: u64 = (run_result.remaining_gas >> 64).try_into().unwrap();
if high != 0 {
return Err(EntryPointExecutionError::NativeExecutionError {
info: "Overflow: gas consumed bigger than 64 bit".into(),
});
}
call.initial_gas - low
};

Ok(CallInfo {
call,
execution: CallExecution {
retdata: Retdata(run_result.return_values),
events: syscall_handler.events,
l2_to_l1_messages: syscall_handler.l2_to_l1_messages,
failed: run_result.failure_flag,
gas_consumed,
},
// todo(rodrigo): execution resources rely heavily on how the VM work, therefore
// the dummy values
resources: ExecutionResources {
n_steps: 0,
n_memory_holes: 0,
builtin_instance_counter: HashMap::default(),
},
inner_calls: syscall_handler.inner_calls,
storage_read_values: syscall_handler.read_values,
accessed_storage_keys: syscall_handler.accessed_keys,
tracked_resource: TrackedResource::SierraGas,
})
}

0 comments on commit 3e3c038

Please sign in to comment.