@@ -3,9 +3,13 @@ use std::collections::HashSet;
3
3
use cairo_vm:: types:: builtin_name:: BuiltinName ;
4
4
use cairo_vm:: types:: layout_name:: LayoutName ;
5
5
use cairo_vm:: types:: relocatable:: { MaybeRelocatable , Relocatable } ;
6
+ use cairo_vm:: vm:: errors:: cairo_run_errors:: CairoRunError ;
7
+ use cairo_vm:: vm:: errors:: memory_errors:: MemoryError ;
6
8
use cairo_vm:: vm:: errors:: vm_errors:: VirtualMachineError ;
9
+ use cairo_vm:: vm:: runners:: builtin_runner:: BuiltinRunner ;
7
10
use cairo_vm:: vm:: runners:: cairo_runner:: { CairoArg , CairoRunner , ExecutionResources } ;
8
- use num_traits:: ToPrimitive ;
11
+ use cairo_vm:: vm:: security:: verify_secure_runner;
12
+ use num_traits:: { ToPrimitive , Zero } ;
9
13
use starknet_api:: felt;
10
14
use starknet_types_core:: felt:: Felt ;
11
15
@@ -17,6 +21,7 @@ use crate::execution::entry_point::{
17
21
use crate :: execution:: errors:: { EntryPointExecutionError , PostExecutionError , PreExecutionError } ;
18
22
use crate :: execution:: execution_utils:: {
19
23
read_execution_retdata, write_felt, write_maybe_relocatable, Args , ReadOnlySegments ,
24
+ SEGMENT_ARENA_BUILTIN_SIZE ,
20
25
} ;
21
26
use crate :: execution:: syscalls:: hint_processor:: SyscallHintProcessor ;
22
27
use crate :: state:: state_api:: State ;
@@ -157,7 +162,6 @@ pub fn initialize_execution_context<'a>(
157
162
BuiltinName :: bitwise,
158
163
BuiltinName :: ec_op,
159
164
BuiltinName :: ecdsa,
160
- BuiltinName :: output,
161
165
BuiltinName :: pedersen,
162
166
BuiltinName :: poseidon,
163
167
BuiltinName :: range_check,
@@ -280,17 +284,86 @@ pub fn run_entry_point(
280
284
args : Args ,
281
285
program_segment_size : usize ,
282
286
) -> EntryPointExecutionResult < ( ) > {
283
- let verify_secure = true ;
287
+ // Note that we run `verify_secure_runner` manually after filling the holes in the rc96 segment.
288
+ let verify_secure = false ;
284
289
let args: Vec < & CairoArg > = args. iter ( ) . collect ( ) ;
285
- let result = runner. run_from_entrypoint (
290
+ runner. run_from_entrypoint (
286
291
entry_point. pc ( ) ,
287
292
& args,
288
293
verify_secure,
289
294
Some ( program_segment_size) ,
290
295
hint_processor,
291
- ) ;
296
+ ) ?;
297
+
298
+ maybe_fill_holes ( entry_point, runner) ?;
292
299
293
- Ok ( result?)
300
+ verify_secure_runner ( runner, false , Some ( program_segment_size) )
301
+ . map_err ( CairoRunError :: VirtualMachine ) ?;
302
+
303
+ Ok ( ( ) )
304
+ }
305
+
306
+ /// Fills the holes after running the entry point.
307
+ /// Currently only fills the holes in the rc96 segment.
308
+ fn maybe_fill_holes (
309
+ entry_point : EntryPointV1 ,
310
+ runner : & mut CairoRunner ,
311
+ ) -> Result < ( ) , EntryPointExecutionError > {
312
+ let Some ( rc96_offset) = entry_point
313
+ . builtins
314
+ . iter ( )
315
+ . rev ( )
316
+ . position ( |name| name. as_str ( ) == BuiltinName :: range_check96. to_str_with_suffix ( ) )
317
+ else {
318
+ return Ok ( ( ) ) ;
319
+ } ;
320
+ let rc96_builtin_runner = runner
321
+ . vm
322
+ . get_builtin_runners ( )
323
+ . iter ( )
324
+ . find_map ( |builtin| {
325
+ if let BuiltinRunner :: RangeCheck96 ( rc96_builtin_runner) = builtin {
326
+ Some ( rc96_builtin_runner)
327
+ } else {
328
+ None
329
+ }
330
+ } )
331
+ . expect ( "RangeCheck96 builtin runner not found." ) ;
332
+
333
+ // 'EntryPointReturnValues' is returned after the implicits and its size is 5,
334
+ // So the last implicit is at offset 5 + 1.
335
+ const IMPLICITS_OFFSET : usize = 6 ;
336
+ let rc_96_stop_ptr = ( runner. vm . get_ap ( ) - ( IMPLICITS_OFFSET + rc96_offset) )
337
+ . map_err ( |err| CairoRunError :: VirtualMachine ( VirtualMachineError :: Math ( err) ) ) ?;
338
+
339
+ let rc96_base = rc96_builtin_runner. base ( ) ;
340
+ let rc96_segment: isize =
341
+ rc96_base. try_into ( ) . expect ( "Builtin segment index must fit in isize." ) ;
342
+
343
+ let Relocatable { segment_index : rc96_stop_segment, offset : stop_offset } =
344
+ runner. vm . get_relocatable ( rc_96_stop_ptr) . map_err ( CairoRunError :: MemoryError ) ?;
345
+ assert_eq ! ( rc96_stop_segment, rc96_segment) ;
346
+
347
+ // Update `segment_used_sizes` to include the holes.
348
+ runner
349
+ . vm
350
+ . segments
351
+ . segment_used_sizes
352
+ . as_mut ( )
353
+ . expect ( "Segments used sizes should be calculated at this point" ) [ rc96_base] = stop_offset;
354
+
355
+ for offset in 0 ..stop_offset {
356
+ match runner
357
+ . vm
358
+ . insert_value ( Relocatable { segment_index : rc96_segment, offset } , Felt :: zero ( ) )
359
+ {
360
+ // If the value is already set, ignore the error.
361
+ Ok ( ( ) ) | Err ( MemoryError :: InconsistentMemory ( _) ) => { }
362
+ Err ( err) => panic ! ( "Unexpected error when filling holes: {err}." ) ,
363
+ }
364
+ }
365
+
366
+ Ok ( ( ) )
294
367
}
295
368
296
369
pub fn finalize_execution (
@@ -319,12 +392,18 @@ pub fn finalize_execution(
319
392
320
393
// Take into account the VM execution resources of the current call, without inner calls.
321
394
// Has to happen after marking holes in segments as accessed.
322
- let vm_resources_without_inner_calls = runner
395
+ let mut vm_resources_without_inner_calls = runner
323
396
. get_execution_resources ( )
324
397
. map_err ( VirtualMachineError :: RunnerError ) ?
325
398
. filter_unused_builtins ( ) ;
326
- * syscall_handler. resources += & vm_resources_without_inner_calls;
327
399
let versioned_constants = syscall_handler. context . versioned_constants ( ) ;
400
+ if versioned_constants. segment_arena_cells {
401
+ vm_resources_without_inner_calls
402
+ . builtin_instance_counter
403
+ . get_mut ( & BuiltinName :: segment_arena)
404
+ . map_or_else ( || { } , |val| * val *= SEGMENT_ARENA_BUILTIN_SIZE ) ;
405
+ }
406
+ * syscall_handler. resources += & vm_resources_without_inner_calls;
328
407
// Take into account the syscall resources of the current call.
329
408
* syscall_handler. resources += & versioned_constants
330
409
. get_additional_os_syscall_resources ( & syscall_handler. syscall_counter ) ?;
0 commit comments