Skip to content

Commit f92814d

Browse files
Added signal mechanism to Extensions (#1605)
**Stack**: - #1624 - #1605⚠️ *Part of a stack created by [spr](https://github.com/ejoffe/spr). Do not merge manually using the UI - doing so may have unexpected results.*
1 parent 2f3775b commit f92814d

File tree

1 file changed

+163
-45
lines changed

1 file changed

+163
-45
lines changed

crates/runtime/src/lib.rs

Lines changed: 163 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use blockifier::execution::syscalls::SyscallResult;
1111

1212
use cairo_felt::Felt252;
1313
use cairo_lang_casm::hints::{Hint, StarknetHint};
14-
use cairo_lang_casm::operand::ResOperand;
14+
use cairo_lang_casm::operand::{CellRef, ResOperand};
1515
use cairo_lang_runner::casm_run::{
1616
extract_buffer, extract_relocatable, get_ptr, vm_get_range, MemBuffer,
1717
};
@@ -75,6 +75,17 @@ impl<'a> ResourceTracker for StarknetRuntime<'a> {
7575
}
7676
}
7777

78+
impl<'a> SignalPropagator for StarknetRuntime<'a> {
79+
fn propagate_system_call_signal(
80+
&mut self,
81+
_selector: DeprecatedSyscallSelector,
82+
_vm: &mut VirtualMachine,
83+
) {
84+
}
85+
86+
fn propagate_cheatcode_signal(&mut self, _selector: &str, _inputs: Vec<Felt252>) {}
87+
}
88+
7889
fn parse_selector(selector: &BigIntAsHex) -> Result<String, HintError> {
7990
let selector = &selector.value.to_bytes_be().1;
8091
let selector = std::str::from_utf8(selector).map_err(|_| {
@@ -159,49 +170,21 @@ impl<Extension: ExtensionLogic> HintProcessorLogic for ExtendedRuntime<Extension
159170
output_end,
160171
} = starknet_hint
161172
{
162-
let selector = parse_selector(selector)?;
163-
let inputs = fetch_cheatcode_input(vm, input_start, input_end)?;
164-
165-
if let CheatcodeHandlingResult::Handled(res) = self.extension.handle_cheatcode(
166-
&selector,
167-
inputs,
168-
&mut self.extended_runtime,
169-
)? {
170-
let mut buffer = MemBuffer::new_segment(vm);
171-
let result_start = buffer.ptr;
172-
buffer
173-
.write_data(res.iter())
174-
.expect("Failed to insert cheatcode result to memory");
175-
let result_end = buffer.ptr;
176-
insert_value_to_cellref!(vm, output_start, result_start)?;
177-
insert_value_to_cellref!(vm, output_end, result_end)?;
178-
return Ok(());
179-
}
180-
}
181-
182-
if let StarknetHint::SystemCall { system } = starknet_hint {
183-
let (cell, offset) = extract_buffer(system);
184-
let system_ptr = get_ptr(vm, cell, &offset)?;
185-
186-
self.verify_syscall_ptr(system_ptr)?;
187-
188-
// We peek into memory to check the selector
189-
let selector = DeprecatedSyscallSelector::try_from(felt_to_stark_felt(
190-
&vm.get_integer(*self.get_mut_syscall_ptr()).unwrap(),
191-
))?;
192-
193-
if let SyscallHandlingResult::Handled(()) =
194-
self.extension
195-
.override_system_call(selector, vm, &mut self.extended_runtime)?
196-
{
197-
return Ok(());
198-
}
199-
let res = self
200-
.extended_runtime
201-
.execute_hint(vm, exec_scopes, hint_data, constants);
202-
self.extension
203-
.post_syscall_hook(&selector, &mut self.extended_runtime);
204-
return res;
173+
return self.execute_cheatcode_hint(
174+
vm,
175+
exec_scopes,
176+
hint_data,
177+
constants,
178+
selector,
179+
&VmIoPointers {
180+
input_start,
181+
input_end,
182+
output_start,
183+
output_end,
184+
},
185+
);
186+
} else if let StarknetHint::SystemCall { system } = starknet_hint {
187+
return self.execute_syscall_hint(vm, exec_scopes, hint_data, constants, system);
205188
}
206189
}
207190
self.extended_runtime
@@ -220,6 +203,117 @@ impl<Extension: ExtensionLogic> HintProcessorLogic for ExtendedRuntime<Extension
220203
}
221204
}
222205

