Skip to content

Commit 3992a18

Browse files
committed
Implement chetable syscall handler for native, implement cheating get_execution_info_v2
1 parent 821bc3f commit 3992a18

File tree

4 files changed

+657
-4
lines changed

4 files changed

+657
-4
lines changed

crates/cheatnet/src/runtime_extensions/native/execution.rs

Lines changed: 193 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
use crate::runtime_extensions::call_to_blockifier_runtime_extension::execution::entry_point::{
22
CallInfoWithExecutionData, ContractClassEntryPointExecutionResult,
33
};
4+
use crate::runtime_extensions::native::native_syscall_handler::CheatableNativeSyscallHandler;
45
use crate::state::CheatnetState;
5-
use blockifier::execution::entry_point::{EntryPointExecutionContext, ExecutableCallEntryPoint};
6+
use blockifier::execution::call_info::{BuiltinCounterMap, CallExecution, CallInfo, Retdata};
7+
use blockifier::execution::contract_class::TrackedResource;
8+
use blockifier::execution::entry_point::{
9+
EntryPointExecutionContext, EntryPointExecutionResult, ExecutableCallEntryPoint,
10+
};
11+
use blockifier::execution::errors::{
12+
EntryPointExecutionError, PostExecutionError, PreExecutionError,
13+
};
614
use blockifier::execution::native::contract_class::NativeCompiledClassV1;
7-
use blockifier::execution::native::entry_point_execution::execute_entry_point_call;
15+
use blockifier::execution::native::syscall_handler::NativeSyscallHandler;
816
use blockifier::state::state_api::State;
17+
use blockifier::transaction::objects::ExecutionResourcesTraits;
18+
use blockifier::utils::add_maps;
19+
use cairo_native::execution_result::{BuiltinStats, ContractExecutionResult};
20+
use cairo_native::utils::BuiltinCosts;
21+
use cairo_vm::types::builtin_name::BuiltinName;
922
use std::default::Default;
1023

