@@ -170,6 +170,12 @@ pub struct CairoRunnerBuilder {
170170 program_base : Option < Relocatable > ,
171171 execution_base : Option < Relocatable > ,
172172 memory : MemorySegmentManager ,
173+ // Set after initializing entrypoint.
174+ initial_pc : Option < Relocatable > ,
175+ initial_fp : Option < Relocatable > ,
176+ initial_ap : Option < Relocatable > ,
177+ final_pc : Option < Relocatable > ,
178+ execution_public_memory : Option < Vec < usize > > ,
173179 // Set after loading program.
174180 loaded_program : bool ,
175181 // Set after compiling hints.
@@ -215,14 +221,23 @@ impl CairoRunnerBuilder {
215221 enable_trace : false ,
216222 disable_trace_padding : false ,
217223 allow_missing_builtins : false ,
218- runner_mode,
224+ runner_mode : runner_mode . clone ( ) ,
219225 builtin_runners : Vec :: new ( ) ,
220226 program_base : None ,
221227 execution_base : None ,
222228 memory : MemorySegmentManager :: new ( ) ,
223229 loaded_program : false ,
224230 hints : None ,
225231 instructions : Vec :: new ( ) ,
232+ initial_pc : None ,
233+ initial_fp : None ,
234+ initial_ap : None ,
235+ final_pc : None ,
236+ execution_public_memory : if runner_mode != RunnerMode :: ExecutionMode {
237+ Some ( Vec :: new ( ) )
238+ } else {
239+ None
240+ } ,
226241 } )
227242 }
228243
@@ -427,12 +442,164 @@ impl CairoRunnerBuilder {
427442 /// Depends on:
428443 /// - [initialize_base_segments](Self::initialize_base_segments)
429444 /// - [initialize_builtin_runners_for_layout](Self::initialize_builtin_runners_for_layout)
445+ /// or [initialize_builtin_runners](Self::initialize_builtin_runners)
430446 pub fn initialize_builtin_segments ( & mut self ) {
431447 for builtin_runner in self . builtin_runners . iter_mut ( ) {
432448 builtin_runner. initialize_segments ( & mut self . memory ) ;
433449 }
434450 }
435451
452+ /// Initializing the builtin segments.
453+ ///
454+ /// Depends on:
455+ /// - [initialize_builtin_segments](Self::initialize_builtin_segments)
456+ pub fn initialize_builtin_zero_segments ( & mut self ) {
457+ for builtin_runner in self . builtin_runners . iter_mut ( ) {
458+ if let BuiltinRunner :: Mod ( runner) = builtin_runner {
459+ runner. initialize_zero_segment ( & mut self . memory ) ;
460+ }
461+ }
462+ }
463+
464+ pub fn initialize_validation_rules ( & mut self ) -> Result < ( ) , RunnerError > {
465+ for builtin in self . builtin_runners . iter ( ) {
466+ builtin. add_validation_rule ( & mut self . memory . memory ) ;
467+ }
468+
469+ self . memory
470+ . memory
471+ . validate_existing_memory ( )
472+ . map_err ( RunnerError :: MemoryValidationError )
473+ }
474+
475+ pub fn initialize_main_entrypoint ( & mut self ) -> Result < Relocatable , RunnerError > {
476+ let mut stack = Vec :: new ( ) ;
477+ {
478+ let builtin_runners = self
479+ . builtin_runners
480+ . iter ( )
481+ . map ( |b| ( b. name ( ) , b) )
482+ . collect :: < HashMap < _ , _ > > ( ) ;
483+ for builtin_name in & self . program . builtins {
484+ if let Some ( builtin_runner) = builtin_runners. get ( builtin_name) {
485+ stack. append ( & mut builtin_runner. initial_stack ( ) ) ;
486+ } else {
487+ stack. push ( Felt252 :: ZERO . into ( ) )
488+ }
489+ }
490+ }
491+
492+ if self . is_proof_mode ( ) {
493+ // In canonical proof mode, add the dummy last fp and pc to the public memory, so that the verifier can enforce
494+
495+ // canonical offset should be 2 for Cairo 0
496+ let mut target_offset = 2 ;
497+
498+ // Cairo1 is not adding data to check [fp - 2] = fp, and has a different initialization of the stack. This should be updated.
499+ // Cairo0 remains canonical
500+
501+ if matches ! ( self . runner_mode, RunnerMode :: ProofModeCairo1 ) {
502+ target_offset = stack. len ( ) + 2 ;
503+
504+ // This values shouldn't be needed with a canonical proof mode
505+ let return_fp = self . add_memory_segment ( ) ;
506+ let end = self . add_memory_segment ( ) ;
507+ stack. append ( & mut vec ! [
508+ MaybeRelocatable :: RelocatableValue ( return_fp) ,
509+ MaybeRelocatable :: RelocatableValue ( end) ,
510+ ] ) ;
511+
512+ self . initialize_state (
513+ self . program
514+ . shared_program_data
515+ . start
516+ . ok_or ( RunnerError :: NoProgramStart ) ?,
517+ stack,
518+ ) ?;
519+ } else {
520+ let mut stack_prefix = vec ! [
521+ Into :: <MaybeRelocatable >:: into(
522+ ( self . execution_base. ok_or( RunnerError :: NoExecBase ) ? + target_offset) ?,
523+ ) ,
524+ MaybeRelocatable :: from( Felt252 :: zero( ) ) ,
525+ ] ;
526+ stack_prefix. extend ( stack. clone ( ) ) ;
527+
528+ self . execution_public_memory = Some ( Vec :: from_iter ( 0 ..stack_prefix. len ( ) ) ) ;
529+
530+ self . initialize_state (
531+ self . program
532+ . shared_program_data
533+ . start
534+ . ok_or ( RunnerError :: NoProgramStart ) ?,
535+ stack_prefix. clone ( ) ,
536+ ) ?;
537+ }
538+
539+ self . initial_fp =
540+ Some ( ( self . execution_base . ok_or ( RunnerError :: NoExecBase ) ? + target_offset) ?) ;
541+
542+ self . initial_ap = self . initial_fp ;
543+ return Ok ( ( self . program_base . ok_or ( RunnerError :: NoProgBase ) ?
544+ + self
545+ . program
546+ . shared_program_data
547+ . end
548+ . ok_or ( RunnerError :: NoProgramEnd ) ?) ?) ;
549+ }
550+
551+ let return_fp = self . add_memory_segment ( ) ;
552+ if let Some ( main) = self . program . shared_program_data . main {
553+ let main_clone = main;
554+ Ok ( self . initialize_function_entrypoint (
555+ main_clone,
556+ stack,
557+ MaybeRelocatable :: RelocatableValue ( return_fp) ,
558+ ) ?)
559+ } else {
560+ Err ( RunnerError :: MissingMain )
561+ }
562+ }
563+
564+ fn initialize_function_entrypoint (
565+ & mut self ,
566+ entrypoint : usize ,
567+ mut stack : Vec < MaybeRelocatable > ,
568+ return_fp : MaybeRelocatable ,
569+ ) -> Result < Relocatable , RunnerError > {
570+ let end = self . add_memory_segment ( ) ;
571+ stack. append ( & mut vec ! [
572+ return_fp,
573+ MaybeRelocatable :: RelocatableValue ( end) ,
574+ ] ) ;
575+ if let Some ( base) = & self . execution_base {
576+ self . initial_fp = Some ( Relocatable {
577+ segment_index : base. segment_index ,
578+ offset : base. offset + stack. len ( ) ,
579+ } ) ;
580+ self . initial_ap = self . initial_fp ;
581+ } else {
582+ return Err ( RunnerError :: NoExecBase ) ;
583+ }
584+ self . initialize_state ( entrypoint, stack) ?;
585+ self . final_pc = Some ( end) ;
586+ Ok ( end)
587+ }
588+
589+ fn initialize_state (
590+ & mut self ,
591+ entrypoint : usize ,
592+ stack : Vec < MaybeRelocatable > ,
593+ ) -> Result < ( ) , RunnerError > {
594+ let prog_base = self . program_base . ok_or ( RunnerError :: NoProgBase ) ?;
595+ let exec_base = self . execution_base . ok_or ( RunnerError :: NoExecBase ) ?;
596+ self . initial_pc = Some ( ( prog_base + entrypoint) ?) ;
597+ self . memory
598+ . load_data ( exec_base, & stack)
599+ . map_err ( RunnerError :: MemoryInitializationError ) ?;
600+ Ok ( ( ) )
601+ }
602+
436603 /// Loads the program into the program segment.
437604 ///
438605 /// If this function is not called, the program will be loaded
@@ -520,7 +687,7 @@ impl CairoRunnerBuilder {
520687 }
521688
522689 pub fn build ( self ) -> Result < CairoRunner , RunnerError > {
523- let vm = VirtualMachineBuilder :: default ( )
690+ let mut vm = VirtualMachineBuilder :: default ( )
524691 . builtin_runners ( self . builtin_runners )
525692 . segments ( self . memory )
526693 . instruction_cache ( self . instructions )
@@ -532,23 +699,29 @@ impl CairoRunnerBuilder {
532699 } )
533700 . build ( ) ;
534701
702+ if let Some ( initial_pc) = self . initial_pc {
703+ vm. run_context . pc = initial_pc;
704+ }
705+ if let Some ( initial_fp) = self . initial_fp {
706+ vm. run_context . fp = initial_fp. offset ;
707+ }
708+ if let Some ( initial_ap) = self . initial_ap {
709+ vm. run_context . ap = initial_ap. offset ;
710+ }
711+
535712 Ok ( CairoRunner {
536713 vm,
537714 layout : self . layout ,
538715 program_base : self . program_base ,
539716 execution_base : self . execution_base ,
540717 entrypoint : self . program . shared_program_data . main ,
541- initial_ap : None ,
542- initial_fp : None ,
543- initial_pc : None ,
544- final_pc : None ,
718+ initial_ap : self . initial_ap ,
719+ initial_fp : self . initial_fp ,
720+ initial_pc : self . initial_pc ,
721+ final_pc : self . final_pc ,
545722 run_ended : false ,
546723 segments_finalized : false ,
547- execution_public_memory : if self . runner_mode != RunnerMode :: ExecutionMode {
548- Some ( Vec :: new ( ) )
549- } else {
550- None
551- } ,
724+ execution_public_memory : self . execution_public_memory ,
552725 runner_mode : self . runner_mode ,
553726 relocated_memory : Vec :: new ( ) ,
554727 exec_scopes : ExecutionScopes :: new ( ) ,
@@ -597,6 +770,11 @@ impl Clone for CairoRunnerBuilder {
597770 loaded_program : self . loaded_program ,
598771 hints : self . hints . clone ( ) ,
599772 instructions : self . instructions . clone ( ) ,
773+ initial_pc : self . initial_pc ,
774+ initial_fp : self . initial_fp ,
775+ initial_ap : self . initial_ap ,
776+ final_pc : self . final_pc ,
777+ execution_public_memory : self . execution_public_memory . clone ( ) ,
600778 }
601779 }
602780}
0 commit comments