Skip to content

Commit 9558d3d

Browse files
Initialize full runner in builder
1 parent bcee2c1 commit 9558d3d

File tree

2 files changed

+197
-12
lines changed

2 files changed

+197
-12
lines changed

cairo1-run/src/cairo_run.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,17 @@ pub fn cairo_run_program(
257257
runner_mode,
258258
)?;
259259
runner_builder.enable_trace(cairo_run_config.trace_enabled);
260+
runner_builder.allow_missing_builtins(cairo_run_config.proof_mode);
261+
runner_builder.initialize_builtin_runners_for_layout()?;
262+
runner_builder.initialize_base_segments();
263+
runner_builder.load_program()?;
264+
runner_builder.initialize_builtin_segments();
265+
runner_builder.initialize_builtin_zero_segments();
266+
let end = runner_builder.initialize_main_entrypoint()?;
267+
runner_builder.initialize_validation_rules()?;
260268

261269
let mut runner = runner_builder.build()?;
262270

263-
let end = runner.initialize(cairo_run_config.proof_mode)?;
264271
load_arguments(&mut runner, &cairo_run_config, main_func)?;
265272

266273
// Run it until the end / infinite loop in proof_mode

vm/src/vm/runners/cairo_runner.rs

Lines changed: 189 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)