1124
pub(crate) fn execute_entry_point_call_native(
@@ -15,8 +28,13 @@ pub(crate) fn execute_entry_point_call_native(
1528
cheatnet_state: &mut CheatnetState, // Added parameter
1629
context: &mut EntryPointExecutionContext,
1730
) -> ContractClassEntryPointExecutionResult {
31+
let syscall_handler = CheatableNativeSyscallHandler {
32+
cheatnet_state,
33+
native_syscall_handler: &mut NativeSyscallHandler::new(call.clone(), state, context),
34+
};
35+
1836
// TODO error handling
19-
let call_info = execute_entry_point_call(call, native_compiled_class_v1, state, context)
37+
let call_info = execute_entry_point_call(call, native_compiled_class_v1, syscall_handler)
2038
.expect("Native execution failed");
2139

2240
Ok(CallInfoWithExecutionData {
@@ -26,3 +44,175 @@ pub(crate) fn execute_entry_point_call_native(
2644
vm_trace: None,
2745
})
2846
}
47+
48+
// Copied from blockifier
49+
// todo(rodrigo): add an `entry point not found` test for Native
50+
#[allow(clippy::result_large_err)]
51+
pub fn execute_entry_point_call(
52+
call: ExecutableCallEntryPoint,
53+
compiled_class: NativeCompiledClassV1,
54+
// state: &mut dyn State,
55+
// context: &mut EntryPointExecutionContext,
56+
mut syscall_handler: CheatableNativeSyscallHandler,
57+
) -> EntryPointExecutionResult<CallInfo> {
58+
let entry_point = compiled_class.get_entry_point(&call.type_and_selector())?;
59+
60+
// let mut syscall_handler: NativeSyscallHandler<'_> =
61+
// NativeSyscallHandler::new(call, state, context);
62+
63+
let gas_costs = &syscall_handler
64+
.native_syscall_handler
65+
.base
66+
.context
67+
.gas_costs();
68+
let builtin_costs = BuiltinCosts {
69+
// todo(rodrigo): Unsure of what value `const` means, but 1 is the right value.
70+
r#const: 1,
71+
pedersen: gas_costs.builtins.pedersen,
72+
bitwise: gas_costs.builtins.bitwise,
73+
ecop: gas_costs.builtins.ecop,
74+
poseidon: gas_costs.builtins.poseidon,
75+
add_mod: gas_costs.builtins.add_mod,
76+
mul_mod: gas_costs.builtins.mul_mod,
77+
};
78+
79+
// Pre-charge entry point's initial budget to ensure sufficient gas for executing a minimal
80+
// entry point code. When redepositing is used, the entry point is aware of this pre-charge
81+
// and adjusts the gas counter accordingly if a smaller amount of gas is required.
82+
let initial_budget = syscall_handler
83+
.native_syscall_handler
84+
.base
85+
.context
86+
.gas_costs()
87+
.base
88+
.entry_point_initial_budget;
89+
let call_initial_gas = syscall_handler
90+
.native_syscall_handler
91+
.base
92+
.call
93+
.initial_gas
94+
.checked_sub(initial_budget)
95+
.ok_or(PreExecutionError::InsufficientEntryPointGas)?;
96+
97+
let execution_result = compiled_class.executor.run(
98+
entry_point.selector.0,
99+
&syscall_handler
100+
.native_syscall_handler
101+
.base
102+
.call
103+
.calldata
104+
.0
105+
.clone(),
106+
call_initial_gas,
107+
Some(builtin_costs),
108+
&mut syscall_handler,
109+
);
110+
111+
syscall_handler.native_syscall_handler.finalize();
112+
113+
let call_result = execution_result.map_err(EntryPointExecutionError::NativeUnexpectedError)?;
114+
115+
// TODO consider modifying this so it doesn't use take internally
116+
if let Some(error) = syscall_handler.unrecoverable_error() {
117+
return Err(EntryPointExecutionError::NativeUnrecoverableError(
118+
Box::new(error),
119+
));
120+
}
121+
122+
create_callinfo(call_result, syscall_handler)
123+
}
124+
125+
// Copied from blockifier
126+
#[allow(clippy::result_large_err)]
127+
fn create_callinfo(
128+
call_result: ContractExecutionResult,
129+
syscall_handler: CheatableNativeSyscallHandler<'_>,
130+
) -> Result<CallInfo, EntryPointExecutionError> {
131+
let remaining_gas = call_result.remaining_gas;
132+
133+
if remaining_gas > syscall_handler.native_syscall_handler.base.call.initial_gas {
134+
return Err(PostExecutionError::MalformedReturnData {
135+
error_message: format!(
136+
"Unexpected remaining gas. Used gas is greater than initial gas: {} > {}",
137+
remaining_gas, syscall_handler.native_syscall_handler.base.call.initial_gas
138+
),
139+
}
140+
.into());
141+
}
142+
143+
let gas_consumed = syscall_handler.native_syscall_handler.base.call.initial_gas - remaining_gas;
144+
let vm_resources = CallInfo::summarize_vm_resources(
145+
syscall_handler
146+
.native_syscall_handler
147+
.base
148+
.inner_calls
149+
.iter(),
150+
);
151+
152+
// Retrieve the builtin counts from the syscall handler
153+
let version_constants = syscall_handler
154+
.native_syscall_handler
155+
.base
156+
.context
157+
.versioned_constants();
158+
let syscall_builtin_counts = version_constants
159+
.get_additional_os_syscall_resources(
160+
&syscall_handler.native_syscall_handler.base.syscalls_usage,
161+
)
162+
.filter_unused_builtins()
163+
.prover_builtins();
164+
let entry_point_builtins = builtin_stats_to_builtin_counter_map(call_result.builtin_stats);
165+
let mut builtin_counters = syscall_builtin_counts;
166+
add_maps(&mut builtin_counters, &entry_point_builtins);
167+
168+
Ok(CallInfo {
169+
call: syscall_handler
170+
.native_syscall_handler
171+
.base
172+
.call
173+
.clone()
174+
.into(),
175+
execution: CallExecution {
176+
retdata: Retdata(call_result.return_values),
177+
events: syscall_handler.native_syscall_handler.base.events.clone(),
178+
cairo_native: true,
179+
l2_to_l1_messages: syscall_handler
180+
.native_syscall_handler
181+
.base
182+
.l2_to_l1_messages
183+
.clone(),
184+
failed: call_result.failure_flag,
185+
gas_consumed,
186+
},
187+
resources: vm_resources,
188+
inner_calls: syscall_handler
189+
.native_syscall_handler
190+
.base
191+
.inner_calls
192+
.clone(),
193+
storage_access_tracker: syscall_handler
194+
.native_syscall_handler
195+
.base
196+
.storage_access_tracker
197+
.clone(),
198+
tracked_resource: TrackedResource::SierraGas,
199+
builtin_counters,
200+
})
201+
}
202+
203+
fn builtin_stats_to_builtin_counter_map(builtin_stats: BuiltinStats) -> BuiltinCounterMap {
204+
let builtins = [
205+
(BuiltinName::range_check, builtin_stats.range_check),
206+
(BuiltinName::pedersen, builtin_stats.pedersen),
207+
(BuiltinName::bitwise, builtin_stats.bitwise),
208+
(BuiltinName::ec_op, builtin_stats.ec_op),
209+
(BuiltinName::poseidon, builtin_stats.poseidon),
210+
(BuiltinName::range_check96, builtin_stats.range_check96),
211+
(BuiltinName::add_mod, builtin_stats.add_mod),
212+
(BuiltinName::mul_mod, builtin_stats.mul_mod),
213+
];
214+
builtins
215+
.into_iter()
216+
.filter(|(_, count)| *count > 0)
217+
.collect()
218+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod execution;
2+
pub mod native_syscall_handler;

0 commit comments

Comments
 (0)