206+
struct VmIoPointers<'a> {
207+
input_start: &'a ResOperand,
208+
input_end: &'a ResOperand,
209+
output_start: &'a CellRef,
210+
output_end: &'a CellRef,
211+
}
212+
213+
impl<Extension: ExtensionLogic> ExtendedRuntime<Extension> {
214+
fn execute_cheatcode_hint(
215+
&mut self,
216+
vm: &mut VirtualMachine,
217+
exec_scopes: &mut ExecutionScopes,
218+
hint_data: &Box<dyn Any>,
219+
constants: &HashMap<String, Felt252>,
220+
selector: &BigIntAsHex,
221+
vm_io_ptrs: &VmIoPointers,
222+
) -> Result<(), HintError> {
223+
let selector = parse_selector(selector)?;
224+
let inputs = fetch_cheatcode_input(vm, vm_io_ptrs.input_start, vm_io_ptrs.input_end)?;
225+
226+
if let CheatcodeHandlingResult::Handled(res) = self.extension.handle_cheatcode(
227+
&selector,
228+
inputs.clone(),
229+
&mut self.extended_runtime,
230+
)? {
231+
let mut buffer = MemBuffer::new_segment(vm);
232+
let result_start = buffer.ptr;
233+
buffer
234+
.write_data(res.iter())
235+
.expect("Failed to insert cheatcode result to memory");
236+
let result_end = buffer.ptr;
237+
let output_start = vm_io_ptrs.output_start;
238+
let output_end = vm_io_ptrs.output_end;
239+
insert_value_to_cellref!(vm, output_start, result_start)?;
240+
insert_value_to_cellref!(vm, output_end, result_end)?;
241+
self.propagate_cheatcode_signal(&selector, inputs);
242+
Ok(())
243+
} else {
244+
let res = self
245+
.extended_runtime
246+
.execute_hint(vm, exec_scopes, hint_data, constants);
247+
self.extension
248+
.handle_cheatcode_signal(&selector, inputs, &mut self.extended_runtime);
249+
res
250+
}
251+
}
252+
fn execute_syscall_hint(
253+
&mut self,
254+
vm: &mut VirtualMachine,
255+
exec_scopes: &mut ExecutionScopes,
256+
hint_data: &Box<dyn Any>,
257+
constants: &HashMap<String, Felt252>,
258+
system: &ResOperand,
259+
) -> Result<(), HintError> {
260+
let (cell, offset) = extract_buffer(system);
261+
let system_ptr = get_ptr(vm, cell, &offset)?;
262+
263+
self.verify_syscall_ptr(system_ptr)?;
264+
265+
// We peek into memory to check the selector
266+
let selector = DeprecatedSyscallSelector::try_from(felt_to_stark_felt(
267+
&vm.get_integer(*self.get_mut_syscall_ptr()).unwrap(),
268+
))?;
269+
270+
if let SyscallHandlingResult::Handled(()) =
271+
self.extension
272+
.override_system_call(selector, vm, &mut self.extended_runtime)?
273+
{
274+
self.propagate_system_call_signal(selector, vm);
275+
Ok(())
276+
} else {
277+
let res = self
278+
.extended_runtime
279+
.execute_hint(vm, exec_scopes, hint_data, constants);
280+
self.extension
281+
.post_syscall_hook(&selector, &mut self.extended_runtime);
282+
res
283+
}
284+
}
285+
}
286+
287+
pub trait SignalPropagator {
288+
fn propagate_system_call_signal(
289+
&mut self,
290+
selector: DeprecatedSyscallSelector,
291+
vm: &mut VirtualMachine,
292+
);
293+
294+
fn propagate_cheatcode_signal(&mut self, selector: &str, inputs: Vec<Felt252>);
295+
}
296+
297+
impl<Extension: ExtensionLogic> SignalPropagator for ExtendedRuntime<Extension> {
298+
fn propagate_system_call_signal(
299+
&mut self,
300+
selector: DeprecatedSyscallSelector,
301+
vm: &mut VirtualMachine,
302+
) {
303+
self.extended_runtime
304+
.propagate_system_call_signal(selector, vm);
305+
self.extension
306+
.handle_system_call_signal(selector, vm, &mut self.extended_runtime);
307+
}
308+
309+
fn propagate_cheatcode_signal(&mut self, selector: &str, inputs: Vec<Felt252>) {
310+
self.extended_runtime
311+
.propagate_cheatcode_signal(selector, inputs.clone());
312+
self.extension
313+
.handle_cheatcode_signal(selector, inputs, &mut self.extended_runtime);
314+
}
315+
}
316+
223317
impl<Extension: ExtensionLogic> SyscallPtrAccess for ExtendedRuntime<Extension> {
224318
fn get_mut_syscall_ptr(&mut self) -> &mut Relocatable {
225319
self.extended_runtime.get_mut_syscall_ptr()
@@ -263,7 +357,7 @@ pub enum CheatcodeHandlingResult {
263357
}
264358

265359
pub trait ExtensionLogic {
266-
type Runtime: HintProcessor + SyscallPtrAccess;
360+
type Runtime: HintProcessor + SyscallPtrAccess + SignalPropagator;
267361

268362
fn override_system_call(
269363
&mut self,
@@ -291,6 +385,30 @@ pub trait ExtensionLogic {
291385
) -> Result<CheatcodeHandlingResult, EnhancedHintError> {
292386
Ok(CheatcodeHandlingResult::Forwarded)
293387
}
388+
389+
/// Different from `override_system_call` because it cannot be overridden,
390+
/// always receives a signal and cannot return an error
391+
/// Signals are executed in reverse order to normal syscall handlers
392+
/// Signals are executed after syscall is handled
393+
fn handle_system_call_signal(
394+
&mut self,
395+
_selector: DeprecatedSyscallSelector,
396+
_vm: &mut VirtualMachine,
397+
_extended_runtime: &mut Self::Runtime,
398+
) {
399+
}
400+
401+
/// Different from `handle_cheadcode` because it cannot be overridden,
402+
/// always receives a signal and cannot return an error
403+
/// Signals are executed in reverse order to normal cheatcode handlers
404+
/// Signals are executed after cheatcode is handled
405+
fn handle_cheatcode_signal(
406+
&mut self,
407+
_selector: &str,
408+
_inputs: Vec<Felt252>,
409+
_extended_runtime: &mut Self::Runtime,
410+
) {
411+
}
294412
}
295413

296414
// All errors that can be thrown from the hint executor have to be added here,

0 commit comments

Comments
 (0)