1use crate::vm::trace::trace_entry::TraceEntry;
2
3use crate::{
4 air_private_input::AirPrivateInput,
5 air_public_input::{PublicInput, PublicInputError},
6 math_utils::safe_div_usize,
7 stdlib::{
8 any::Any,
9 collections::{BTreeMap, HashMap, HashSet},
10 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
11 prelude::*,
12 },
13 types::{builtin_name::BuiltinName, layout::CairoLayoutParams, layout_name::LayoutName},
14 vm::{
15 runners::builtin_runner::SegmentArenaBuiltinRunner,
16 trace::trace_entry::{relocate_trace_register, RelocatedTraceEntry},
17 },
18 Felt252,
19};
20
21use crate::{
22 hint_processor::hint_processor_definition::{HintProcessor, HintReference},
23 types::{
24 errors::{math_errors::MathError, program_errors::ProgramError},
25 exec_scope::ExecutionScopes,
26 layout::CairoLayout,
27 program::Program,
28 relocatable::{relocate_address, relocate_value, MaybeRelocatable, Relocatable},
29 },
30 utils::is_subsequence,
31 vm::{
32 errors::{
33 cairo_run_errors::CairoRunError,
34 memory_errors::{InsufficientAllocatedCellsError, MemoryError},
35 runner_errors::RunnerError,
36 trace_errors::TraceError,
37 vm_errors::VirtualMachineError,
38 vm_exception::VmException,
39 },
40 security::verify_secure_runner,
41 {
42 runners::builtin_runner::{
43 BitwiseBuiltinRunner, BuiltinRunner, EcOpBuiltinRunner, HashBuiltinRunner,
44 OutputBuiltinRunner, RangeCheckBuiltinRunner, SignatureBuiltinRunner,
45 },
46 vm_core::VirtualMachine,
47 },
48 },
49};
50use num_integer::div_rem;
51use num_traits::{ToPrimitive, Zero};
52use serde::{Deserialize, Serialize};
53
54use super::{builtin_runner::ModBuiltinRunner, cairo_pie::CairoPieAdditionalData};
55use super::{
56 builtin_runner::{
57 KeccakBuiltinRunner, PoseidonBuiltinRunner, RC_N_PARTS_96, RC_N_PARTS_STANDARD,
58 },
59 cairo_pie::{self, CairoPie, CairoPieMetadata, CairoPieVersion},
60};
61use crate::types::instance_definitions::mod_instance_def::ModInstanceDef;
62
63#[derive(Clone, Debug, Eq, PartialEq)]
64pub enum CairoArg {
65 Single(MaybeRelocatable),
66 Array(Vec<MaybeRelocatable>),
67 Composed(Vec<CairoArg>),
68}
69
70impl From<MaybeRelocatable> for CairoArg {
71 fn from(other: MaybeRelocatable) -> Self {
72 CairoArg::Single(other)
73 }
74}
75
76impl From<Vec<MaybeRelocatable>> for CairoArg {
77 fn from(other: Vec<MaybeRelocatable>) -> Self {
78 CairoArg::Array(other)
79 }
80}
81
82#[derive(Clone, Default, Debug, PartialEq)]
88pub struct RunResources {
89 n_steps: Option<usize>,
90}
91
92pub trait ResourceTracker {
98 fn consumed(&self) -> bool {
100 false
101 }
102 fn consume_step(&mut self) {}
104 fn get_n_steps(&self) -> Option<usize> {
106 None
107 }
108 fn run_resources(&self) -> &RunResources {
110 &RunResources { n_steps: None }
111 }
112}
113
114impl RunResources {
115 pub fn new(n_steps: usize) -> Self {
116 Self {
117 n_steps: Some(n_steps),
118 }
119 }
120}
121
122impl ResourceTracker for RunResources {
123 fn consumed(&self) -> bool {
124 if self.n_steps == Some(0) {
125 return true;
126 }
127 false
128 }
129
130 fn consume_step(&mut self) {
131 if let Some(n_steps) = self.n_steps {
132 self.n_steps = Some(n_steps.saturating_sub(1));
133 }
134 }
135
136 fn get_n_steps(&self) -> Option<usize> {
137 self.n_steps
138 }
139
140 fn run_resources(&self) -> &RunResources {
141 self
142 }
143}
144
145pub struct CairoRunner {
146 pub vm: VirtualMachine,
147 pub(crate) program: Program,
148 layout: CairoLayout,
149 final_pc: Option<Relocatable>,
150 pub program_base: Option<Relocatable>,
151 execution_base: Option<Relocatable>,
152 entrypoint: Option<usize>,
153 initial_ap: Option<Relocatable>,
154 initial_fp: Option<Relocatable>,
155 initial_pc: Option<Relocatable>,
156 run_ended: bool,
157 segments_finalized: bool,
158 execution_public_memory: Option<Vec<usize>>,
159 pub(crate) runner_mode: RunnerMode,
160 pub relocated_memory: Vec<Option<Felt252>>,
161 pub exec_scopes: ExecutionScopes,
162 pub relocated_trace: Option<Vec<RelocatedTraceEntry>>,
163}
164
165#[derive(Clone, Debug, PartialEq)]
166pub enum RunnerMode {
167 ExecutionMode,
168 ProofModeCanonical,
169 ProofModeCairo1,
170}
171
172impl CairoRunner {
173 pub fn new_v2(
176 program: &Program,
177 layout: LayoutName,
178 dynamic_layout_params: Option<CairoLayoutParams>,
179 mode: RunnerMode,
180 trace_enabled: bool,
181 disable_trace_padding: bool,
182 ) -> Result<CairoRunner, RunnerError> {
183 let cairo_layout = match layout {
184 LayoutName::plain => CairoLayout::plain_instance(),
185 LayoutName::small => CairoLayout::small_instance(),
186 LayoutName::dex => CairoLayout::dex_instance(),
187 LayoutName::recursive => CairoLayout::recursive_instance(),
188 LayoutName::starknet => CairoLayout::starknet_instance(),
189 LayoutName::starknet_with_keccak => CairoLayout::starknet_with_keccak_instance(),
190 LayoutName::recursive_large_output => CairoLayout::recursive_large_output_instance(),
191 LayoutName::recursive_with_poseidon => CairoLayout::recursive_with_poseidon(),
192 LayoutName::all_cairo => CairoLayout::all_cairo_instance(),
193 LayoutName::all_cairo_stwo => CairoLayout::all_cairo_stwo_instance(),
194 LayoutName::all_solidity => CairoLayout::all_solidity_instance(),
195 LayoutName::perpetual => CairoLayout::perpetual_instance(),
196 LayoutName::dex_with_bitwise => CairoLayout::dex_with_bitwise_instance(),
197 LayoutName::dynamic => {
198 let params =
199 dynamic_layout_params.ok_or(RunnerError::MissingDynamicLayoutParams)?;
200
201 CairoLayout::dynamic_instance(params)
202 }
203 };
204 Ok(CairoRunner {
205 program: program.clone(),
206 vm: VirtualMachine::new(trace_enabled, disable_trace_padding),
207 layout: cairo_layout,
208 final_pc: None,
209 program_base: None,
210 execution_base: None,
211 entrypoint: program.shared_program_data.main,
212 initial_ap: None,
213 initial_fp: None,
214 initial_pc: None,
215 run_ended: false,
216 segments_finalized: false,
217 runner_mode: mode.clone(),
218 relocated_memory: Vec::new(),
219 exec_scopes: ExecutionScopes::new(),
220 execution_public_memory: if mode != RunnerMode::ExecutionMode {
221 Some(Vec::new())
222 } else {
223 None
224 },
225 relocated_trace: None,
226 })
227 }
228
229 pub fn new(
230 program: &Program,
231 layout: LayoutName,
232 dynamic_layout_params: Option<CairoLayoutParams>,
233 proof_mode: bool,
234 trace_enabled: bool,
235 disable_trace_padding: bool,
236 ) -> Result<CairoRunner, RunnerError> {
237 if disable_trace_padding && !proof_mode {
240 return Err(RunnerError::DisableTracePaddingWithoutProofMode);
241 }
242 if proof_mode {
243 Self::new_v2(
244 program,
245 layout,
246 dynamic_layout_params,
247 RunnerMode::ProofModeCanonical,
248 trace_enabled,
249 disable_trace_padding,
250 )
251 } else {
252 Self::new_v2(
253 program,
254 layout,
255 dynamic_layout_params,
256 RunnerMode::ExecutionMode,
257 trace_enabled,
258 disable_trace_padding,
259 )
260 }
261 }
262
263 pub fn initialize(&mut self, allow_missing_builtins: bool) -> Result<Relocatable, RunnerError> {
264 self.initialize_builtins(allow_missing_builtins)?;
265 self.initialize_segments(None);
266 let end = self.initialize_main_entrypoint()?;
267 for builtin_runner in self.vm.builtin_runners.iter_mut() {
268 if let BuiltinRunner::Mod(runner) = builtin_runner {
269 runner.initialize_zero_segment(&mut self.vm.segments);
270 }
271 }
272 self.initialize_vm()?;
273 Ok(end)
274 }
275
276 pub fn initialize_builtins(&mut self, allow_missing_builtins: bool) -> Result<(), RunnerError> {
283 let builtin_ordered_list = vec![
284 BuiltinName::output,
285 BuiltinName::pedersen,
286 BuiltinName::range_check,
287 BuiltinName::ecdsa,
288 BuiltinName::bitwise,
289 BuiltinName::ec_op,
290 BuiltinName::keccak,
291 BuiltinName::poseidon,
292 BuiltinName::range_check96,
293 BuiltinName::add_mod,
294 BuiltinName::mul_mod,
295 ];
296 if !is_subsequence(&self.program.builtins, &builtin_ordered_list) {
297 return Err(RunnerError::DisorderedBuiltins);
298 };
299 let mut program_builtins: HashSet<&BuiltinName> = self.program.builtins.iter().collect();
300
301 if self.layout.builtins.output {
302 let included = program_builtins.remove(&BuiltinName::output);
303 if included || self.is_proof_mode() {
304 self.vm
305 .builtin_runners
306 .push(OutputBuiltinRunner::new(included).into());
307 }
308 }
309
310 if let Some(instance_def) = self.layout.builtins.pedersen.as_ref() {
311 let included = program_builtins.remove(&BuiltinName::pedersen);
312 if included || self.is_proof_mode() {
313 self.vm
314 .builtin_runners
315 .push(HashBuiltinRunner::new(instance_def.ratio, included).into());
316 }
317 }
318
319 if let Some(instance_def) = self.layout.builtins.range_check.as_ref() {
320 let included = program_builtins.remove(&BuiltinName::range_check);
321 if included || self.is_proof_mode() {
322 self.vm.builtin_runners.push(
323 RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new_with_low_ratio(
324 instance_def.ratio,
325 included,
326 )
327 .into(),
328 );
329 }
330 }
331
332 if let Some(instance_def) = self.layout.builtins.ecdsa.as_ref() {
333 let included = program_builtins.remove(&BuiltinName::ecdsa);
334 if included || self.is_proof_mode() {
335 self.vm
336 .builtin_runners
337 .push(SignatureBuiltinRunner::new(instance_def.ratio, included).into());
338 }
339 }
340
341 if let Some(instance_def) = self.layout.builtins.bitwise.as_ref() {
342 let included = program_builtins.remove(&BuiltinName::bitwise);
343 if included || self.is_proof_mode() {
344 self.vm
345 .builtin_runners
346 .push(BitwiseBuiltinRunner::new(instance_def.ratio, included).into());
347 }
348 }
349
350 if let Some(instance_def) = self.layout.builtins.ec_op.as_ref() {
351 let included = program_builtins.remove(&BuiltinName::ec_op);
352 if included || self.is_proof_mode() {
353 self.vm
354 .builtin_runners
355 .push(EcOpBuiltinRunner::new(instance_def.ratio, included).into());
356 }
357 }
358
359 if let Some(instance_def) = self.layout.builtins.keccak.as_ref() {
360 let included = program_builtins.remove(&BuiltinName::keccak);
361 if included || self.is_proof_mode() {
362 self.vm
363 .builtin_runners
364 .push(KeccakBuiltinRunner::new(instance_def.ratio, included).into());
365 }
366 }
367
368 if let Some(instance_def) = self.layout.builtins.poseidon.as_ref() {
369 let included = program_builtins.remove(&BuiltinName::poseidon);
370 if included || self.is_proof_mode() {
371 self.vm
372 .builtin_runners
373 .push(PoseidonBuiltinRunner::new(instance_def.ratio, included).into());
374 }
375 }
376
377 if let Some(instance_def) = self.layout.builtins.range_check96.as_ref() {
378 let included = program_builtins.remove(&BuiltinName::range_check96);
379 if included || self.is_proof_mode() {
380 self.vm.builtin_runners.push(
381 RangeCheckBuiltinRunner::<RC_N_PARTS_96>::new_with_low_ratio(
382 instance_def.ratio,
383 included,
384 )
385 .into(),
386 );
387 }
388 }
389 if let Some(instance_def) = self.layout.builtins.add_mod.as_ref() {
390 let included = program_builtins.remove(&BuiltinName::add_mod);
391 if included || self.is_proof_mode() {
392 self.vm
393 .builtin_runners
394 .push(ModBuiltinRunner::new_add_mod(instance_def, included).into());
395 }
396 }
397 if let Some(instance_def) = self.layout.builtins.mul_mod.as_ref() {
398 let included = program_builtins.remove(&BuiltinName::mul_mod);
399 if included || self.is_proof_mode() {
400 self.vm
401 .builtin_runners
402 .push(ModBuiltinRunner::new_mul_mod(instance_def, included).into());
403 }
404 }
405 if !program_builtins.is_empty() && !allow_missing_builtins {
406 return Err(RunnerError::NoBuiltinForInstance(Box::new((
407 program_builtins.iter().map(|n| **n).collect(),
408 self.layout.name,
409 ))));
410 }
411
412 Ok(())
413 }
414
415 fn is_proof_mode(&self) -> bool {
416 self.runner_mode == RunnerMode::ProofModeCanonical
417 || self.runner_mode == RunnerMode::ProofModeCairo1
418 }
419
420 pub fn initialize_program_builtins(&mut self) -> Result<(), RunnerError> {
423 fn initialize_builtin(name: BuiltinName, vm: &mut VirtualMachine) {
424 match name {
425 BuiltinName::pedersen => vm
426 .builtin_runners
427 .push(HashBuiltinRunner::new(Some(32), true).into()),
428 BuiltinName::range_check => vm.builtin_runners.push(
429 RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(1), true).into(),
430 ),
431 BuiltinName::output => vm
432 .builtin_runners
433 .push(OutputBuiltinRunner::new(true).into()),
434 BuiltinName::ecdsa => vm
435 .builtin_runners
436 .push(SignatureBuiltinRunner::new(Some(1), true).into()),
437 BuiltinName::bitwise => vm
438 .builtin_runners
439 .push(BitwiseBuiltinRunner::new(Some(1), true).into()),
440 BuiltinName::ec_op => vm
441 .builtin_runners
442 .push(EcOpBuiltinRunner::new(Some(1), true).into()),
443 BuiltinName::keccak => vm
444 .builtin_runners
445 .push(KeccakBuiltinRunner::new(Some(1), true).into()),
446 BuiltinName::poseidon => vm
447 .builtin_runners
448 .push(PoseidonBuiltinRunner::new(Some(1), true).into()),
449 BuiltinName::segment_arena => vm
450 .builtin_runners
451 .push(SegmentArenaBuiltinRunner::new(true).into()),
452 BuiltinName::range_check96 => vm
453 .builtin_runners
454 .push(RangeCheckBuiltinRunner::<RC_N_PARTS_96>::new(Some(1), true).into()),
455 BuiltinName::add_mod => vm.builtin_runners.push(
456 ModBuiltinRunner::new_add_mod(&ModInstanceDef::new(Some(1), 1, 96), true)
457 .into(),
458 ),
459 BuiltinName::mul_mod => vm.builtin_runners.push(
460 ModBuiltinRunner::new_mul_mod(&ModInstanceDef::new(Some(1), 1, 96), true)
461 .into(),
462 ),
463 }
464 }
465
466 for builtin_name in &self.program.builtins {
467 initialize_builtin(*builtin_name, &mut self.vm);
468 }
469 Ok(())
470 }
471
472 pub fn initialize_segments(&mut self, program_base: Option<Relocatable>) {
474 self.program_base = match program_base {
475 Some(base) => Some(base),
476 None => Some(self.vm.add_memory_segment()),
477 };
478 self.execution_base = Some(self.vm.add_memory_segment());
479 for builtin_runner in self.vm.builtin_runners.iter_mut() {
480 builtin_runner.initialize_segments(&mut self.vm.segments);
481 }
482 }
483
484 fn initialize_state(
485 &mut self,
486 entrypoint: usize,
487 stack: Vec<MaybeRelocatable>,
488 ) -> Result<(), RunnerError> {
489 let prog_base = self.program_base.ok_or(RunnerError::NoProgBase)?;
490 let exec_base = self.execution_base.ok_or(RunnerError::NoExecBase)?;
491 self.initial_pc = Some((prog_base + entrypoint)?);
492 self.vm
493 .load_data(prog_base, &self.program.shared_program_data.data)
494 .map_err(RunnerError::MemoryInitializationError)?;
495
496 for i in 0..self.program.shared_program_data.data.len() {
498 self.vm.segments.memory.mark_as_accessed((prog_base + i)?);
499 }
500 self.vm
501 .segments
502 .load_data(exec_base, &stack)
503 .map_err(RunnerError::MemoryInitializationError)?;
504 Ok(())
505 }
506
507 pub fn initialize_function_entrypoint(
508 &mut self,
509 entrypoint: usize,
510 mut stack: Vec<MaybeRelocatable>,
511 return_fp: MaybeRelocatable,
512 ) -> Result<Relocatable, RunnerError> {
513 let end = self.vm.add_memory_segment();
514 stack.append(&mut vec![
515 return_fp,
516 MaybeRelocatable::RelocatableValue(end),
517 ]);
518 if let Some(base) = &self.execution_base {
519 self.initial_fp = Some(Relocatable {
520 segment_index: base.segment_index,
521 offset: base.offset + stack.len(),
522 });
523 self.initial_ap = self.initial_fp;
524 } else {
525 return Err(RunnerError::NoExecBase);
526 }
527 self.initialize_state(entrypoint, stack)?;
528 self.final_pc = Some(end);
529 Ok(end)
530 }
531
532 fn initialize_main_entrypoint(&mut self) -> Result<Relocatable, RunnerError> {
536 let mut stack = Vec::new();
537 {
538 let builtin_runners = self
539 .vm
540 .builtin_runners
541 .iter()
542 .map(|b| (b.name(), b))
543 .collect::<HashMap<_, _>>();
544 for builtin_name in &self.program.builtins {
545 if let Some(builtin_runner) = builtin_runners.get(builtin_name) {
546 stack.append(&mut builtin_runner.initial_stack());
547 } else {
548 stack.push(Felt252::ZERO.into())
549 }
550 }
551 }
552
553 if self.is_proof_mode() {
554 let mut target_offset = 2;
558
559 if matches!(self.runner_mode, RunnerMode::ProofModeCairo1) {
563 target_offset = stack.len() + 2;
564
565 let return_fp = self.vm.add_memory_segment();
567 let end = self.vm.add_memory_segment();
568 stack.append(&mut vec![
569 MaybeRelocatable::RelocatableValue(return_fp),
570 MaybeRelocatable::RelocatableValue(end),
571 ]);
572
573 self.initialize_state(
574 self.program
575 .shared_program_data
576 .start
577 .ok_or(RunnerError::NoProgramStart)?,
578 stack,
579 )?;
580 } else {
581 let mut stack_prefix = vec![
582 Into::<MaybeRelocatable>::into(
583 (self.execution_base.ok_or(RunnerError::NoExecBase)? + target_offset)?,
584 ),
585 MaybeRelocatable::from(Felt252::zero()),
586 ];
587 stack_prefix.extend(stack.clone());
588
589 self.execution_public_memory = Some(Vec::from_iter(0..stack_prefix.len()));
590
591 self.initialize_state(
592 self.program
593 .shared_program_data
594 .start
595 .ok_or(RunnerError::NoProgramStart)?,
596 stack_prefix.clone(),
597 )?;
598 }
599
600 self.initial_fp =
601 Some((self.execution_base.ok_or(RunnerError::NoExecBase)? + target_offset)?);
602
603 self.initial_ap = self.initial_fp;
604 return Ok((self.program_base.ok_or(RunnerError::NoProgBase)?
605 + self
606 .program
607 .shared_program_data
608 .end
609 .ok_or(RunnerError::NoProgramEnd)?)?);
610 }
611
612 let return_fp = self.vm.add_memory_segment();
613 if let Some(main) = &self.entrypoint {
614 let main_clone = *main;
615 Ok(self.initialize_function_entrypoint(
616 main_clone,
617 stack,
618 MaybeRelocatable::RelocatableValue(return_fp),
619 )?)
620 } else {
621 Err(RunnerError::MissingMain)
622 }
623 }
624
625 pub fn initialize_vm(&mut self) -> Result<(), RunnerError> {
626 self.vm.run_context.pc = *self.initial_pc.as_ref().ok_or(RunnerError::NoPC)?;
627 self.vm.run_context.ap = self.initial_ap.as_ref().ok_or(RunnerError::NoAP)?.offset;
628 self.vm.run_context.fp = self.initial_fp.as_ref().ok_or(RunnerError::NoFP)?.offset;
629 for builtin in self.vm.builtin_runners.iter() {
630 builtin.add_validation_rule(&mut self.vm.segments.memory);
631 }
632
633 self.vm
634 .segments
635 .memory
636 .validate_existing_memory()
637 .map_err(RunnerError::MemoryValidationError)
638 }
639
640 pub fn get_initial_fp(&self) -> Option<Relocatable> {
641 self.initial_fp
642 }
643
644 pub fn get_hint_data(
646 &self,
647 references: &[HintReference],
648 hint_executor: &mut dyn HintProcessor,
649 ) -> Result<Vec<Box<dyn Any>>, VirtualMachineError> {
650 self.program
651 .shared_program_data
652 .hints_collection
653 .iter_hints()
654 .map(|hint| {
655 hint_executor
656 .compile_hint(
657 &hint.code,
658 &hint.flow_tracking_data.ap_tracking,
659 &hint.flow_tracking_data.reference_ids,
660 references,
661 &hint.accessible_scopes,
662 self.program.constants.clone(),
663 )
664 .map_err(|_| VirtualMachineError::CompileHintFail(hint.code.clone().into()))
665 })
666 .collect()
667 }
668
669 pub fn get_constants(&self) -> &HashMap<String, Felt252> {
670 &self.program.constants
671 }
672
673 pub fn get_program_builtins(&self) -> &Vec<BuiltinName> {
674 &self.program.builtins
675 }
676
677 pub fn run_until_pc(
678 &mut self,
679 address: Relocatable,
680 hint_processor: &mut dyn HintProcessor,
681 ) -> Result<(), VirtualMachineError> {
682 let references = &self.program.shared_program_data.reference_manager;
683 #[cfg(not(feature = "extensive_hints"))]
684 let hint_data = self.get_hint_data(references, hint_processor)?;
685 #[cfg(feature = "extensive_hints")]
686 let mut hint_data = self.get_hint_data(references, hint_processor)?;
687 #[cfg(feature = "extensive_hints")]
688 let mut hint_ranges = self
689 .program
690 .shared_program_data
691 .hints_collection
692 .hints_ranges
693 .clone();
694 #[cfg(feature = "test_utils")]
695 self.vm.execute_before_first_step(&hint_data)?;
696 while self.vm.get_pc() != address && !hint_processor.consumed() {
697 self.vm.step(
698 hint_processor,
699 &mut self.exec_scopes,
700 #[cfg(feature = "extensive_hints")]
701 &mut hint_data,
702 #[cfg(not(feature = "extensive_hints"))]
703 self.program
704 .shared_program_data
705 .hints_collection
706 .get_hint_range_for_pc(self.vm.get_pc().offset)
707 .and_then(|range| {
708 range.and_then(|(start, length)| hint_data.get(start..start + length.get()))
709 })
710 .unwrap_or(&[]),
711 #[cfg(feature = "extensive_hints")]
712 &mut hint_ranges,
713 #[cfg(feature = "test_utils")]
714 &self.program.constants,
715 )?;
716
717 hint_processor.consume_step();
718 }
719
720 if self.vm.get_pc() != address {
721 return Err(VirtualMachineError::UnfinishedExecution);
722 }
723
724 Ok(())
725 }
726
727 pub fn run_for_steps(
729 &mut self,
730 steps: usize,
731 hint_processor: &mut dyn HintProcessor,
732 ) -> Result<(), VirtualMachineError> {
733 let references = &self.program.shared_program_data.reference_manager;
734 #[cfg(not(feature = "extensive_hints"))]
735 let hint_data = self.get_hint_data(references, hint_processor)?;
736 #[cfg(feature = "extensive_hints")]
737 let mut hint_data = self.get_hint_data(references, hint_processor)?;
738 #[cfg(feature = "extensive_hints")]
739 let mut hint_ranges = self
740 .program
741 .shared_program_data
742 .hints_collection
743 .hints_ranges
744 .clone();
745 #[cfg(not(feature = "extensive_hints"))]
746 let hint_data = &self
747 .program
748 .shared_program_data
749 .hints_collection
750 .get_hint_range_for_pc(self.vm.get_pc().offset)
751 .and_then(|range| {
752 range.and_then(|(start, length)| hint_data.get(start..start + length.get()))
753 })
754 .unwrap_or(&[]);
755
756 for remaining_steps in (1..=steps).rev() {
757 if self.final_pc.as_ref() == Some(&self.vm.get_pc()) {
758 return Err(VirtualMachineError::EndOfProgram(remaining_steps));
759 }
760
761 self.vm.step(
762 hint_processor,
763 &mut self.exec_scopes,
764 #[cfg(feature = "extensive_hints")]
765 &mut hint_data,
766 #[cfg(not(feature = "extensive_hints"))]
767 hint_data,
768 #[cfg(feature = "extensive_hints")]
769 &mut hint_ranges,
770 #[cfg(feature = "test_utils")]
771 &self.program.constants,
772 )?;
773 }
774
775 Ok(())
776 }
777
778 pub fn run_until_steps(
780 &mut self,
781 steps: usize,
782 hint_processor: &mut dyn HintProcessor,
783 ) -> Result<(), VirtualMachineError> {
784 self.run_for_steps(steps.saturating_sub(self.vm.current_step), hint_processor)
785 }
786
787 pub fn run_until_next_power_of_2(
789 &mut self,
790 hint_processor: &mut dyn HintProcessor,
791 ) -> Result<(), VirtualMachineError> {
792 self.run_until_steps(self.vm.current_step.next_power_of_two(), hint_processor)
793 }
794
795 pub fn get_perm_range_check_limits(&self) -> Option<(isize, isize)> {
796 let runner_usages = self
797 .vm
798 .builtin_runners
799 .iter()
800 .filter_map(|runner| runner.get_range_check_usage(&self.vm.segments.memory))
801 .map(|(rc_min, rc_max)| (rc_min as isize, rc_max as isize));
802 let rc_bounds = self.vm.rc_limits.iter().copied().chain(runner_usages);
803 rc_bounds.reduce(|(min1, max1), (min2, max2)| (min1.min(min2), max1.max(max2)))
804 }
805
806 pub fn check_range_check_usage(&self) -> Result<(), VirtualMachineError> {
809 let Some((rc_min, rc_max)) = self.get_perm_range_check_limits() else {
810 return Ok(());
811 };
812
813 let rc_units_used_by_builtins: usize = self
814 .vm
815 .builtin_runners
816 .iter()
817 .map(|runner| runner.get_used_perm_range_check_units(&self.vm))
818 .sum::<Result<usize, MemoryError>>()
819 .map_err(Into::<VirtualMachineError>::into)?;
820
821 let unused_rc_units =
822 (self.layout.rc_units as usize - 3) * self.vm.current_step - rc_units_used_by_builtins;
823 if unused_rc_units < (rc_max - rc_min) as usize {
824 return Err(MemoryError::InsufficientAllocatedCells(
825 InsufficientAllocatedCellsError::RangeCheckUnits(Box::new((
826 unused_rc_units,
827 (rc_max - rc_min) as usize,
828 ))),
829 )
830 .into());
831 }
832
833 Ok(())
834 }
835
836 pub fn get_memory_holes(&self) -> Result<usize, MemoryError> {
838 let builtin_segment_indexes: HashSet<usize> = self
840 .vm
841 .builtin_runners
842 .iter()
843 .filter(|b| b.name() != BuiltinName::output)
844 .map(|b| b.base())
845 .collect();
846
847 self.vm.segments.get_memory_holes(builtin_segment_indexes)
848 }
849
850 pub fn check_diluted_check_usage(&self) -> Result<(), VirtualMachineError> {
852 let diluted_pool_instance = match &self.layout.diluted_pool_instance_def {
853 Some(x) => x,
854 None => return Ok(()),
855 };
856
857 let mut used_units_by_builtins = 0;
858 for builtin_runner in &self.vm.builtin_runners {
859 let used_units = builtin_runner.get_used_diluted_check_units(
860 diluted_pool_instance.spacing,
861 diluted_pool_instance.n_bits,
862 );
863
864 let multiplier = builtin_runner.get_allocated_instances(&self.vm)?;
865
866 used_units_by_builtins += used_units * multiplier;
867 }
868
869 let diluted_units = if !diluted_pool_instance.fractional_units_per_step {
870 diluted_pool_instance.units_per_step as usize * self.vm.current_step
871 } else {
872 safe_div_usize(
873 self.vm.current_step,
874 diluted_pool_instance.units_per_step as usize,
875 )?
876 };
877
878 let unused_diluted_units = diluted_units.saturating_sub(used_units_by_builtins);
879
880 let diluted_usage_upper_bound = 1usize << diluted_pool_instance.n_bits;
881 if unused_diluted_units < diluted_usage_upper_bound {
882 return Err(MemoryError::InsufficientAllocatedCells(
883 InsufficientAllocatedCellsError::DilutedCells(Box::new((
884 unused_diluted_units,
885 diluted_usage_upper_bound,
886 ))),
887 )
888 .into());
889 }
890
891 Ok(())
892 }
893
894 pub fn end_run(
895 &mut self,
896 disable_trace_padding: bool,
897 disable_finalize_all: bool,
898 hint_processor: &mut dyn HintProcessor,
899 fill_holes: bool,
900 ) -> Result<(), VirtualMachineError> {
901 if self.run_ended {
902 return Err(RunnerError::EndRunCalledTwice.into());
903 }
904
905 self.vm.segments.memory.relocate_memory()?;
906 self.vm.end_run(&self.exec_scopes, fill_holes)?;
907
908 if disable_finalize_all {
909 return Ok(());
910 }
911
912 self.vm.segments.compute_effective_sizes();
913 if self.is_proof_mode() && !disable_trace_padding {
914 self.run_until_next_power_of_2(hint_processor)?;
915 loop {
916 match self.check_used_cells() {
917 Ok(_) => break,
918 Err(e) => match e {
919 VirtualMachineError::Memory(MemoryError::InsufficientAllocatedCells(_)) => {
920 }
921 e => return Err(e),
922 },
923 }
924
925 self.run_for_steps(1, hint_processor)?;
926 self.run_until_next_power_of_2(hint_processor)?;
927 }
928 }
929
930 self.run_ended = true;
931 Ok(())
932 }
933
934 pub fn relocate_trace(&mut self, relocation_table: &[usize]) -> Result<(), TraceError> {
936 if self.relocated_trace.is_some() {
937 return Err(TraceError::AlreadyRelocated);
938 }
939
940 let trace = self
941 .vm
942 .trace
943 .as_ref()
944 .ok_or(TraceError::TraceNotEnabled)?
945 .iter();
946 let mut relocated_trace = Vec::<RelocatedTraceEntry>::with_capacity(trace.len());
947 let segment_1_base = relocation_table
948 .get(1)
949 .ok_or(TraceError::NoRelocationFound)?;
950
951 for entry in trace {
952 relocated_trace.push(RelocatedTraceEntry {
953 pc: relocate_trace_register(entry.pc, relocation_table)?,
954 ap: entry.ap + segment_1_base,
955 fp: entry.fp + segment_1_base,
956 })
957 }
958 self.relocated_trace = Some(relocated_trace);
959 Ok(())
960 }
961
962 fn relocate_memory(&mut self, relocation_table: &[usize]) -> Result<(), MemoryError> {
966 if !(self.relocated_memory.is_empty()) {
967 return Err(MemoryError::Relocation);
968 }
969 self.relocated_memory.push(None);
971 for (index, segment) in self.vm.segments.memory.data.iter().enumerate() {
972 for (seg_offset, cell) in segment.iter().enumerate() {
973 match cell.get_value() {
974 Some(cell) => {
975 let relocated_addr = relocate_address(
976 Relocatable::from((index as isize, seg_offset)),
977 relocation_table,
978 )?;
979 let value = relocate_value(cell, relocation_table)?;
980 if self.relocated_memory.len() <= relocated_addr {
981 self.relocated_memory.resize(relocated_addr + 1, None);
982 }
983 self.relocated_memory[relocated_addr] = Some(value);
984 }
985 None => self.relocated_memory.push(None),
986 }
987 }
988 }
989 Ok(())
990 }
991
992 pub fn relocate(&mut self, relocate_mem: bool, relocate_trace: bool) -> Result<(), TraceError> {
993 self.vm.segments.compute_effective_sizes();
994 if !relocate_mem && (self.vm.trace.is_none() || !relocate_trace) {
995 return Ok(());
996 }
997 let relocation_table = self
1000 .vm
1001 .segments
1002 .relocate_segments()
1003 .expect("compute_effective_sizes called but relocate_memory still returned error");
1004
1005 if relocate_mem {
1006 if let Err(memory_error) = self.relocate_memory(&relocation_table) {
1007 return Err(TraceError::MemoryError(memory_error));
1008 }
1009 }
1010 if self.vm.trace.is_some() && relocate_trace {
1011 self.relocate_trace(&relocation_table)?;
1012 }
1013 self.vm.relocation_table = Some(relocation_table);
1014 Ok(())
1015 }
1016
1017 pub fn get_builtin_segments_info(&self) -> Result<Vec<(usize, usize)>, RunnerError> {
1020 let proof_mode = self.is_proof_mode();
1021 let mut builtin_segment_info = Vec::new();
1022
1023 for builtin in &self.vm.builtin_runners {
1024 let (index, stop_ptr) = builtin.get_memory_segment_addresses();
1025
1026 match (proof_mode, stop_ptr) {
1027 (_, Some(sp)) => builtin_segment_info.push((index, sp)),
1029
1030 (false, None) => {
1033 return Err(RunnerError::NoStopPointer(Box::new(
1034 builtin.name().to_owned(),
1035 )));
1036 }
1037
1038 (true, None) => {}
1042 }
1043 }
1044
1045 Ok(builtin_segment_info)
1046 }
1047
1048 pub fn get_builtin_segment_info_for_pie(
1051 &self,
1052 ) -> Result<HashMap<BuiltinName, cairo_pie::SegmentInfo>, RunnerError> {
1053 let mut builtin_segment_info = HashMap::new();
1054
1055 for builtin in &self.vm.builtin_runners {
1056 let (index, stop_ptr) = builtin.get_memory_segment_addresses();
1057
1058 builtin_segment_info.insert(
1059 builtin.name(),
1060 (
1061 index as isize,
1062 stop_ptr.ok_or_else(|| RunnerError::NoStopPointer(Box::new(builtin.name())))?,
1063 )
1064 .into(),
1065 );
1066 }
1067
1068 Ok(builtin_segment_info)
1069 }
1070
1071 pub fn get_execution_resources(&self) -> Result<ExecutionResources, RunnerError> {
1072 let n_steps = self
1073 .vm
1074 .trace
1075 .as_ref()
1076 .map(|x| x.len())
1077 .unwrap_or(self.vm.current_step);
1078 let n_memory_holes = self.get_memory_holes()?;
1079
1080 let mut builtin_instance_counter = BTreeMap::new();
1081 for builtin_runner in &self.vm.builtin_runners {
1082 builtin_instance_counter.insert(
1083 builtin_runner.name(),
1084 builtin_runner.get_used_instances(&self.vm.segments)?,
1085 );
1086 }
1087
1088 Ok(ExecutionResources {
1089 n_steps,
1090 n_memory_holes,
1091 builtin_instance_counter,
1092 })
1093 }
1094
1095 pub fn finalize_segments(&mut self) -> Result<(), RunnerError> {
1101 if self.segments_finalized {
1102 return Ok(());
1103 }
1104 if !self.run_ended {
1105 return Err(RunnerError::FinalizeNoEndRun);
1106 }
1107 let size = self.program.shared_program_data.data.len();
1108 let mut public_memory = Vec::with_capacity(size);
1109 for i in 0..size {
1110 public_memory.push((i, 0_usize))
1111 }
1112 self.vm.segments.finalize(
1113 Some(size),
1114 self.program_base
1115 .as_ref()
1116 .ok_or(RunnerError::NoProgBase)?
1117 .segment_index as usize,
1118 Some(&public_memory),
1119 );
1120 let mut public_memory = Vec::with_capacity(size);
1121 let exec_base = self
1122 .execution_base
1123 .as_ref()
1124 .ok_or(RunnerError::NoExecBase)?;
1125 for elem in self
1126 .execution_public_memory
1127 .as_ref()
1128 .ok_or(RunnerError::FinalizeSegmentsNoProofMode)?
1129 .iter()
1130 {
1131 public_memory.push((elem + exec_base.offset, 0))
1132 }
1133 self.vm
1134 .segments
1135 .finalize(None, exec_base.segment_index as usize, Some(&public_memory));
1136 for builtin_runner in self.vm.builtin_runners.iter() {
1137 let (_, size) = builtin_runner
1138 .get_used_cells_and_allocated_size(&self.vm)
1139 .map_err(RunnerError::FinalizeSegements)?;
1140 if let BuiltinRunner::Output(output_builtin) = builtin_runner {
1141 let public_memory = output_builtin.get_public_memory(&self.vm.segments)?;
1142 self.vm
1143 .segments
1144 .finalize(Some(size), builtin_runner.base(), Some(&public_memory))
1145 } else {
1146 self.vm
1147 .segments
1148 .finalize(Some(size), builtin_runner.base(), None)
1149 }
1150 }
1151 self.vm.segments.finalize_zero_segment();
1152 self.segments_finalized = true;
1153 Ok(())
1154 }
1155
1156 #[allow(clippy::result_large_err)]
1157 pub fn run_from_entrypoint(
1161 &mut self,
1162 entrypoint: usize,
1163 args: &[&CairoArg],
1164 verify_secure: bool,
1165 program_segment_size: Option<usize>,
1166 hint_processor: &mut dyn HintProcessor,
1167 ) -> Result<(), CairoRunError> {
1168 let stack = args
1169 .iter()
1170 .map(|arg| self.vm.segments.gen_cairo_arg(arg))
1171 .collect::<Result<Vec<MaybeRelocatable>, VirtualMachineError>>()?;
1172 let return_fp = MaybeRelocatable::from(0);
1173 let end = self.initialize_function_entrypoint(entrypoint, stack, return_fp)?;
1174
1175 self.initialize_vm()?;
1176
1177 self.run_until_pc(end, hint_processor)
1178 .map_err(|err| VmException::from_vm_error(self, err))?;
1179 self.end_run(true, false, hint_processor, self.is_proof_mode())?;
1180
1181 if verify_secure {
1182 verify_secure_runner(self, false, program_segment_size)?;
1183 }
1184
1185 Ok(())
1186 }
1187
1188 pub fn check_used_cells(&self) -> Result<(), VirtualMachineError> {
1191 self.vm
1192 .builtin_runners
1193 .iter()
1194 .map(|builtin_runner| builtin_runner.get_used_cells_and_allocated_size(&self.vm))
1195 .collect::<Result<Vec<(usize, usize)>, MemoryError>>()?;
1196 self.check_range_check_usage()?;
1197 self.check_memory_usage()?;
1198 self.check_diluted_check_usage()?;
1199 Ok(())
1200 }
1201
1202 pub fn check_memory_usage(&self) -> Result<(), VirtualMachineError> {
1204 let instance = &self.layout;
1205
1206 let builtins_memory_units: usize = self
1207 .vm
1208 .builtin_runners
1209 .iter()
1210 .map(|builtin_runner| builtin_runner.get_allocated_memory_units(&self.vm))
1211 .collect::<Result<Vec<usize>, MemoryError>>()?
1212 .iter()
1213 .sum();
1214
1215 let builtins_memory_units = builtins_memory_units as u32;
1216
1217 let vm_current_step_u32 = self.vm.current_step as u32;
1218
1219 let total_memory_units = instance.memory_units_per_step * vm_current_step_u32;
1222 let (public_memory_units, rem) =
1223 div_rem(total_memory_units, instance.public_memory_fraction);
1224 if rem != 0 {
1225 return Err(MathError::SafeDivFailU32(
1226 total_memory_units,
1227 instance.public_memory_fraction,
1228 )
1229 .into());
1230 }
1231
1232 let instruction_memory_units = 4 * vm_current_step_u32;
1233
1234 let unused_memory_units = total_memory_units
1235 - (public_memory_units + instruction_memory_units + builtins_memory_units);
1236 let memory_address_holes = self.get_memory_holes()?;
1237 if unused_memory_units < memory_address_holes as u32 {
1238 Err(MemoryError::InsufficientAllocatedCells(
1239 InsufficientAllocatedCellsError::MemoryAddresses(Box::new((
1240 unused_memory_units,
1241 memory_address_holes,
1242 ))),
1243 ))?
1244 }
1245 Ok(())
1246 }
1247
1248 pub fn initialize_function_runner_cairo_1(
1252 &mut self,
1253 program_builtins: &[BuiltinName],
1254 ) -> Result<(), RunnerError> {
1255 self.program.builtins = program_builtins.to_vec();
1256 self.initialize_program_builtins()?;
1257 self.initialize_segments(self.program_base);
1258 Ok(())
1259 }
1260
1261 pub fn initialize_function_runner(&mut self) -> Result<(), RunnerError> {
1264 self.initialize_program_builtins()?;
1265 self.initialize_segments(self.program_base);
1266 Ok(())
1267 }
1268
1269 pub fn set_entrypoint(&mut self, new_entrypoint: Option<&str>) -> Result<(), ProgramError> {
1272 let new_entrypoint = new_entrypoint.unwrap_or("main");
1273 self.entrypoint = Some(
1274 self.program
1275 .shared_program_data
1276 .identifiers
1277 .get(&format!("__main__.{new_entrypoint}"))
1278 .and_then(|x| x.pc)
1279 .ok_or_else(|| ProgramError::EntrypointNotFound(new_entrypoint.to_string()))?,
1280 );
1281
1282 Ok(())
1283 }
1284
1285 pub fn read_return_values(&mut self, allow_missing_builtins: bool) -> Result<(), RunnerError> {
1286 if !self.run_ended {
1287 return Err(RunnerError::ReadReturnValuesNoEndRun);
1288 }
1289 let mut pointer = self.vm.get_ap();
1290 for builtin_name in self.program.builtins.iter().rev() {
1291 if let Some(builtin_runner) = self
1292 .vm
1293 .builtin_runners
1294 .iter_mut()
1295 .find(|b| b.name() == *builtin_name)
1296 {
1297 let new_pointer = builtin_runner.final_stack(&self.vm.segments, pointer)?;
1298 pointer = new_pointer;
1299 } else {
1300 if !allow_missing_builtins {
1301 return Err(RunnerError::MissingBuiltin(*builtin_name));
1302 }
1303 pointer.offset = pointer.offset.saturating_sub(1);
1304
1305 if !self.vm.get_integer(pointer)?.is_zero() {
1306 return Err(RunnerError::MissingBuiltinStopPtrNotZero(*builtin_name));
1307 }
1308 }
1309 }
1310 if self.segments_finalized {
1311 return Err(RunnerError::FailedAddingReturnValues);
1312 }
1313 if self.is_proof_mode() {
1314 let exec_base = *self
1315 .execution_base
1316 .as_ref()
1317 .ok_or(RunnerError::NoExecBase)?;
1318 let begin = pointer.offset - exec_base.offset;
1319 let ap = self.vm.get_ap();
1320 let end = ap.offset - exec_base.offset;
1321 self.execution_public_memory
1322 .as_mut()
1323 .ok_or(RunnerError::NoExecPublicMemory)?
1324 .extend(begin..end);
1325 }
1326 Ok(())
1327 }
1328
1329 pub fn get_builtins_final_stack(
1332 &mut self,
1333 stack_ptr: Relocatable,
1334 ) -> Result<Relocatable, RunnerError> {
1335 let mut stack_ptr = Relocatable::from(&stack_ptr);
1336 for runner in self
1337 .vm
1338 .builtin_runners
1339 .iter_mut()
1340 .rev()
1341 .filter(|builtin_runner| {
1342 self.program
1343 .builtins
1344 .iter()
1345 .any(|bn| *bn == builtin_runner.name())
1346 })
1347 {
1348 stack_ptr = runner.final_stack(&self.vm.segments, stack_ptr)?
1349 }
1350 Ok(stack_ptr)
1351 }
1352
1353 pub fn get_program(&self) -> &Program {
1355 &self.program
1356 }
1357
1358 pub fn get_cairo_pie(&self) -> Result<CairoPie, RunnerError> {
1360 let program_base = self.program_base.ok_or(RunnerError::NoProgBase)?;
1361 let execution_base = self.execution_base.ok_or(RunnerError::NoExecBase)?;
1362
1363 let builtin_segments = self.get_builtin_segment_info_for_pie()?;
1364 let mut known_segment_indices = HashSet::new();
1365 for info in builtin_segments.values() {
1366 known_segment_indices.insert(info.index);
1367 }
1368 let n_used_builtins = self.program.builtins_len();
1369 let return_fp_addr = (execution_base + n_used_builtins)?;
1370 let return_fp = self.vm.get_relocatable(return_fp_addr)?;
1371 let return_pc = self.vm.get_relocatable((return_fp_addr + 1)?)?;
1372
1373 if let None | Some(false) = return_fp
1374 .segment_index
1375 .to_usize()
1376 .and_then(|u| self.vm.get_segment_size(u))
1377 .map(|u| u.is_zero())
1378 {
1379 return Err(RunnerError::UnexpectedRetFpSegmentSize);
1381 }
1382
1383 if let None | Some(false) = return_pc
1384 .segment_index
1385 .to_usize()
1386 .and_then(|u| self.vm.get_segment_size(u))
1387 .map(|u| u.is_zero())
1388 {
1389 return Err(RunnerError::UnexpectedRetPcSegmentSize);
1391 }
1392
1393 if program_base.offset != 0 {
1394 return Err(RunnerError::ProgramBaseOffsetNotZero);
1395 }
1396 known_segment_indices.insert(program_base.segment_index);
1397
1398 if execution_base.offset != 0 {
1399 return Err(RunnerError::ExecBaseOffsetNotZero);
1400 }
1401 known_segment_indices.insert(execution_base.segment_index);
1402
1403 if return_fp.offset != 0 {
1404 return Err(RunnerError::RetFpOffsetNotZero);
1405 }
1406 known_segment_indices.insert(return_fp.segment_index);
1407
1408 if return_pc.offset != 0 {
1409 return Err(RunnerError::RetPcOffsetNotZero);
1410 }
1411 known_segment_indices.insert(return_pc.segment_index);
1412
1413 let mut extra_segments = Vec::default();
1415 for index in 0..self.vm.segments.num_segments() {
1416 if !known_segment_indices.contains(&(index as isize)) {
1417 extra_segments.push(
1418 (
1419 index as isize,
1420 self.vm
1421 .get_segment_size(index)
1422 .ok_or(MemoryError::MissingSegmentUsedSizes)?,
1423 )
1424 .into(),
1425 );
1426 }
1427 }
1428
1429 let execution_size = (self.vm.get_ap() - execution_base)?;
1430 let metadata = CairoPieMetadata {
1431 program: self
1432 .get_program()
1433 .get_stripped_program()
1434 .map_err(|_| RunnerError::StrippedProgramNoMain)?,
1435 program_segment: (program_base.segment_index, self.program.data_len()).into(),
1436 execution_segment: (execution_base.segment_index, execution_size).into(),
1437 ret_fp_segment: (return_fp.segment_index, 0).into(),
1438 ret_pc_segment: (return_pc.segment_index, 0).into(),
1439 builtin_segments: builtin_segments.into_iter().collect(),
1440 extra_segments,
1441 };
1442
1443 Ok(CairoPie {
1444 metadata,
1445 memory: (&self.vm.segments.memory).into(),
1446 execution_resources: self.get_execution_resources()?,
1447 additional_data: CairoPieAdditionalData(
1448 self.vm
1449 .builtin_runners
1450 .iter()
1451 .map(|b| (b.name(), b.get_additional_data()))
1452 .collect(),
1453 ),
1454 version: CairoPieVersion { cairo_pie: () },
1455 })
1456 }
1457
1458 pub fn get_air_public_input(&'_ self) -> Result<PublicInput<'_>, PublicInputError> {
1459 PublicInput::new(
1460 &self.relocated_memory,
1461 self.layout.name.to_str(),
1462 &self.vm.get_public_memory_addresses()?,
1463 self.get_memory_segment_addresses()?,
1464 self.relocated_trace
1465 .as_ref()
1466 .ok_or(PublicInputError::EmptyTrace)?,
1467 self.get_perm_range_check_limits()
1468 .ok_or(PublicInputError::NoRangeCheckLimits)?,
1469 )
1470 }
1471
1472 pub fn get_air_private_input(&self) -> AirPrivateInput {
1473 let mut private_inputs = HashMap::new();
1474 for builtin in self.vm.builtin_runners.iter() {
1475 private_inputs.insert(builtin.name(), builtin.air_private_input(&self.vm.segments));
1476 }
1477 AirPrivateInput(private_inputs)
1478 }
1479
1480 pub fn get_memory_segment_addresses(
1481 &self,
1482 ) -> Result<HashMap<&'static str, (usize, usize)>, VirtualMachineError> {
1483 let relocation_table = self
1484 .vm
1485 .relocation_table
1486 .as_ref()
1487 .ok_or(MemoryError::UnrelocatedMemory)?;
1488
1489 let relocate = |segment: (usize, usize)| -> Result<(usize, usize), VirtualMachineError> {
1490 let (index, stop_ptr_offset) = segment;
1491 let base = relocation_table
1492 .get(index)
1493 .ok_or(VirtualMachineError::RelocationNotFound(index))?;
1494 Ok((*base, base + stop_ptr_offset))
1495 };
1496
1497 self.vm
1498 .builtin_runners
1499 .iter()
1500 .map(|builtin| -> Result<_, VirtualMachineError> {
1501 let (base, stop_ptr) = builtin.get_memory_segment_addresses();
1502 let stop_ptr = if self.program.builtins.contains(&builtin.name()) {
1503 stop_ptr.ok_or_else(|| RunnerError::NoStopPointer(Box::new(builtin.name())))?
1504 } else {
1505 stop_ptr.unwrap_or_default()
1506 };
1507
1508 Ok((builtin.name().to_str(), relocate((base, stop_ptr))?))
1509 })
1510 .collect()
1511 }
1512
1513 pub fn get_relocatable_trace(&self) -> Result<&[TraceEntry], RunnerError> {
1515 self.vm
1516 .trace
1517 .as_deref()
1518 .ok_or(RunnerError::Trace(TraceError::TraceNotEnabled))
1519 }
1520
1521 pub fn get_relocatable_memory(&self) -> Vec<Vec<Option<MaybeRelocatable>>> {
1523 self.vm
1524 .segments
1525 .memory
1526 .data
1527 .iter()
1528 .map(|segment| segment.iter().map(|cell| cell.get_value()).collect())
1529 .collect()
1530 }
1531
1532 pub fn get_builtin_segments(&self) -> BTreeMap<usize, BuiltinName> {
1534 self.vm
1535 .builtin_runners
1536 .iter()
1537 .map(|builtin| {
1538 let (index, _) = builtin.get_memory_segment_addresses();
1539 (index, builtin.name())
1540 })
1541 .collect()
1542 }
1543}
1544
1545#[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
1550pub struct ExecutionResources {
1551 pub n_steps: usize,
1552 pub n_memory_holes: usize,
1553 #[serde(with = "crate::types::builtin_name::serde_generic_map_impl")]
1554 pub builtin_instance_counter: BTreeMap<BuiltinName, usize>,
1555}
1556
1557impl ExecutionResources {
1560 pub fn filter_unused_builtins(&self) -> ExecutionResources {
1561 ExecutionResources {
1562 n_steps: self.n_steps,
1563 n_memory_holes: self.n_memory_holes,
1564 builtin_instance_counter: self
1565 .clone()
1566 .builtin_instance_counter
1567 .into_iter()
1568 .filter(|builtin| !builtin.1.is_zero())
1569 .collect(),
1570 }
1571 }
1572}
1573
1574impl Add<&ExecutionResources> for &ExecutionResources {
1575 type Output = ExecutionResources;
1576
1577 fn add(self, rhs: &ExecutionResources) -> ExecutionResources {
1578 let mut new = self.clone();
1579 new.add_assign(rhs);
1580 new
1581 }
1582}
1583
1584impl AddAssign<&ExecutionResources> for ExecutionResources {
1585 fn add_assign(&mut self, rhs: &ExecutionResources) {
1586 self.n_steps += rhs.n_steps;
1587 self.n_memory_holes += rhs.n_memory_holes;
1588 for (k, v) in rhs.builtin_instance_counter.iter() {
1589 *self.builtin_instance_counter.entry(*k).or_insert(0) += v;
1591 }
1592 }
1593}
1594
1595impl Sub<&ExecutionResources> for &ExecutionResources {
1596 type Output = ExecutionResources;
1597
1598 fn sub(self, rhs: &ExecutionResources) -> ExecutionResources {
1599 let mut new = self.clone();
1600 new.sub_assign(rhs);
1601 new
1602 }
1603}
1604
1605impl SubAssign<&ExecutionResources> for ExecutionResources {
1606 fn sub_assign(&mut self, rhs: &ExecutionResources) {
1607 self.n_steps -= rhs.n_steps;
1608 self.n_memory_holes -= rhs.n_memory_holes;
1609 for (k, v) in rhs.builtin_instance_counter.iter() {
1610 let entry = self.builtin_instance_counter.entry(*k).or_insert(0);
1612 *entry = (*entry).saturating_sub(*v);
1613 }
1614 }
1615}
1616
1617impl Mul<usize> for &ExecutionResources {
1618 type Output = ExecutionResources;
1619
1620 fn mul(self, rhs: usize) -> ExecutionResources {
1621 let mut new = self.clone();
1622 new.mul_assign(rhs);
1623 new
1624 }
1625}
1626
1627impl MulAssign<usize> for ExecutionResources {
1628 fn mul_assign(&mut self, rhs: usize) {
1629 self.n_steps *= rhs;
1630 self.n_memory_holes *= rhs;
1631 for (_builtin_name, counter) in self.builtin_instance_counter.iter_mut() {
1632 *counter *= rhs;
1633 }
1634 }
1635}
1636
1637#[cfg(test)]
1638mod tests {
1639 use super::*;
1640 use crate::air_private_input::{PrivateInput, PrivateInputSignature, SignatureInput};
1641 use crate::cairo_run::{cairo_run, CairoRunConfig};
1642 use crate::stdlib::collections::{HashMap, HashSet};
1643 use crate::types::instance_definitions::bitwise_instance_def::CELLS_PER_BITWISE;
1644 use crate::types::instance_definitions::keccak_instance_def::CELLS_PER_KECCAK;
1645 use crate::vm::vm_memory::memory::MemoryCell;
1646
1647 use crate::felt_hex;
1648 use crate::{
1649 hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor,
1650 relocatable,
1651 serde::deserialize_program::{Identifier, ReferenceManager},
1652 utils::test_utils::*,
1653 vm::trace::trace_entry::TraceEntry,
1654 };
1655 use assert_matches::assert_matches;
1656
1657 #[cfg(target_arch = "wasm32")]
1658 use wasm_bindgen_test::*;
1659
1660 #[test]
1661 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1662 fn check_memory_usage_ok_case() {
1663 let program = program![BuiltinName::range_check, BuiltinName::output];
1664 let mut cairo_runner = cairo_runner!(program);
1665 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
1666
1667 assert_matches!(cairo_runner.check_memory_usage(), Ok(()));
1668 }
1669
1670 #[test]
1671 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1672 fn check_memory_usage_err_case() {
1673 let program = program!();
1674
1675 let mut cairo_runner = cairo_runner!(program);
1676 cairo_runner.vm.builtin_runners = vec![{
1677 let mut builtin_runner: BuiltinRunner = OutputBuiltinRunner::new(true).into();
1678 builtin_runner.initialize_segments(&mut cairo_runner.vm.segments);
1679
1680 builtin_runner
1681 }];
1682 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4, 12]);
1683 cairo_runner.vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 1)];
1684 cairo_runner
1685 .vm
1686 .segments
1687 .memory
1688 .mark_as_accessed((0, 0).into());
1689 assert_matches!(
1690 cairo_runner.check_memory_usage(),
1691 Err(VirtualMachineError::Memory(
1692 MemoryError::InsufficientAllocatedCells(_)
1693 ))
1694 );
1695 }
1696
1697 #[test]
1698 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1699 fn initialize_builtins_with_disordered_builtins() {
1700 let program = program![BuiltinName::range_check, BuiltinName::output];
1701 let mut cairo_runner = cairo_runner!(program, LayoutName::plain);
1702 assert!(cairo_runner.initialize_builtins(false).is_err());
1703 }
1704
1705 #[test]
1706 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1707 fn initialize_builtins_missing_builtins_no_allow_missing() {
1708 let program = program![BuiltinName::output, BuiltinName::ecdsa];
1709 let mut cairo_runner = cairo_runner!(program, LayoutName::plain);
1710 assert_matches!(
1711 cairo_runner.initialize_builtins(false),
1712 Err(RunnerError::NoBuiltinForInstance(_))
1713 )
1714 }
1715
1716 #[test]
1717 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1718 fn initialize_builtins_missing_builtins_allow_missing() {
1719 let program = program![BuiltinName::output, BuiltinName::ecdsa];
1720 let mut cairo_runner = cairo_runner!(program);
1721 assert!(cairo_runner.initialize_builtins(true).is_ok())
1722 }
1723
1724 #[test]
1725 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1726 fn initialize_segments_with_base() {
1727 let program = program![BuiltinName::output];
1728 let mut cairo_runner = cairo_runner!(program);
1729 let program_base = Some(Relocatable {
1730 segment_index: 5,
1731 offset: 9,
1732 });
1733 add_segments!(&mut cairo_runner.vm, 6);
1734 cairo_runner.initialize_builtins(false).unwrap();
1735 cairo_runner.initialize_segments(program_base);
1736 assert_eq!(
1737 cairo_runner.program_base,
1738 Some(Relocatable {
1739 segment_index: 5,
1740 offset: 9,
1741 })
1742 );
1743 assert_eq!(
1744 cairo_runner.execution_base,
1745 Some(Relocatable {
1746 segment_index: 6,
1747 offset: 0,
1748 })
1749 );
1750 assert_eq!(
1751 cairo_runner.vm.builtin_runners[0].name(),
1752 BuiltinName::output
1753 );
1754 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 7);
1755
1756 assert_eq!(cairo_runner.vm.segments.num_segments(), 8);
1757 }
1758
1759 #[test]
1760 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1761 fn initialize_segments_no_base() {
1762 let program = program![BuiltinName::output];
1763 let mut cairo_runner = cairo_runner!(program);
1764 cairo_runner.initialize_builtins(false).unwrap();
1765 cairo_runner.initialize_segments(None);
1766 assert_eq!(
1767 cairo_runner.program_base,
1768 Some(Relocatable {
1769 segment_index: 0,
1770 offset: 0
1771 })
1772 );
1773 assert_eq!(
1774 cairo_runner.execution_base,
1775 Some(Relocatable {
1776 segment_index: 1,
1777 offset: 0
1778 })
1779 );
1780 assert_eq!(
1781 cairo_runner.vm.builtin_runners[0].name(),
1782 BuiltinName::output
1783 );
1784 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 2);
1785
1786 assert_eq!(cairo_runner.vm.segments.num_segments(), 3);
1787 }
1788
1789 #[test]
1790 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1791 fn initialize_state_empty_data_and_stack() {
1792 let program = program![BuiltinName::output];
1793 let mut cairo_runner = cairo_runner!(program);
1794 cairo_runner.program_base = Some(relocatable!(1, 0));
1795 cairo_runner.execution_base = Some(relocatable!(2, 0));
1796 let stack = Vec::new();
1797 cairo_runner.initialize_builtins(false).unwrap();
1798 cairo_runner.initialize_state(1, stack).unwrap();
1799 assert_eq!(
1800 cairo_runner.initial_pc,
1801 Some(Relocatable {
1802 segment_index: 1,
1803 offset: 1
1804 })
1805 );
1806 }
1807
1808 #[test]
1809 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1810 fn initialize_state_some_data_empty_stack() {
1811 let program = program!(
1812 builtins = vec![BuiltinName::output],
1813 data = vec_data!((4), (6)),
1814 );
1815 let mut cairo_runner = cairo_runner!(program);
1816 for _ in 0..2 {
1817 cairo_runner.vm.segments.add();
1818 }
1819 cairo_runner.program_base = Some(Relocatable {
1820 segment_index: 1,
1821 offset: 0,
1822 });
1823 cairo_runner.execution_base = Some(relocatable!(2, 0));
1824 let stack = Vec::new();
1825 cairo_runner.initialize_state(1, stack).unwrap();
1826 check_memory!(cairo_runner.vm.segments.memory, ((1, 0), 4), ((1, 1), 6));
1827 }
1828
1829 #[test]
1830 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1831 fn initialize_state_empty_data_some_stack() {
1832 let program = program![BuiltinName::output];
1833 let mut cairo_runner = cairo_runner!(program);
1834 for _ in 0..3 {
1835 cairo_runner.vm.segments.add();
1836 }
1837 cairo_runner.program_base = Some(relocatable!(1, 0));
1838 cairo_runner.execution_base = Some(relocatable!(2, 0));
1839 let stack = vec![mayberelocatable!(4), mayberelocatable!(6)];
1840 cairo_runner.initialize_state(1, stack).unwrap();
1841 check_memory!(cairo_runner.vm.segments.memory, ((2, 0), 4), ((2, 1), 6));
1842 }
1843
1844 #[test]
1845 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1846 fn initialize_state_no_program_base() {
1847 let program = program![BuiltinName::output];
1848 let mut cairo_runner = cairo_runner!(program);
1849 for _ in 0..2 {
1850 cairo_runner.vm.segments.add();
1851 }
1852 cairo_runner.execution_base = Some(Relocatable {
1853 segment_index: 2,
1854 offset: 0,
1855 });
1856 let stack = vec![
1857 MaybeRelocatable::from(Felt252::from(4_i32)),
1858 MaybeRelocatable::from(Felt252::from(6_i32)),
1859 ];
1860 assert!(cairo_runner.initialize_state(1, stack).is_err());
1861 }
1862
1863 #[test]
1864 #[should_panic]
1865 fn initialize_state_no_execution_base() {
1866 let program = program![BuiltinName::output];
1867 let mut cairo_runner = cairo_runner!(program);
1868 for _ in 0..2 {
1869 cairo_runner.vm.segments.add();
1870 }
1871 cairo_runner.program_base = Some(relocatable!(1, 0));
1872 let stack = vec![
1873 MaybeRelocatable::from(Felt252::from(4_i32)),
1874 MaybeRelocatable::from(Felt252::from(6_i32)),
1875 ];
1876 cairo_runner.initialize_state(1, stack).unwrap();
1877 }
1878
1879 #[test]
1880 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1881 fn initialize_function_entrypoint_empty_stack() {
1882 let program = program![BuiltinName::output];
1883 let mut cairo_runner = cairo_runner!(program);
1884 for _ in 0..2 {
1885 cairo_runner.vm.segments.add();
1886 }
1887 cairo_runner.program_base = Some(relocatable!(0, 0));
1888 cairo_runner.execution_base = Some(relocatable!(1, 0));
1889 let stack = Vec::new();
1890 let return_fp = MaybeRelocatable::from(Felt252::from(9_i32));
1891 cairo_runner
1892 .initialize_function_entrypoint(0, stack, return_fp)
1893 .unwrap();
1894 assert_eq!(cairo_runner.initial_fp, cairo_runner.initial_ap);
1895 assert_eq!(cairo_runner.initial_fp, Some(relocatable!(1, 2)));
1896 check_memory!(
1897 cairo_runner.vm.segments.memory,
1898 ((1, 0), 9),
1899 ((1, 1), (2, 0))
1900 );
1901 }
1902
1903 #[test]
1904 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1905 fn initialize_function_entrypoint_some_stack() {
1906 let program = program![BuiltinName::output];
1907 let mut cairo_runner = cairo_runner!(program);
1908 for _ in 0..2 {
1909 cairo_runner.vm.segments.add();
1910 }
1911 cairo_runner.program_base = Some(relocatable!(0, 0));
1912 cairo_runner.execution_base = Some(relocatable!(1, 0));
1913 let stack = vec![MaybeRelocatable::from(Felt252::from(7_i32))];
1914 let return_fp = MaybeRelocatable::from(Felt252::from(9_i32));
1915 cairo_runner
1916 .initialize_function_entrypoint(1, stack, return_fp)
1917 .unwrap();
1918 assert_eq!(cairo_runner.initial_fp, cairo_runner.initial_ap);
1919 assert_eq!(cairo_runner.initial_fp, Some(relocatable!(1, 3)));
1920 check_memory!(
1921 cairo_runner.vm.segments.memory,
1922 ((1, 0), 7),
1923 ((1, 1), 9),
1924 ((1, 2), (2, 0))
1925 );
1926 }
1927
1928 #[test]
1929 #[should_panic]
1930 fn initialize_function_entrypoint_no_execution_base() {
1931 let program = program![BuiltinName::output];
1932 let mut cairo_runner = cairo_runner!(program);
1933 let stack = vec![MaybeRelocatable::from(Felt252::from(7_i32))];
1934 let return_fp = MaybeRelocatable::from(Felt252::from(9_i32));
1935 cairo_runner
1936 .initialize_function_entrypoint(1, stack, return_fp)
1937 .unwrap();
1938 }
1939
1940 #[test]
1941 #[should_panic]
1942 fn initialize_main_entrypoint_no_main() {
1943 let program = program![BuiltinName::output];
1944 let mut cairo_runner = cairo_runner!(program);
1945 cairo_runner.initialize_main_entrypoint().unwrap();
1946 }
1947
1948 #[test]
1949 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1950 fn initialize_main_entrypoint() {
1951 let program = program!(main = Some(1),);
1952 let mut cairo_runner = cairo_runner!(program);
1953 cairo_runner.program_base = Some(relocatable!(0, 0));
1954 cairo_runner.execution_base = Some(relocatable!(0, 0));
1955 let return_pc = cairo_runner.initialize_main_entrypoint().unwrap();
1956 assert_eq!(return_pc, Relocatable::from((1, 0)));
1957 }
1958
1959 #[test]
1960 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1961 fn initialize_state_program_segment_accessed_addrs() {
1962 let program = Program::from_bytes(
1966 include_bytes!("../../../../cairo_programs/fibonacci.json"),
1967 Some("main"),
1968 )
1969 .unwrap();
1970
1971 let mut cairo_runner = cairo_runner!(program);
1972
1973 cairo_runner.initialize(false).unwrap();
1974 assert_eq!(
1975 cairo_runner
1976 .vm
1977 .segments
1978 .memory
1979 .get_amount_of_accessed_addresses_for_segment(0),
1980 Some(24)
1981 );
1982 }
1983
1984 #[test]
1985 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1986 fn initialize_vm_no_builtins() {
1987 let program = program!(main = Some(1),);
1988 let mut cairo_runner = cairo_runner!(program);
1989 cairo_runner.program_base = Some(relocatable!(0, 0));
1990 cairo_runner.initial_pc = Some(relocatable!(0, 1));
1991 cairo_runner.initial_ap = Some(relocatable!(1, 2));
1992 cairo_runner.initial_fp = Some(relocatable!(1, 2));
1993 cairo_runner.initialize_vm().unwrap();
1994 assert_eq!(cairo_runner.vm.run_context.pc, relocatable!(0, 1));
1995 assert_eq!(cairo_runner.vm.run_context.ap, 2);
1996 assert_eq!(cairo_runner.vm.run_context.fp, 2);
1997 }
1998
1999 #[test]
2000 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2001 fn initialize_vm_with_range_check_valid() {
2002 let program = program!(builtins = vec![BuiltinName::range_check], main = Some(1),);
2003 let mut cairo_runner = cairo_runner!(program);
2004 cairo_runner.initial_pc = Some(relocatable!(0, 1));
2005 cairo_runner.initial_ap = Some(relocatable!(1, 2));
2006 cairo_runner.initial_fp = Some(relocatable!(1, 2));
2007 cairo_runner.initialize_builtins(false).unwrap();
2008 cairo_runner.initialize_segments(None);
2009 cairo_runner.vm.segments = segments![((2, 0), 23), ((2, 1), 233)];
2010 assert_eq!(
2011 cairo_runner.vm.builtin_runners[0].name(),
2012 BuiltinName::range_check
2013 );
2014 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 2);
2015 cairo_runner.initialize_vm().unwrap();
2016 assert!(cairo_runner
2017 .vm
2018 .segments
2019 .memory
2020 .validated_addresses
2021 .contains(&Relocatable::from((2, 0))));
2022 assert!(cairo_runner
2023 .vm
2024 .segments
2025 .memory
2026 .validated_addresses
2027 .contains(&Relocatable::from((2, 1))));
2028 assert_eq!(cairo_runner.vm.segments.memory.validated_addresses.len(), 2);
2029 }
2030
2031 #[test]
2032 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2033 fn initialize_vm_with_range_check_invalid() {
2034 let program = program!(builtins = vec![BuiltinName::range_check], main = Some(1),);
2035 let mut cairo_runner = cairo_runner!(program);
2036 cairo_runner.initial_pc = Some(relocatable!(0, 1));
2037 cairo_runner.initial_ap = Some(relocatable!(1, 2));
2038 cairo_runner.initial_fp = Some(relocatable!(1, 2));
2039 cairo_runner.initialize_builtins(false).unwrap();
2040 cairo_runner.initialize_segments(None);
2041 cairo_runner.vm.segments = segments![((2, 1), 23), ((2, 4), (-1))];
2042
2043 assert_eq!(
2044 cairo_runner.initialize_vm(),
2045 Err(RunnerError::MemoryValidationError(
2046 MemoryError::RangeCheckFoundNonInt(Box::new((2, 0).into()))
2047 ))
2048 );
2049 }
2050
2051 #[test]
2054 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2055 fn initialization_phase_no_builtins() {
2071 let program = program!(
2072 data = vec_data!(
2073 (5207990763031199744_u64),
2074 (2),
2075 (2345108766317314046_u64),
2076 (5189976364521848832_u64),
2077 (1),
2078 (1226245742482522112_u64),
2079 ((
2080 "3618502788666131213697322783095070105623107215331596699973092056135872020476",
2081 10
2082 )),
2083 (2345108766317314046_i64)
2084 ),
2085 main = Some(3),
2086 );
2087 let mut cairo_runner = cairo_runner!(program);
2088 cairo_runner.initialize_segments(None);
2089 cairo_runner.initialize_main_entrypoint().unwrap();
2090 cairo_runner.initialize_vm().unwrap();
2091
2092 assert_eq!(cairo_runner.program_base, Some(relocatable!(0, 0)));
2093 assert_eq!(cairo_runner.execution_base, Some(relocatable!(1, 0)));
2094 assert_eq!(cairo_runner.final_pc, Some(relocatable!(3, 0)));
2095
2096 assert_eq!(cairo_runner.vm.run_context.pc, relocatable!(0, 3));
2099 assert_eq!(cairo_runner.vm.run_context.ap, 2);
2100 assert_eq!(cairo_runner.vm.run_context.fp, 2);
2101 check_memory!(
2103 cairo_runner.vm.segments.memory,
2104 ((0, 0), 5207990763031199744_u64),
2105 ((0, 1), 2),
2106 ((0, 2), 2345108766317314046_u64),
2107 ((0, 3), 5189976364521848832_u64),
2108 ((0, 4), 1),
2109 ((0, 5), 1226245742482522112_u64),
2110 (
2111 (0, 6),
2112 (
2113 "3618502788666131213697322783095070105623107215331596699973092056135872020476",
2114 10
2115 )
2116 ),
2117 ((0, 7), 2345108766317314046_u64),
2118 ((1, 0), (2, 0)),
2119 ((1, 1), (3, 0))
2120 );
2121 }
2122
2123 #[test]
2124 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2125 fn initialization_phase_output_builtin() {
2140 let program = program!(
2141 builtins = vec![BuiltinName::output],
2142 data = vec_data!(
2143 (4612671182993129469_u64),
2144 (5198983563776393216_u64),
2145 (1),
2146 (2345108766317314046_u64),
2147 (5191102247248822272_u64),
2148 (5189976364521848832_u64),
2149 (1),
2150 (1226245742482522112_u64),
2151 ((
2152 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
2153 10
2154 )),
2155 (2345108766317314046_u64)
2156 ),
2157 main = Some(4),
2158 );
2159 let mut cairo_runner = cairo_runner!(program);
2160
2161 cairo_runner.initialize_builtins(false).unwrap();
2162 cairo_runner.initialize_segments(None);
2163 cairo_runner.initialize_main_entrypoint().unwrap();
2164 cairo_runner.initialize_vm().unwrap();
2165
2166 assert_eq!(cairo_runner.program_base, Some(relocatable!(0, 0)));
2167 assert_eq!(cairo_runner.execution_base, Some(relocatable!(1, 0)));
2168 assert_eq!(cairo_runner.final_pc, Some(relocatable!(4, 0)));
2169
2170 assert_eq!(cairo_runner.vm.run_context.pc, relocatable!(0, 4));
2173 assert_eq!(cairo_runner.vm.run_context.ap, 3);
2174 assert_eq!(cairo_runner.vm.run_context.fp, 3);
2175 check_memory!(
2177 cairo_runner.vm.segments.memory,
2178 ((0, 0), 4612671182993129469_u64),
2179 ((0, 1), 5198983563776393216_u64),
2180 ((0, 2), 1),
2181 ((0, 3), 2345108766317314046_u64),
2182 ((0, 4), 5191102247248822272_u64),
2183 ((0, 5), 5189976364521848832_u64),
2184 ((0, 6), 1),
2185 ((0, 7), 1226245742482522112_u64),
2186 (
2187 (0, 8),
2188 (
2189 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
2190 10
2191 )
2192 ),
2193 ((0, 9), 2345108766317314046_u64),
2194 ((1, 0), (2, 0)),
2195 ((1, 1), (3, 0)),
2196 ((1, 2), (4, 0))
2197 );
2198 }
2199
2200 #[test]
2201 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2202 fn initialization_phase_range_check_builtin() {
2223 let program = program!(
2224 builtins = vec![BuiltinName::range_check],
2225 data = vec_data!(
2226 (4612671182993129469_u64),
2227 (5189976364521848832_u64),
2228 (18446744073709551615_u128),
2229 (5199546496550207487_u64),
2230 (4612389712311386111_u64),
2231 (5198983563776393216_u64),
2232 (2),
2233 (2345108766317314046_u64),
2234 (5191102247248822272_u64),
2235 (5189976364521848832_u64),
2236 (7),
2237 (1226245742482522112_u64),
2238 ((
2239 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
2240 10
2241 )),
2242 (2345108766317314046_u64)
2243 ),
2244 main = Some(8),
2245 );
2246
2247 let mut cairo_runner = cairo_runner!(program);
2248
2249 cairo_runner.initialize_builtins(false).unwrap();
2250 cairo_runner.initialize_segments(None);
2251 cairo_runner.initialize_main_entrypoint().unwrap();
2252 cairo_runner.initialize_vm().unwrap();
2253
2254 assert_eq!(cairo_runner.program_base, Some(relocatable!(0, 0)));
2255 assert_eq!(cairo_runner.execution_base, Some(relocatable!(1, 0)));
2256 assert_eq!(cairo_runner.final_pc, Some(relocatable!(4, 0)));
2257
2258 assert_eq!(cairo_runner.vm.run_context.pc, relocatable!(0, 8));
2261 assert_eq!(cairo_runner.vm.run_context.ap, 3);
2262 assert_eq!(cairo_runner.vm.run_context.fp, 3);
2263 check_memory!(
2265 cairo_runner.vm.segments.memory,
2266 ((0, 0), 4612671182993129469_u64),
2267 ((0, 1), 5189976364521848832_u64),
2268 ((0, 2), 18446744073709551615_u128),
2269 ((0, 3), 5199546496550207487_u64),
2270 ((0, 4), 4612389712311386111_u64),
2271 ((0, 5), 5198983563776393216_u64),
2272 ((0, 6), 2),
2273 ((0, 7), 2345108766317314046_u64),
2274 ((0, 8), 5191102247248822272_u64),
2275 ((0, 9), 5189976364521848832_u64),
2276 ((0, 10), 7),
2277 ((0, 11), 1226245742482522112_u64),
2278 (
2279 (0, 12),
2280 (
2281 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
2282 10
2283 )
2284 ),
2285 ((0, 13), 2345108766317314046_u64),
2286 ((1, 0), (2, 0)),
2287 ((1, 1), (3, 0)),
2288 ((1, 2), (4, 0))
2289 );
2290 }
2291
2292 #[test]
2295 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2296 fn initialize_and_run_function_call() {
2312 let program = program!(
2314 data = vec_data!(
2315 (5207990763031199744_i64),
2316 (2),
2317 (2345108766317314046_i64),
2318 (5189976364521848832_i64),
2319 (1),
2320 (1226245742482522112_i64),
2321 ((
2322 "3618502788666131213697322783095070105623107215331596699973092056135872020476",
2323 10
2324 )),
2325 (2345108766317314046_i64)
2326 ),
2327 main = Some(3),
2328 );
2329 let mut hint_processor = BuiltinHintProcessor::new_empty();
2330 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
2331 cairo_runner.initialize_segments(None);
2332 let end = cairo_runner.initialize_main_entrypoint().unwrap();
2333 assert_eq!(end, Relocatable::from((3, 0)));
2334 cairo_runner.initialize_vm().unwrap();
2335 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
2337 assert_eq!(cairo_runner.vm.run_context.pc, Relocatable::from((3, 0)));
2340
2341 assert_eq!(cairo_runner.vm.run_context.ap, 6);
2342
2343 assert_eq!(cairo_runner.vm.run_context.fp, 0);
2344
2345 let trace = cairo_runner.vm.trace.unwrap();
2347 assert_eq!(trace.len(), 5);
2348 trace_check(
2349 &trace,
2350 &[
2351 ((0, 3).into(), 2, 2),
2352 ((0, 5).into(), 3, 2),
2353 ((0, 0).into(), 5, 5),
2354 ((0, 2).into(), 6, 5),
2355 ((0, 7).into(), 6, 2),
2356 ],
2357 );
2358 }
2359
2360 #[test]
2361 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2362 fn initialize_and_run_range_check_builtin() {
2383 let program = program!(
2385 builtins = vec![BuiltinName::range_check],
2386 data = vec_data!(
2387 (4612671182993129469_i64),
2388 (5189976364521848832_i64),
2389 (18446744073709551615_i128),
2390 (5199546496550207487_i64),
2391 (4612389712311386111_i64),
2392 (5198983563776393216_i64),
2393 (2),
2394 (2345108766317314046_i64),
2395 (5191102247248822272_i64),
2396 (5189976364521848832_i64),
2397 (7),
2398 (1226245742482522112_i64),
2399 ((
2400 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
2401 10
2402 )),
2403 (2345108766317314046_i64)
2404 ),
2405 main = Some(8),
2406 );
2407 let mut hint_processor = BuiltinHintProcessor::new_empty();
2408 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
2409 cairo_runner.initialize_builtins(false).unwrap();
2410 cairo_runner.initialize_segments(None);
2411 let end = cairo_runner.initialize_main_entrypoint().unwrap();
2412 cairo_runner.initialize_vm().unwrap();
2413 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
2415 assert_eq!(cairo_runner.vm.run_context.pc, Relocatable::from((4, 0)));
2418
2419 assert_eq!(cairo_runner.vm.run_context.ap, 10);
2420
2421 assert_eq!(cairo_runner.vm.run_context.fp, 0);
2422
2423 let trace = cairo_runner.vm.trace.unwrap();
2425 assert_eq!(trace.len(), 10);
2426 trace_check(
2427 &trace,
2428 &[
2429 ((0, 8).into(), 3, 3),
2430 ((0, 9).into(), 4, 3),
2431 ((0, 11).into(), 5, 3),
2432 ((0, 0).into(), 7, 7),
2433 ((0, 1).into(), 7, 7),
2434 ((0, 3).into(), 8, 7),
2435 ((0, 4).into(), 9, 7),
2436 ((0, 5).into(), 9, 7),
2437 ((0, 7).into(), 10, 7),
2438 ((0, 13).into(), 10, 3),
2439 ],
2440 );
2441 assert_eq!(
2443 cairo_runner.vm.builtin_runners[0].name(),
2444 BuiltinName::range_check
2445 );
2446 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 2);
2447
2448 check_memory!(
2449 cairo_runner.vm.segments.memory,
2450 ((2, 0), 7),
2451 ((2, 1), 18446744073709551608_i128)
2452 );
2453 assert!(cairo_runner
2454 .vm
2455 .segments
2456 .memory
2457 .get(&MaybeRelocatable::from((2, 2)))
2458 .is_none());
2459 }
2460
2461 #[test]
2462 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2463 fn initialize_and_run_output_builtin() {
2495 let program = program!(
2497 builtins = vec![BuiltinName::output],
2498 data = vec_data!(
2499 (4612671182993129469_i64),
2500 (5198983563776393216_i64),
2501 (1),
2502 (2345108766317314046_i64),
2503 (5191102247248822272_i64),
2504 (5189976364521848832_i64),
2505 (1),
2506 (1226245742482522112_i64),
2507 ((
2508 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
2509 10
2510 )),
2511 (5189976364521848832_i64),
2512 (17),
2513 (1226245742482522112_i64),
2514 ((
2515 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
2516 10
2517 )),
2518 (2345108766317314046_i64)
2519 ),
2520 main = Some(4),
2521 );
2522 let mut hint_processor = BuiltinHintProcessor::new_empty();
2523 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
2524 cairo_runner.initialize_builtins(false).unwrap();
2525 cairo_runner.initialize_segments(None);
2526 let end = cairo_runner.initialize_main_entrypoint().unwrap();
2527 cairo_runner.initialize_vm().unwrap();
2528 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
2530 assert_eq!(cairo_runner.vm.run_context.pc, Relocatable::from((4, 0)));
2534
2535 assert_eq!(cairo_runner.vm.run_context.ap, 12);
2536
2537 assert_eq!(cairo_runner.vm.run_context.fp, 0);
2538
2539 let trace = cairo_runner.vm.trace.unwrap();
2541 assert_eq!(trace.len(), 12);
2542 trace_check(
2543 &trace,
2544 &[
2545 ((0, 4).into(), 3, 3),
2546 ((0, 5).into(), 4, 3),
2547 ((0, 7).into(), 5, 3),
2548 ((0, 0).into(), 7, 7),
2549 ((0, 1).into(), 7, 7),
2550 ((0, 3).into(), 8, 7),
2551 ((0, 9).into(), 8, 3),
2552 ((0, 11).into(), 9, 3),
2553 ((0, 0).into(), 11, 11),
2554 ((0, 1).into(), 11, 11),
2555 ((0, 3).into(), 12, 11),
2556 ((0, 13).into(), 12, 3),
2557 ],
2558 );
2559 assert_eq!(
2561 cairo_runner.vm.builtin_runners[0].name(),
2562 BuiltinName::output
2563 );
2564 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 2);
2565 check_memory!(cairo_runner.vm.segments.memory, ((2, 0), 1), ((2, 1), 17));
2566 assert!(cairo_runner
2567 .vm
2568 .segments
2569 .memory
2570 .get(&MaybeRelocatable::from((2, 2)))
2571 .is_none());
2572 }
2573
2574 #[test]
2575 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2576 fn initialize_and_run_output_range_check_builtin() {
2624 let program = program!(
2626 builtins = vec![BuiltinName::output, BuiltinName::range_check],
2627 data = vec_data!(
2628 (4612671182993129469_i64),
2629 (5198983563776393216_i64),
2630 (1),
2631 (2345108766317314046_i64),
2632 (4612671182993129469_i64),
2633 (5189976364521848832_i64),
2634 (18446744073709551615_i128),
2635 (5199546496550207487_i64),
2636 (4612389712311386111_i64),
2637 (5198983563776393216_i64),
2638 (2),
2639 (5191102247248822272_i64),
2640 (2345108766317314046_i64),
2641 (5191102247248822272_i64),
2642 (5189976364521848832_i64),
2643 (7),
2644 (1226245742482522112_i64),
2645 ((
2646 "3618502788666131213697322783095070105623107215331596699973092056135872020469",
2647 10
2648 )),
2649 (5191102242953854976_i64),
2650 (5193354051357474816_i64),
2651 (1226245742482522112_i64),
2652 ((
2653 "3618502788666131213697322783095070105623107215331596699973092056135872020461",
2654 10
2655 )),
2656 (5193354029882638336_i64),
2657 (2345108766317314046_i64)
2658 ),
2659 main = Some(13),
2660 );
2661 let mut hint_processor = BuiltinHintProcessor::new_empty();
2662 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
2663 cairo_runner.initialize_builtins(false).unwrap();
2664 cairo_runner.initialize_segments(None);
2665 let end = cairo_runner.initialize_main_entrypoint().unwrap();
2666 cairo_runner.initialize_vm().unwrap();
2667 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
2669 assert_eq!(cairo_runner.vm.run_context.pc, Relocatable::from((5, 0)));
2672
2673 assert_eq!(cairo_runner.vm.run_context.ap, 18);
2674
2675 assert_eq!(cairo_runner.vm.run_context.fp, 0);
2676
2677 let trace = cairo_runner.vm.trace.unwrap();
2679 assert_eq!(trace.len(), 18);
2680 trace_check(
2681 &trace,
2682 &[
2683 ((0, 13).into(), 4, 4),
2684 ((0, 14).into(), 5, 4),
2685 ((0, 16).into(), 6, 4),
2686 ((0, 4).into(), 8, 8),
2687 ((0, 5).into(), 8, 8),
2688 ((0, 7).into(), 9, 8),
2689 ((0, 8).into(), 10, 8),
2690 ((0, 9).into(), 10, 8),
2691 ((0, 11).into(), 11, 8),
2692 ((0, 12).into(), 12, 8),
2693 ((0, 18).into(), 12, 4),
2694 ((0, 19).into(), 13, 4),
2695 ((0, 20).into(), 14, 4),
2696 ((0, 0).into(), 16, 16),
2697 ((0, 1).into(), 16, 16),
2698 ((0, 3).into(), 17, 16),
2699 ((0, 22).into(), 17, 4),
2700 ((0, 23).into(), 18, 4),
2701 ],
2702 );
2703 assert_eq!(
2705 cairo_runner.vm.builtin_runners[1].name(),
2706 BuiltinName::range_check
2707 );
2708 assert_eq!(cairo_runner.vm.builtin_runners[1].base(), 3);
2709
2710 check_memory!(
2711 cairo_runner.vm.segments.memory,
2712 ((3, 0), 7),
2713 ((3, 1), 18446744073709551608_i128)
2714 );
2715 assert!(cairo_runner
2716 .vm
2717 .segments
2718 .memory
2719 .get(&MaybeRelocatable::from((2, 2)))
2720 .is_none());
2721
2722 assert_eq!(
2724 cairo_runner.vm.builtin_runners[0].name(),
2725 BuiltinName::output
2726 );
2727 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 2);
2728
2729 check_memory!(cairo_runner.vm.segments.memory, ((2, 0), 7));
2730 assert!(cairo_runner
2731 .vm
2732 .segments
2733 .memory
2734 .get(&(MaybeRelocatable::from((2, 1))))
2735 .is_none());
2736 }
2737
2738 #[test]
2739 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2740 fn relocate_memory_with_gap() {
2765 let program = program!();
2766 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
2767 for _ in 0..4 {
2768 cairo_runner.vm.segments.add();
2769 }
2770 cairo_runner
2772 .vm
2773 .segments
2774 .memory
2775 .insert(
2776 Relocatable::from((0, 0)),
2777 &MaybeRelocatable::from(Felt252::from(4613515612218425347_i64)),
2778 )
2779 .unwrap();
2780 cairo_runner
2781 .vm
2782 .segments
2783 .memory
2784 .insert(
2785 Relocatable::from((0, 1)),
2786 &MaybeRelocatable::from(Felt252::from(5)),
2787 )
2788 .unwrap();
2789 cairo_runner
2790 .vm
2791 .segments
2792 .memory
2793 .insert(
2794 Relocatable::from((0, 2)),
2795 &MaybeRelocatable::from(Felt252::from(2345108766317314046_i64)),
2796 )
2797 .unwrap();
2798 cairo_runner
2799 .vm
2800 .segments
2801 .memory
2802 .insert(Relocatable::from((1, 0)), &MaybeRelocatable::from((2, 0)))
2803 .unwrap();
2804 cairo_runner
2805 .vm
2806 .segments
2807 .memory
2808 .insert(Relocatable::from((1, 1)), &MaybeRelocatable::from((3, 0)))
2809 .unwrap();
2810 cairo_runner
2811 .vm
2812 .segments
2813 .memory
2814 .insert(
2815 Relocatable::from((1, 5)),
2816 &MaybeRelocatable::from(Felt252::from(5)),
2817 )
2818 .unwrap();
2819 cairo_runner.vm.segments.compute_effective_sizes();
2820 let rel_table = cairo_runner
2821 .vm
2822 .segments
2823 .relocate_segments()
2824 .expect("Couldn't relocate after compute effective sizes");
2825 assert_eq!(cairo_runner.relocate_memory(&rel_table), Ok(()));
2826 assert_eq!(cairo_runner.relocated_memory[0], None);
2827 assert_eq!(
2828 cairo_runner.relocated_memory[1],
2829 Some(Felt252::from(4613515612218425347_i64))
2830 );
2831 assert_eq!(cairo_runner.relocated_memory[2], Some(Felt252::from(5)));
2832 assert_eq!(
2833 cairo_runner.relocated_memory[3],
2834 Some(Felt252::from(2345108766317314046_i64))
2835 );
2836 assert_eq!(cairo_runner.relocated_memory[4], Some(Felt252::from(10)));
2837 assert_eq!(cairo_runner.relocated_memory[5], Some(Felt252::from(10)));
2838 assert_eq!(cairo_runner.relocated_memory[6], None);
2839 assert_eq!(cairo_runner.relocated_memory[7], None);
2840 assert_eq!(cairo_runner.relocated_memory[8], None);
2841 assert_eq!(cairo_runner.relocated_memory[9], Some(Felt252::from(5)));
2842 }
2843
2844 #[test]
2845 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
2846 fn initialize_run_and_relocate_output_builtin() {
2889 let program = program!(
2890 builtins = vec![BuiltinName::output],
2891 data = vec_data!(
2892 (4612671182993129469_i64),
2893 (5198983563776393216_i64),
2894 (1),
2895 (2345108766317314046_i64),
2896 (5191102247248822272_i64),
2897 (5189976364521848832_i64),
2898 (1),
2899 (1226245742482522112_i64),
2900 ((
2901 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
2902 10
2903 )),
2904 (5189976364521848832_i64),
2905 (17),
2906 (1226245742482522112_i64),
2907 ((
2908 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
2909 10
2910 )),
2911 (2345108766317314046_i64)
2912 ),
2913 main = Some(4),
2914 );
2915 let mut hint_processor = BuiltinHintProcessor::new_empty();
2916 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
2917 cairo_runner.initialize_builtins(false).unwrap();
2918 cairo_runner.initialize_segments(None);
2919 let end = cairo_runner.initialize_main_entrypoint().unwrap();
2920 cairo_runner.initialize_vm().unwrap();
2921 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
2922 cairo_runner.vm.segments.compute_effective_sizes();
2923 let rel_table = cairo_runner
2924 .vm
2925 .segments
2926 .relocate_segments()
2927 .expect("Couldn't relocate after compute effective sizes");
2928 assert_eq!(cairo_runner.relocate_memory(&rel_table), Ok(()));
2929 assert_eq!(cairo_runner.relocated_memory[0], None);
2930 assert_eq!(
2931 cairo_runner.relocated_memory[1],
2932 Some(Felt252::from(4612671182993129469_u64))
2933 );
2934 assert_eq!(
2935 cairo_runner.relocated_memory[2],
2936 Some(Felt252::from(5198983563776393216_u64))
2937 );
2938 assert_eq!(cairo_runner.relocated_memory[3], Some(Felt252::ONE));
2939 assert_eq!(
2940 cairo_runner.relocated_memory[4],
2941 Some(Felt252::from(2345108766317314046_u64))
2942 );
2943 assert_eq!(
2944 cairo_runner.relocated_memory[5],
2945 Some(Felt252::from(5191102247248822272_u64))
2946 );
2947 assert_eq!(
2948 cairo_runner.relocated_memory[6],
2949 Some(Felt252::from(5189976364521848832_u64))
2950 );
2951 assert_eq!(cairo_runner.relocated_memory[7], Some(Felt252::ONE));
2952 assert_eq!(
2953 cairo_runner.relocated_memory[8],
2954 Some(Felt252::from(1226245742482522112_u64))
2955 );
2956 assert_eq!(
2957 cairo_runner.relocated_memory[9],
2958 Some(felt_hex!(
2959 "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffffa"
2960 ))
2961 );
2962 assert_eq!(
2963 cairo_runner.relocated_memory[10],
2964 Some(Felt252::from(5189976364521848832_u64))
2965 );
2966 assert_eq!(cairo_runner.relocated_memory[11], Some(Felt252::from(17)));
2967 assert_eq!(
2968 cairo_runner.relocated_memory[12],
2969 Some(Felt252::from(1226245742482522112_u64))
2970 );
2971 assert_eq!(
2972 cairo_runner.relocated_memory[13],
2973 Some(felt_hex!(
2974 "0x800000000000010fffffffffffffffffffffffffffffffffffffffffffffff6"
2975 ))
2976 );
2977 assert_eq!(
2978 cairo_runner.relocated_memory[14],
2979 Some(Felt252::from(2345108766317314046_u64))
2980 );
2981 assert_eq!(
2982 cairo_runner.relocated_memory[15],
2983 Some(Felt252::from(27_u64))
2984 );
2985 assert_eq!(cairo_runner.relocated_memory[16], Some(Felt252::from(29)));
2986 assert_eq!(cairo_runner.relocated_memory[17], Some(Felt252::from(29)));
2987 assert_eq!(cairo_runner.relocated_memory[18], Some(Felt252::from(27)));
2988 assert_eq!(cairo_runner.relocated_memory[19], Some(Felt252::ONE));
2989 assert_eq!(cairo_runner.relocated_memory[20], Some(Felt252::from(18)));
2990 assert_eq!(cairo_runner.relocated_memory[21], Some(Felt252::from(10)));
2991 assert_eq!(cairo_runner.relocated_memory[22], Some(Felt252::from(28)));
2992 assert_eq!(cairo_runner.relocated_memory[23], Some(Felt252::from(17)));
2993 assert_eq!(cairo_runner.relocated_memory[24], Some(Felt252::from(18)));
2994 assert_eq!(cairo_runner.relocated_memory[25], Some(Felt252::from(14)));
2995 assert_eq!(cairo_runner.relocated_memory[26], Some(Felt252::from(29)));
2996 assert_eq!(cairo_runner.relocated_memory[27], Some(Felt252::ONE));
2997 assert_eq!(cairo_runner.relocated_memory[28], Some(Felt252::from(17)));
2998 }
2999
3000 #[test]
3001 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3002 fn relocate_trace_output_builtin() {
3025 let program = program!(
3026 builtins = vec![BuiltinName::output],
3027 data = vec_data!(
3028 (4612671182993129469_i64),
3029 (5198983563776393216_i64),
3030 (1),
3031 (2345108766317314046_i64),
3032 (5191102247248822272_i64),
3033 (5189976364521848832_i64),
3034 (1),
3035 (1226245742482522112_i64),
3036 ((
3037 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
3038 10
3039 )),
3040 (5189976364521848832_i64),
3041 (17),
3042 (1226245742482522112_i64),
3043 ((
3044 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
3045 10
3046 )),
3047 (2345108766317314046_i64)
3048 ),
3049 main = Some(4),
3050 );
3051 let mut hint_processor = BuiltinHintProcessor::new_empty();
3052 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
3053 cairo_runner.initialize_builtins(false).unwrap();
3054 cairo_runner.initialize_segments(None);
3055 let end = cairo_runner.initialize_main_entrypoint().unwrap();
3056 cairo_runner.initialize_vm().unwrap();
3057 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
3058 cairo_runner.vm.segments.compute_effective_sizes();
3059 let rel_table = cairo_runner
3060 .vm
3061 .segments
3062 .relocate_segments()
3063 .expect("Couldn't relocate after compute effective sizes");
3064 cairo_runner.relocate_trace(&rel_table).unwrap();
3065 let relocated_trace = cairo_runner.relocated_trace.unwrap();
3066 assert_eq!(relocated_trace.len(), 12);
3067 assert_eq!(
3068 relocated_trace[0],
3069 RelocatedTraceEntry {
3070 pc: 5,
3071 ap: 18,
3072 fp: 18
3073 }
3074 );
3075 assert_eq!(
3076 relocated_trace[1],
3077 RelocatedTraceEntry {
3078 pc: 6,
3079 ap: 19,
3080 fp: 18
3081 }
3082 );
3083 assert_eq!(
3084 relocated_trace[2],
3085 RelocatedTraceEntry {
3086 pc: 8,
3087 ap: 20,
3088 fp: 18
3089 }
3090 );
3091 assert_eq!(
3092 relocated_trace[3],
3093 RelocatedTraceEntry {
3094 pc: 1,
3095 ap: 22,
3096 fp: 22
3097 }
3098 );
3099 assert_eq!(
3100 relocated_trace[4],
3101 RelocatedTraceEntry {
3102 pc: 2,
3103 ap: 22,
3104 fp: 22
3105 }
3106 );
3107 assert_eq!(
3108 relocated_trace[5],
3109 RelocatedTraceEntry {
3110 pc: 4,
3111 ap: 23,
3112 fp: 22
3113 }
3114 );
3115 assert_eq!(
3116 relocated_trace[6],
3117 RelocatedTraceEntry {
3118 pc: 10,
3119 ap: 23,
3120 fp: 18
3121 }
3122 );
3123 assert_eq!(
3124 relocated_trace[7],
3125 RelocatedTraceEntry {
3126 pc: 12,
3127 ap: 24,
3128 fp: 18
3129 }
3130 );
3131 assert_eq!(
3132 relocated_trace[8],
3133 RelocatedTraceEntry {
3134 pc: 1,
3135 ap: 26,
3136 fp: 26
3137 }
3138 );
3139 assert_eq!(
3140 relocated_trace[9],
3141 RelocatedTraceEntry {
3142 pc: 2,
3143 ap: 26,
3144 fp: 26
3145 }
3146 );
3147 assert_eq!(
3148 relocated_trace[10],
3149 RelocatedTraceEntry {
3150 pc: 4,
3151 ap: 27,
3152 fp: 26
3153 }
3154 );
3155 assert_eq!(
3156 relocated_trace[11],
3157 RelocatedTraceEntry {
3158 pc: 14,
3159 ap: 27,
3160 fp: 18
3161 }
3162 );
3163 }
3164
3165 #[test]
3166 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3167 fn write_output_from_preset_memory() {
3168 let program = program![BuiltinName::output];
3169 let mut cairo_runner = cairo_runner!(program);
3170 cairo_runner.initialize_builtins(false).unwrap();
3171 cairo_runner.initialize_segments(None);
3172 assert_eq!(
3173 cairo_runner.vm.builtin_runners[0].name(),
3174 BuiltinName::output
3175 );
3176 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 2);
3177
3178 cairo_runner.vm.segments = segments![((2, 0), 1), ((2, 1), 2)];
3179 cairo_runner.vm.segments.segment_used_sizes = Some(vec![0, 0, 2]);
3180
3181 let mut output_buffer = String::new();
3182 cairo_runner.vm.write_output(&mut output_buffer).unwrap();
3183 assert_eq!(&output_buffer, "1\n2\n");
3184 }
3185
3186 #[test]
3187 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3188 fn get_output_from_program() {
3199 let program = program!(
3201 builtins = vec![BuiltinName::output],
3202 data = vec_data!(
3203 (4612671182993129469_i64),
3204 (5198983563776393216_i64),
3205 (1),
3206 (2345108766317314046_i64),
3207 (5191102247248822272_i64),
3208 (5189976364521848832_i64),
3209 (1),
3210 (1226245742482522112_i64),
3211 ((
3212 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
3213 10
3214 )),
3215 (5189976364521848832_i64),
3216 (17),
3217 (1226245742482522112_i64),
3218 ((
3219 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
3220 10
3221 )),
3222 (2345108766317314046_i64)
3223 ),
3224 main = Some(4),
3225 );
3226 let mut cairo_runner = cairo_runner!(program);
3227 cairo_runner.initialize_builtins(false).unwrap();
3228 cairo_runner.initialize_segments(None);
3229 let end = cairo_runner.initialize_main_entrypoint().unwrap();
3230 cairo_runner.initialize_vm().unwrap();
3231 let mut hint_processor = BuiltinHintProcessor::new_empty();
3233 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
3234
3235 let mut output_buffer = String::new();
3236 cairo_runner.vm.write_output(&mut output_buffer).unwrap();
3237 assert_eq!(&output_buffer, "1\n17\n");
3238 }
3239
3240 #[test]
3241 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3242 fn write_output_from_program_gap_relocatable_output() {
3252 let program = program!(
3254 builtins = vec![BuiltinName::output],
3255 data = vec_data!(
3256 (4612671187288162301),
3257 (5198983563776458752),
3258 (2),
3259 (2345108766317314046)
3260 ),
3261 main = Some(0),
3262 );
3263 let mut cairo_runner = cairo_runner!(program);
3264 cairo_runner.initialize_builtins(false).unwrap();
3265 cairo_runner.initialize_segments(None);
3266 let end = cairo_runner.initialize_main_entrypoint().unwrap();
3267 cairo_runner.initialize_vm().unwrap();
3268 let mut hint_processor = BuiltinHintProcessor::new_empty();
3270 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
3271
3272 let mut output_buffer = String::new();
3273 cairo_runner.vm.write_output(&mut output_buffer).unwrap();
3274 assert_eq!(&output_buffer, "<missing>\n2:0\n");
3275 }
3276
3277 #[test]
3278 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3279 fn write_output_from_preset_memory_neg_output() {
3280 let program = program![BuiltinName::output];
3281 let mut cairo_runner = cairo_runner!(program);
3282 cairo_runner.initialize_builtins(false).unwrap();
3283 cairo_runner.initialize_segments(None);
3284 assert_eq!(
3285 cairo_runner.vm.builtin_runners[0].name(),
3286 BuiltinName::output
3287 );
3288 assert_eq!(cairo_runner.vm.builtin_runners[0].base(), 2);
3289 cairo_runner.vm.segments = segments![(
3290 (2, 0),
3291 (
3292 "800000000000011000000000000000000000000000000000000000000000000",
3293 16
3294 )
3295 )];
3296 cairo_runner.vm.segments.segment_used_sizes = Some(vec![0, 0, 1]);
3297
3298 let mut output_buffer = String::new();
3299 cairo_runner.vm.write_output(&mut output_buffer).unwrap();
3300 assert_eq!(&output_buffer, "-1\n");
3301 }
3302
3303 #[test]
3305 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3306 fn get_output_unordered_builtins() {
3307 let program = program!(
3309 builtins = vec![BuiltinName::output, BuiltinName::bitwise],
3310 data = vec_data!(
3311 (4612671182993129469_i64),
3312 (5198983563776393216_i64),
3313 (1),
3314 (2345108766317314046_i64),
3315 (5191102247248822272_i64),
3316 (5189976364521848832_i64),
3317 (1),
3318 (1226245742482522112_i64),
3319 ((
3320 "3618502788666131213697322783095070105623107215331596699973092056135872020474",
3321 10
3322 )),
3323 (5189976364521848832_i64),
3324 (17),
3325 (1226245742482522112_i64),
3326 ((
3327 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
3328 10
3329 )),
3330 (2345108766317314046_i64)
3331 ),
3332 main = Some(4),
3333 );
3334
3335 let mut cairo_runner = cairo_runner!(program);
3336
3337 cairo_runner
3338 .initialize_builtins(false)
3339 .expect("Couldn't initialize builtins.");
3340
3341 cairo_runner.vm.builtin_runners.swap(0, 1);
3343 cairo_runner.program.builtins.swap(0, 1);
3344
3345 cairo_runner.initialize_segments(None);
3346
3347 let end = cairo_runner
3348 .initialize_main_entrypoint()
3349 .expect("Couldn't initialize the main entrypoint.");
3350 cairo_runner
3351 .initialize_vm()
3352 .expect("Couldn't initialize the cairo_runner.VM.");
3353
3354 let mut hint_processor = BuiltinHintProcessor::new_empty();
3355 assert_matches!(cairo_runner.run_until_pc(end, &mut hint_processor), Ok(()));
3356
3357 let mut output_buffer = String::new();
3358 cairo_runner.vm.write_output(&mut output_buffer).unwrap();
3359 assert_eq!(&output_buffer, "1\n17\n");
3360 }
3361
3362 #[test]
3363 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3364 fn insert_all_builtins_in_order() {
3365 let program = program![
3366 BuiltinName::output,
3367 BuiltinName::pedersen,
3368 BuiltinName::range_check,
3369 BuiltinName::bitwise,
3370 BuiltinName::ec_op
3371 ];
3372 let mut cairo_runner = cairo_runner!(program);
3373 cairo_runner.initialize_builtins(false).unwrap();
3374 assert_eq!(
3375 cairo_runner.vm.builtin_runners[0].name(),
3376 BuiltinName::output
3377 );
3378 assert_eq!(
3379 cairo_runner.vm.builtin_runners[1].name(),
3380 BuiltinName::pedersen
3381 );
3382 assert_eq!(
3383 cairo_runner.vm.builtin_runners[2].name(),
3384 BuiltinName::range_check
3385 );
3386 assert_eq!(
3387 cairo_runner.vm.builtin_runners[3].name(),
3388 BuiltinName::bitwise
3389 );
3390 assert_eq!(
3391 cairo_runner.vm.builtin_runners[4].name(),
3392 BuiltinName::ec_op
3393 );
3394 }
3395
3396 #[test]
3397 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3398 fn run_for_steps() {
3418 let program = program!(
3419 builtins = vec![BuiltinName::range_check],
3420 data = vec_data!(
3421 (4612671182993129469_i64),
3422 (5189976364521848832_i64),
3423 (18446744073709551615_i128),
3424 (5199546496550207487_i64),
3425 (4612389712311386111_i64),
3426 (5198983563776393216_i64),
3427 (2),
3428 (2345108766317314046_i64),
3429 (5191102247248822272_i64),
3430 (5189976364521848832_i64),
3431 (7),
3432 (1226245742482522112_i64),
3433 ((
3434 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
3435 10
3436 )),
3437 (2345108766317314046_i64)
3438 ),
3439 main = Some(8),
3440 );
3441
3442 let mut hint_processor = BuiltinHintProcessor::new_empty();
3443 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
3444 cairo_runner.initialize_builtins(false).unwrap();
3445 cairo_runner.initialize_segments(None);
3446
3447 cairo_runner.initialize_main_entrypoint().unwrap();
3448 cairo_runner.initialize_vm().unwrap();
3449
3450 assert_matches!(cairo_runner.run_for_steps(8, &mut hint_processor), Ok(()));
3452 assert_matches!(
3453 cairo_runner.run_for_steps(8, &mut hint_processor),
3454 Err(VirtualMachineError::EndOfProgram(x)) if x == 8 - 2
3455 );
3456 }
3457
3458 #[test]
3459 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3460 fn run_empty_all_cairo() {
3461 let program = program!();
3462 let mut cairo_runner = cairo_runner!(&program, LayoutName::all_cairo, false, true);
3463 assert_matches!(
3464 cairo_runner.initialize(false),
3465 Err(RunnerError::MissingMain)
3466 );
3467 }
3468
3469 #[test]
3470 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3471 fn run_empty_recursive_with_poseidon() {
3472 let program = program!();
3473 let mut cairo_runner =
3474 cairo_runner!(&program, LayoutName::recursive_with_poseidon, false, true);
3475 assert_matches!(
3476 cairo_runner.initialize(false),
3477 Err(RunnerError::MissingMain)
3478 );
3479 }
3480
3481 #[test]
3482 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3483 fn run_empty_all_cairo_stwo() {
3484 let program = program!();
3485 let mut cairo_runner = cairo_runner!(&program, LayoutName::all_cairo_stwo, false, true);
3486 assert_matches!(
3487 cairo_runner.initialize(false),
3488 Err(RunnerError::MissingMain)
3489 );
3490 }
3491
3492 #[test]
3493 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3494 fn run_until_steps() {
3514 let program = program!(
3515 builtins = vec![BuiltinName::range_check],
3516 data = vec_data!(
3517 (4612671182993129469_i64),
3518 (5189976364521848832_i64),
3519 (18446744073709551615_i128),
3520 (5199546496550207487_i64),
3521 (4612389712311386111_i64),
3522 (5198983563776393216_i64),
3523 (2),
3524 (2345108766317314046_i64),
3525 (5191102247248822272_i64),
3526 (5189976364521848832_i64),
3527 (7),
3528 (1226245742482522112_i64),
3529 ((
3530 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
3531 10
3532 )),
3533 (2345108766317314046_i64)
3534 ),
3535 main = Some(8),
3536 );
3537
3538 let mut hint_processor = BuiltinHintProcessor::new_empty();
3539 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
3540 cairo_runner.initialize_builtins(false).unwrap();
3541 cairo_runner.initialize_segments(None);
3542
3543 cairo_runner.initialize_main_entrypoint().unwrap();
3544 cairo_runner.initialize_vm().unwrap();
3545
3546 assert_matches!(cairo_runner.run_until_steps(8, &mut hint_processor), Ok(()));
3548 assert_matches!(
3549 cairo_runner.run_until_steps(10, &mut hint_processor),
3550 Ok(())
3551 );
3552 assert_matches!(
3553 cairo_runner.run_until_steps(11, &mut hint_processor),
3554 Err(VirtualMachineError::EndOfProgram(1))
3555 );
3556 }
3557
3558 #[test]
3559 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3560 fn run_until_next_power_of_2() {
3582 let program = program!(
3583 builtins = vec![BuiltinName::range_check],
3584 data = vec_data!(
3585 (4612671182993129469_i64),
3586 (5189976364521848832_i64),
3587 (18446744073709551615_i128),
3588 (5199546496550207487_i64),
3589 (4612389712311386111_i64),
3590 (5198983563776393216_i64),
3591 (2),
3592 (2345108766317314046_i64),
3593 (5191102247248822272_i64),
3594 (5189976364521848832_i64),
3595 (7),
3596 (1226245742482522112_i64),
3597 ((
3598 "3618502788666131213697322783095070105623107215331596699973092056135872020470",
3599 10
3600 )),
3601 (2345108766317314046_i64)
3602 ),
3603 main = Some(8),
3604 );
3605
3606 let mut hint_processor = BuiltinHintProcessor::new_empty();
3607 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
3608 cairo_runner.initialize_builtins(false).unwrap();
3609 cairo_runner.initialize_segments(None);
3610
3611 cairo_runner.initialize_main_entrypoint().unwrap();
3612 cairo_runner.initialize_vm().unwrap();
3613
3614 assert_matches!(cairo_runner.run_for_steps(1, &mut hint_processor), Ok(()));
3616 assert_matches!(
3617 cairo_runner.run_until_next_power_of_2(&mut hint_processor),
3618 Ok(())
3619 );
3620 assert_eq!(cairo_runner.vm.current_step, 1);
3621
3622 assert_matches!(cairo_runner.run_for_steps(1, &mut hint_processor), Ok(()));
3623 assert_matches!(
3624 cairo_runner.run_until_next_power_of_2(&mut hint_processor),
3625 Ok(())
3626 );
3627 assert_eq!(cairo_runner.vm.current_step, 2);
3628
3629 assert_matches!(cairo_runner.run_for_steps(1, &mut hint_processor), Ok(()));
3630 assert_matches!(
3631 cairo_runner.run_until_next_power_of_2(&mut hint_processor),
3632 Ok(())
3633 );
3634 assert_eq!(cairo_runner.vm.current_step, 4);
3635
3636 assert_matches!(cairo_runner.run_for_steps(1, &mut hint_processor), Ok(()));
3637 assert_matches!(
3638 cairo_runner.run_until_next_power_of_2(&mut hint_processor),
3639 Ok(())
3640 );
3641 assert_eq!(cairo_runner.vm.current_step, 8);
3642
3643 assert_matches!(cairo_runner.run_for_steps(1, &mut hint_processor), Ok(()));
3644 assert_matches!(
3645 cairo_runner.run_until_next_power_of_2(&mut hint_processor),
3646 Err(VirtualMachineError::EndOfProgram(6))
3647 );
3648 assert_eq!(cairo_runner.vm.current_step, 10);
3649 }
3650
3651 #[test]
3652 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3653 fn get_constants() {
3654 let program_constants = HashMap::from([
3655 ("MAX".to_string(), Felt252::from(300)),
3656 ("MIN".to_string(), Felt252::from(20)),
3657 ]);
3658 let program = program!(constants = program_constants.clone(),);
3659 let cairo_runner = cairo_runner!(program);
3660 assert_eq!(cairo_runner.get_constants(), &program_constants);
3661 }
3662
3663 #[test]
3664 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3665 fn get_memory_holes_missing_segment_used_sizes() {
3666 let program = program!();
3667
3668 let mut cairo_runner = cairo_runner!(program);
3669 cairo_runner.vm.segments.memory = memory![((0, 0), 9)];
3671 cairo_runner
3672 .vm
3673 .segments
3674 .memory
3675 .mark_as_accessed((0, 0).into());
3676
3677 cairo_runner.vm.builtin_runners = Vec::new();
3678 assert_eq!(
3679 cairo_runner.get_memory_holes(),
3680 Err(MemoryError::MissingSegmentUsedSizes),
3681 );
3682 }
3683
3684 #[test]
3685 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3686 fn get_memory_holes_empty() {
3687 let program = program!();
3688
3689 let mut cairo_runner = cairo_runner!(program);
3690
3691 cairo_runner.vm.builtin_runners = Vec::new();
3692 cairo_runner.vm.segments.segment_used_sizes = Some(Vec::new());
3693 assert_eq!(cairo_runner.get_memory_holes(), Ok(0));
3694 }
3695
3696 #[test]
3697 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3698 fn get_memory_holes_empty_builtins() {
3699 let program = program!();
3700
3701 let mut cairo_runner = cairo_runner!(program);
3702 cairo_runner.vm.segments.memory = memory![((0, 0), 0), ((0, 2), 0)];
3703 cairo_runner
3704 .vm
3705 .segments
3706 .memory
3707 .mark_as_accessed((0, 0).into());
3708 cairo_runner
3709 .vm
3710 .segments
3711 .memory
3712 .mark_as_accessed((0, 2).into());
3713 cairo_runner.vm.builtin_runners = Vec::new();
3714 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
3715 assert_eq!(cairo_runner.get_memory_holes(), Ok(2));
3716 }
3717
3718 #[test]
3719 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3720 fn get_memory_holes_empty_accesses() {
3721 let program = program!();
3722
3723 let mut cairo_runner = cairo_runner!(program);
3724
3725 cairo_runner.vm.builtin_runners = vec![{
3726 let mut builtin_runner: BuiltinRunner = OutputBuiltinRunner::new(true).into();
3727 builtin_runner.initialize_segments(&mut cairo_runner.vm.segments);
3728
3729 builtin_runner
3730 }];
3731 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
3732 assert_eq!(cairo_runner.get_memory_holes(), Ok(0));
3733 }
3734
3735 #[test]
3736 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3737 fn get_memory_holes() {
3738 let program = program!();
3739
3740 let mut cairo_runner = cairo_runner!(program);
3741 cairo_runner.vm.segments.memory = memory![((1, 0), 0), ((1, 2), 2)];
3742 cairo_runner
3743 .vm
3744 .segments
3745 .memory
3746 .mark_as_accessed((1, 0).into());
3747 cairo_runner
3748 .vm
3749 .segments
3750 .memory
3751 .mark_as_accessed((1, 2).into());
3752 cairo_runner.vm.builtin_runners = vec![{
3753 let mut builtin_runner: BuiltinRunner = OutputBuiltinRunner::new(true).into();
3754 builtin_runner.initialize_segments(&mut cairo_runner.vm.segments);
3755
3756 builtin_runner
3757 }];
3758 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4, 4]);
3759 assert_eq!(cairo_runner.get_memory_holes(), Ok(2));
3760 }
3761
3762 #[test]
3765 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3766 fn check_diluted_check_usage_without_pool_instance() {
3767 let program = program!();
3768
3769 let mut cairo_runner = cairo_runner!(program);
3770
3771 cairo_runner.layout.diluted_pool_instance_def = None;
3772 assert_matches!(cairo_runner.check_diluted_check_usage(), Ok(()));
3773 }
3774
3775 #[test]
3777 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3778 fn check_diluted_check_usage_without_builtin_runners() {
3779 let program = program!();
3780
3781 let mut cairo_runner = cairo_runner!(program);
3782
3783 cairo_runner.vm.current_step = 10000;
3784 cairo_runner.vm.builtin_runners = vec![];
3785 assert_matches!(cairo_runner.check_diluted_check_usage(), Ok(()));
3786 }
3787
3788 #[test]
3791 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3792 fn check_diluted_check_usage_insufficient_allocated_cells() {
3793 let program = program!();
3794
3795 let mut cairo_runner = cairo_runner!(program);
3796
3797 cairo_runner.vm.current_step = 100;
3798 cairo_runner.vm.builtin_runners = vec![];
3799 assert_matches!(
3800 cairo_runner.check_diluted_check_usage(),
3801 Err(VirtualMachineError::Memory(
3802 MemoryError::InsufficientAllocatedCells(_)
3803 ))
3804 );
3805 }
3806
3807 #[test]
3810 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3811 fn check_diluted_check_usage() {
3812 let program = program!();
3813
3814 let mut cairo_runner = cairo_runner!(program);
3815
3816 cairo_runner.vm.current_step = 8192;
3817 cairo_runner.vm.builtin_runners = vec![BitwiseBuiltinRunner::new(Some(256), true).into()];
3818 assert_matches!(cairo_runner.check_diluted_check_usage(), Ok(()));
3819 }
3820
3821 #[test]
3822 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3823 fn end_run_run_already_finished() {
3824 let program = program!();
3825
3826 let mut hint_processor = BuiltinHintProcessor::new_empty();
3827 let mut cairo_runner = cairo_runner!(program);
3828
3829 cairo_runner.run_ended = true;
3830 assert_matches!(
3831 cairo_runner.end_run(true, false, &mut hint_processor, false),
3832 Err(VirtualMachineError::RunnerError(
3833 RunnerError::EndRunCalledTwice
3834 ))
3835 );
3836 }
3837
3838 #[test]
3839 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3840 fn end_run() {
3841 let program = program!();
3842
3843 let mut hint_processor = BuiltinHintProcessor::new_empty();
3844 let mut cairo_runner = cairo_runner!(program);
3845
3846 assert_matches!(
3847 cairo_runner.end_run(true, false, &mut hint_processor, false),
3848 Ok(())
3849 );
3850
3851 cairo_runner.run_ended = false;
3852 cairo_runner.relocated_memory.clear();
3853 assert_matches!(
3854 cairo_runner.end_run(true, true, &mut hint_processor, false),
3855 Ok(())
3856 );
3857 assert!(!cairo_runner.run_ended);
3858 }
3859
3860 #[test]
3861 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3862 fn end_run_proof_mode_insufficient_allocated_cells() {
3863 let program = Program::from_bytes(
3864 include_bytes!("../../../../cairo_programs/proof_programs/fibonacci.json"),
3865 Some("main"),
3866 )
3867 .unwrap();
3868 let proof_mode = true;
3869 let mut hint_processor = BuiltinHintProcessor::new_empty();
3870 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, proof_mode, true);
3871
3872 let end = cairo_runner.initialize(false).unwrap();
3873 cairo_runner
3874 .run_until_pc(end, &mut hint_processor)
3875 .expect("Call to `CairoRunner::run_until_pc()` failed.");
3876 assert_matches!(
3877 cairo_runner.end_run(false, false, &mut hint_processor, proof_mode),
3878 Ok(())
3879 );
3880 }
3881
3882 #[test]
3883 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3884 fn get_builtin_segments_info_empty() {
3885 let program = program!();
3886
3887 let cairo_runner = cairo_runner!(program);
3888
3889 assert_eq!(cairo_runner.get_builtin_segments_info(), Ok(Vec::new()),);
3890 }
3891
3892 #[test]
3893 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3894 fn get_builtin_segments_info_base_not_finished() {
3895 let program = program!();
3896
3897 let mut cairo_runner = cairo_runner!(program);
3898
3899 cairo_runner.vm.builtin_runners =
3900 vec![BuiltinRunner::Output(OutputBuiltinRunner::new(true))];
3901 assert_eq!(
3902 cairo_runner.get_builtin_segments_info(),
3903 Err(RunnerError::NoStopPointer(Box::new(BuiltinName::output))),
3904 );
3905 }
3906
3907 #[test]
3908 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3909 fn get_builtin_segments_info_non_proof_mode() {
3910 let program_data =
3911 include_bytes!("../../../../cairo_programs/proof_programs/assert_nn.json");
3912 let cairo_run_config = CairoRunConfig {
3913 entrypoint: "main",
3914 trace_enabled: false,
3915 relocate_mem: false,
3916 layout: LayoutName::small,
3917 proof_mode: false,
3918 fill_holes: false,
3919 secure_run: Some(true),
3920 ..Default::default()
3921 };
3922 let mut hint_executor = BuiltinHintProcessor::new_empty();
3923 let runner = cairo_run(program_data, &cairo_run_config, &mut hint_executor).unwrap();
3924 assert_eq!(runner.get_builtin_segments_info(), Ok(vec![(2, 6)]));
3927 }
3928
3929 #[test]
3930 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3931 fn get_builtin_segments_info_proof_mode() {
3932 let program_data =
3933 include_bytes!("../../../../cairo_programs/proof_programs/assert_nn.json");
3934 let cairo_run_config = CairoRunConfig {
3935 entrypoint: "main",
3936 trace_enabled: false,
3937 relocate_mem: false,
3938 layout: LayoutName::small,
3939 proof_mode: true,
3940 fill_holes: true,
3941 secure_run: Some(true),
3942 ..Default::default()
3943 };
3944 let mut hint_executor = BuiltinHintProcessor::new_empty();
3945 let runner = cairo_run(program_data, &cairo_run_config, &mut hint_executor).unwrap();
3946 assert_eq!(runner.get_builtin_segments_info(), Ok(vec![(4, 6)]));
3950 }
3951
3952 #[test]
3953 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3954 fn get_execution_resources_trace_not_enabled() {
3955 let program = program!();
3956
3957 let mut cairo_runner = cairo_runner!(program);
3958
3959 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
3960 cairo_runner.vm.current_step = 10;
3961 assert_eq!(
3962 cairo_runner.get_execution_resources(),
3963 Ok(ExecutionResources {
3964 n_steps: 10,
3965 n_memory_holes: 0,
3966 builtin_instance_counter: BTreeMap::new(),
3967 }),
3968 );
3969 }
3970
3971 #[test]
3972 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3973 fn get_execution_resources_run_program() {
3974 let program_data = include_bytes!("../../../../cairo_programs/fibonacci.json");
3975 let cairo_run_config = CairoRunConfig {
3976 entrypoint: "main",
3977 trace_enabled: true,
3978 relocate_mem: false,
3979 layout: LayoutName::all_cairo,
3980 proof_mode: false,
3981 fill_holes: false,
3982 secure_run: Some(false),
3983 ..Default::default()
3984 };
3985 let mut hint_executor = BuiltinHintProcessor::new_empty();
3986 let runner = cairo_run(program_data, &cairo_run_config, &mut hint_executor).unwrap();
3987 assert_eq!(runner.get_execution_resources().unwrap().n_steps, 80);
3988 }
3989
3990 #[test]
3991 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
3992 fn get_execution_resources_run_program_no_trace() {
3993 let program_data = include_bytes!("../../../../cairo_programs/fibonacci.json");
3994 let cairo_run_config = CairoRunConfig {
3995 entrypoint: "main",
3996 trace_enabled: false,
3997 relocate_mem: false,
3998 layout: LayoutName::all_cairo,
3999 proof_mode: false,
4000 fill_holes: false,
4001 secure_run: Some(false),
4002 ..Default::default()
4003 };
4004 let mut hint_executor = BuiltinHintProcessor::new_empty();
4005 let runner = cairo_run(program_data, &cairo_run_config, &mut hint_executor).unwrap();
4006 assert_eq!(runner.get_execution_resources().unwrap().n_steps, 80);
4007 }
4008
4009 #[test]
4010 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4011 fn get_execution_resources_empty_builtins() {
4012 let program = program!();
4013
4014 let mut cairo_runner = cairo_runner!(program);
4015
4016 cairo_runner.vm.current_step = 10;
4017 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
4018 assert_eq!(
4019 cairo_runner.get_execution_resources(),
4020 Ok(ExecutionResources {
4021 n_steps: 10,
4022 n_memory_holes: 0,
4023 builtin_instance_counter: BTreeMap::new(),
4024 }),
4025 );
4026 }
4027
4028 #[test]
4029 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4030 fn get_execution_resources() {
4031 let program = program!();
4032
4033 let mut cairo_runner = cairo_runner!(program);
4034
4035 cairo_runner.vm.current_step = 10;
4036 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
4037 cairo_runner.vm.builtin_runners = vec![{
4038 let mut builtin = OutputBuiltinRunner::new(true);
4039 builtin.initialize_segments(&mut cairo_runner.vm.segments);
4040
4041 BuiltinRunner::Output(builtin)
4042 }];
4043 assert_eq!(
4044 cairo_runner.get_execution_resources(),
4045 Ok(ExecutionResources {
4046 n_steps: 10,
4047 n_memory_holes: 0,
4048 builtin_instance_counter: BTreeMap::from([(BuiltinName::output, 4)]),
4049 }),
4050 );
4051 }
4052
4053 #[test]
4054 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4055 fn finalize_segments_run_not_ended() {
4056 let program = program!();
4057 let mut cairo_runner = cairo_runner!(program);
4058 assert_eq!(
4059 cairo_runner.finalize_segments(),
4060 Err(RunnerError::FinalizeNoEndRun)
4061 )
4062 }
4063
4064 #[test]
4065 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4066 fn finalize_segments_run_ended_empty_no_prog_base() {
4067 let program = program!();
4068 let mut cairo_runner = cairo_runner!(program);
4069 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4070 cairo_runner.run_ended = true;
4071 assert_eq!(
4072 cairo_runner.finalize_segments(),
4073 Err(RunnerError::NoProgBase)
4074 )
4075 }
4076
4077 #[test]
4078 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4079 fn finalize_segments_run_ended_empty_no_exec_base() {
4080 let program = program!();
4081 let mut cairo_runner = cairo_runner!(program);
4082 cairo_runner.runner_mode = RunnerMode::ProofModeCanonical;
4083 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4084 cairo_runner.run_ended = true;
4085 assert_eq!(
4086 cairo_runner.finalize_segments(),
4087 Err(RunnerError::NoExecBase)
4088 )
4089 }
4090
4091 #[test]
4092 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4093 fn finalize_segments_run_ended_empty_noproof_mode() {
4094 let program = program!();
4095 let mut cairo_runner = cairo_runner!(program);
4096 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4097 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4098 cairo_runner.run_ended = true;
4099 assert_eq!(
4100 cairo_runner.finalize_segments(),
4101 Err(RunnerError::FinalizeSegmentsNoProofMode)
4102 )
4103 }
4104
4105 #[test]
4106 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4107 fn finalize_segments_run_ended_emptyproof_mode() {
4108 let program = program!();
4109 let mut cairo_runner = cairo_runner!(program, LayoutName::plain, true);
4110 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4111 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4112 cairo_runner.run_ended = true;
4113 assert_eq!(cairo_runner.finalize_segments(), Ok(()));
4114 assert!(cairo_runner.segments_finalized);
4115 assert!(cairo_runner.execution_public_memory.unwrap().is_empty())
4116 }
4117
4118 #[test]
4119 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4120 fn finalize_segments_run_ended_not_emptyproof_mode_empty_execution_public_memory() {
4121 let mut program = program!();
4122 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4123 vec_data![(1), (2), (3), (4), (5), (6), (7), (8)];
4124 let mut cairo_runner = cairo_runner!(program, LayoutName::plain, true);
4126 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4127 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4128 cairo_runner.run_ended = true;
4129 assert_eq!(cairo_runner.finalize_segments(), Ok(()));
4130 assert!(cairo_runner.segments_finalized);
4131 assert_eq!(
4133 cairo_runner.vm.segments.segment_sizes.get(&0),
4134 Some(&8_usize)
4135 );
4136 assert_eq!(
4137 cairo_runner.vm.segments.public_memory_offsets.get(&0),
4138 Some(&vec![
4139 (0_usize, 0_usize),
4140 (1_usize, 0_usize),
4141 (2_usize, 0_usize),
4142 (3_usize, 0_usize),
4143 (4_usize, 0_usize),
4144 (5_usize, 0_usize),
4145 (6_usize, 0_usize),
4146 (7_usize, 0_usize)
4147 ])
4148 );
4149 assert_eq!(cairo_runner.vm.segments.segment_sizes.get(&1), None);
4151 assert_eq!(
4152 cairo_runner.vm.segments.public_memory_offsets.get(&1),
4153 Some(&vec![])
4154 );
4155 }
4156
4157 #[test]
4158 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4159 fn finalize_segments_run_ended_not_emptyproof_mode_with_execution_public_memory() {
4160 let mut program = program!();
4161 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4162 vec_data![(1), (2), (3), (4)];
4163 let mut cairo_runner = cairo_runner!(program, LayoutName::plain, true);
4165 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4166 cairo_runner.execution_base = Some(Relocatable::from((1, 1)));
4167 cairo_runner.execution_public_memory = Some(vec![1_usize, 3_usize, 5_usize, 4_usize]);
4168 cairo_runner.run_ended = true;
4169 assert_eq!(cairo_runner.finalize_segments(), Ok(()));
4170 assert!(cairo_runner.segments_finalized);
4171 assert_eq!(
4173 cairo_runner.vm.segments.segment_sizes.get(&0),
4174 Some(&4_usize)
4175 );
4176 assert_eq!(
4177 cairo_runner.vm.segments.public_memory_offsets.get(&0),
4178 Some(&vec![
4179 (0_usize, 0_usize),
4180 (1_usize, 0_usize),
4181 (2_usize, 0_usize),
4182 (3_usize, 0_usize)
4183 ])
4184 );
4185 assert_eq!(cairo_runner.vm.segments.segment_sizes.get(&1), None);
4187 assert_eq!(
4188 cairo_runner.vm.segments.public_memory_offsets.get(&1),
4189 Some(&vec![
4190 (2_usize, 0_usize),
4191 (4_usize, 0_usize),
4192 (6_usize, 0_usize),
4193 (5_usize, 0_usize)
4194 ])
4195 );
4196 }
4197
4198 #[test]
4201 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4202 fn get_perm_range_check_limits_no_builtins() {
4203 let program = program!();
4204 let mut hint_processor = BuiltinHintProcessor::new(HashMap::new(), RunResources::default());
4205
4206 let mut cairo_runner = cairo_runner!(program);
4207
4208 cairo_runner.vm.segments.memory.data = vec![
4209 vec![
4210 MemoryCell::new(Felt252::from(0x8000_8023_8012u64).into()),
4211 MemoryCell::new(Felt252::from(0xBFFF_8000_0620u64).into()),
4212 MemoryCell::new(Felt252::from(0x8FFF_8000_0750u64).into()),
4213 ],
4214 vec![MemoryCell::new((0isize, 0usize).into()); 128 * 1024],
4215 ];
4216
4217 cairo_runner.run_for_steps(1, &mut hint_processor).unwrap();
4218
4219 assert_matches!(
4220 cairo_runner.get_perm_range_check_limits(),
4221 Some((32768, 32803))
4222 );
4223 }
4224
4225 #[test]
4228 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4229 fn get_perm_range_check_limits() {
4230 let program = program!();
4231
4232 let mut cairo_runner = cairo_runner!(program);
4233
4234 cairo_runner.vm.segments.memory.data = vec![vec![MemoryCell::new(mayberelocatable!(
4235 0x80FF_8000_0530u64
4236 ))]];
4237 cairo_runner.vm.builtin_runners =
4238 vec![RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(12), true).into()];
4239
4240 assert_matches!(cairo_runner.get_perm_range_check_limits(), Some((0, 33023)));
4241 }
4242
4243 #[test]
4246 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4247 fn check_range_check_usage_perm_range_limits_none() {
4248 let program = program!();
4249
4250 let mut cairo_runner = cairo_runner!(program);
4251 cairo_runner.vm.trace = Some(vec![]);
4252
4253 assert_matches!(cairo_runner.check_range_check_usage(), Ok(()));
4254 }
4255
4256 #[test]
4259 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4260 fn check_range_check_usage_without_builtins() {
4261 let program = program!();
4262
4263 let mut cairo_runner = cairo_runner!(program, LayoutName::plain);
4264 cairo_runner.vm.builtin_runners = vec![];
4265 cairo_runner.vm.current_step = 10000;
4266 cairo_runner.vm.segments.memory.data = vec![vec![MemoryCell::new(mayberelocatable!(
4267 0x80FF_8000_0530u64
4268 ))]];
4269 cairo_runner.vm.trace = Some(vec![TraceEntry {
4270 pc: (0, 0).into(),
4271 ap: 0,
4272 fp: 0,
4273 }]);
4274
4275 assert_matches!(cairo_runner.check_range_check_usage(), Ok(()));
4276 }
4277
4278 #[test]
4281 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4282 fn check_range_check_usage_insufficient_allocated_cells() {
4283 let program = program!();
4284
4285 let mut cairo_runner = cairo_runner!(program);
4286 cairo_runner.vm.builtin_runners =
4287 vec![RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true).into()];
4288 cairo_runner.vm.segments.memory.data = vec![vec![MemoryCell::new(mayberelocatable!(
4289 0x80FF_8000_0530u64
4290 ))]];
4291 cairo_runner.vm.trace = Some(vec![TraceEntry {
4292 pc: (0, 0).into(),
4293 ap: 0,
4294 fp: 0,
4295 }]);
4296 cairo_runner.vm.segments.compute_effective_sizes();
4297
4298 assert_matches!(
4299 cairo_runner.check_range_check_usage(),
4300 Err(VirtualMachineError::Memory(
4301 MemoryError::InsufficientAllocatedCells(_)
4302 ))
4303 );
4304 }
4305
4306 #[test]
4307 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4308 fn get_initial_fp_is_none_without_initialization() {
4309 let program = program!();
4310
4311 let runner = cairo_runner!(program);
4312
4313 assert_eq!(None, runner.get_initial_fp());
4314 }
4315
4316 #[test]
4317 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4318 fn get_initial_fp_can_be_obtained() {
4319 let program = program![BuiltinName::output];
4320 let mut cairo_runner = cairo_runner!(program);
4321 for _ in 0..2 {
4322 cairo_runner.vm.segments.add();
4323 }
4324 cairo_runner.program_base = Some(relocatable!(0, 0));
4325 cairo_runner.execution_base = Some(relocatable!(1, 0));
4326 let return_fp = Felt252::from(9_i32).into();
4327 cairo_runner
4328 .initialize_function_entrypoint(0, vec![], return_fp)
4329 .unwrap();
4330 assert_eq!(Some(relocatable!(1, 2)), cairo_runner.get_initial_fp());
4331 }
4332
4333 #[test]
4334 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4335 fn check_used_cells_valid_case() {
4336 let program = program![BuiltinName::range_check, BuiltinName::output];
4337 let mut cairo_runner = cairo_runner!(program);
4338 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
4339 cairo_runner.vm.trace = Some(vec![]);
4340 cairo_runner.layout.diluted_pool_instance_def = None;
4341
4342 assert_matches!(cairo_runner.check_used_cells(), Ok(()));
4343 }
4344
4345 #[test]
4346 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4347 fn check_used_cells_get_used_cells_and_allocated_size_error() {
4348 let program = program!();
4349
4350 let mut cairo_runner = cairo_runner!(program);
4351 cairo_runner.vm.builtin_runners =
4352 vec![RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true).into()];
4353 cairo_runner.vm.segments.memory.data = vec![vec![MemoryCell::new(mayberelocatable!(
4354 0x80FF_8000_0530u64
4355 ))]];
4356 cairo_runner.vm.trace = Some(vec![TraceEntry {
4357 pc: (0, 0).into(),
4358 ap: 0,
4359 fp: 0,
4360 }]);
4361 cairo_runner.vm.segments.compute_effective_sizes();
4362 assert_matches!(
4363 cairo_runner.check_used_cells(),
4364 Err(VirtualMachineError::Memory(
4365 MemoryError::InsufficientAllocatedCells(_)
4366 ))
4367 );
4368 }
4369
4370 #[test]
4371 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4372 fn check_used_cells_check_memory_usage_error() {
4373 let program = program!();
4374
4375 let mut cairo_runner = cairo_runner!(program);
4376 cairo_runner
4377 .vm
4378 .segments
4379 .memory
4380 .mark_as_accessed((1, 0).into());
4381 cairo_runner
4382 .vm
4383 .segments
4384 .memory
4385 .mark_as_accessed((1, 3).into());
4386 cairo_runner.vm.builtin_runners = vec![{
4387 let mut builtin_runner: BuiltinRunner = OutputBuiltinRunner::new(true).into();
4388 builtin_runner.initialize_segments(&mut cairo_runner.vm.segments);
4389
4390 builtin_runner
4391 }];
4392 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4, 12]);
4393 cairo_runner.vm.trace = Some(vec![]);
4394
4395 assert_matches!(
4396 cairo_runner.check_used_cells(),
4397 Err(VirtualMachineError::Memory(
4398 MemoryError::InsufficientAllocatedCells(_)
4399 ))
4400 );
4401 }
4402
4403 #[test]
4404 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4405 fn check_used_cells_check_diluted_check_usage_error() {
4406 let program = program![BuiltinName::range_check, BuiltinName::output];
4407 let mut cairo_runner = cairo_runner!(program);
4408 cairo_runner.vm.segments.segment_used_sizes = Some(vec![4]);
4409 cairo_runner.vm.trace = Some(vec![]);
4410
4411 assert_matches!(
4412 cairo_runner.check_used_cells(),
4413 Err(VirtualMachineError::Memory(
4414 MemoryError::InsufficientAllocatedCells(_)
4415 ))
4416 );
4417 }
4418
4419 #[test]
4420 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4421 fn initialize_all_program_builtins() {
4422 let mut program = program!();
4423
4424 program.builtins = vec![
4426 BuiltinName::pedersen,
4427 BuiltinName::range_check,
4428 BuiltinName::output,
4429 BuiltinName::ecdsa,
4430 BuiltinName::bitwise,
4431 BuiltinName::ec_op,
4432 BuiltinName::keccak,
4433 BuiltinName::poseidon,
4434 ];
4435
4436 let mut cairo_runner = cairo_runner!(program);
4437
4438 cairo_runner
4439 .initialize_program_builtins()
4440 .expect("Builtin initialization failed.");
4441
4442 let given_output = cairo_runner.vm.get_builtin_runners();
4443
4444 assert_eq!(given_output[0].name(), BuiltinName::pedersen);
4445 assert_eq!(given_output[1].name(), BuiltinName::range_check);
4446 assert_eq!(given_output[2].name(), BuiltinName::output);
4447 assert_eq!(given_output[3].name(), BuiltinName::ecdsa);
4448 assert_eq!(given_output[4].name(), BuiltinName::bitwise);
4449 assert_eq!(given_output[5].name(), BuiltinName::ec_op);
4450 assert_eq!(given_output[6].name(), BuiltinName::keccak);
4451 assert_eq!(given_output[7].name(), BuiltinName::poseidon);
4452 }
4453
4454 #[test]
4455 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4456 fn initialize_function_runner_without_builtins() {
4457 let program = program!();
4458
4459 let mut cairo_runner = cairo_runner!(program);
4460
4461 cairo_runner
4462 .initialize_function_runner()
4463 .expect("initialize_function_runner failed.");
4464
4465 assert_eq!(
4466 cairo_runner.program_base,
4467 Some(Relocatable {
4468 segment_index: 0,
4469 offset: 0,
4470 })
4471 );
4472 assert_eq!(
4473 cairo_runner.execution_base,
4474 Some(Relocatable {
4475 segment_index: 1,
4476 offset: 0,
4477 })
4478 );
4479 assert_eq!(cairo_runner.vm.segments.num_segments(), 2);
4480 }
4481
4482 #[test]
4483 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4484 fn initialize_function_runner_with_segment_arena_builtin() {
4485 let program = program!();
4486
4487 let mut cairo_runner = cairo_runner!(program);
4488
4489 cairo_runner
4490 .initialize_function_runner_cairo_1(&[BuiltinName::segment_arena])
4491 .expect("initialize_function_runner failed.");
4492
4493 let builtin_runners = cairo_runner.vm.get_builtin_runners();
4494
4495 assert_eq!(builtin_runners[0].name(), BuiltinName::segment_arena);
4496
4497 assert_eq!(
4498 cairo_runner.program_base,
4499 Some(Relocatable {
4500 segment_index: 0,
4501 offset: 0,
4502 })
4503 );
4504 assert_eq!(
4505 cairo_runner.execution_base,
4506 Some(Relocatable {
4507 segment_index: 1,
4508 offset: 0,
4509 })
4510 );
4511 assert_eq!(cairo_runner.vm.segments.num_segments(), 4);
4513 }
4514
4515 #[test]
4516 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4517 fn initialize_segments_incorrect_layout_plain_one_builtin() {
4518 let program = program![BuiltinName::output];
4519 let mut cairo_runner = cairo_runner!(program, LayoutName::plain);
4520 assert_eq!(
4521 cairo_runner.initialize_builtins(false),
4522 Err(RunnerError::NoBuiltinForInstance(Box::new((
4523 HashSet::from([BuiltinName::output]),
4524 LayoutName::plain
4525 ))))
4526 );
4527 }
4528
4529 #[test]
4530 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4531 fn initialize_segments_incorrect_layout_plain_two_builtins() {
4532 let program = program![BuiltinName::output, BuiltinName::pedersen];
4533 let mut cairo_runner = cairo_runner!(program, LayoutName::plain);
4534 assert_eq!(
4535 cairo_runner.initialize_builtins(false),
4536 Err(RunnerError::NoBuiltinForInstance(Box::new((
4537 HashSet::from([BuiltinName::output, BuiltinName::pedersen]),
4538 LayoutName::plain
4539 ))))
4540 );
4541 }
4542
4543 #[test]
4544 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4545 fn initialize_segments_incorrect_layout_small_two_builtins() {
4546 let program = program![BuiltinName::output, BuiltinName::bitwise];
4547 let mut cairo_runner = cairo_runner!(program, LayoutName::small);
4548 assert_eq!(
4549 cairo_runner.initialize_builtins(false),
4550 Err(RunnerError::NoBuiltinForInstance(Box::new((
4551 HashSet::from([BuiltinName::bitwise]),
4552 LayoutName::small,
4553 ))))
4554 );
4555 }
4556 #[test]
4557 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4558 fn initialize_main_entrypoint_proof_mode_empty_program() {
4559 let program = program!(start = Some(0), end = Some(0), main = Some(8),);
4560 let mut runner = cairo_runner!(program);
4561 runner.runner_mode = RunnerMode::ProofModeCanonical;
4562 runner.initialize_segments(None);
4563 assert_eq!(runner.execution_base, Some(Relocatable::from((1, 0))));
4564 assert_eq!(runner.program_base, Some(Relocatable::from((0, 0))));
4565 assert_eq!(
4566 runner.initialize_main_entrypoint(),
4567 Ok(Relocatable::from((0, 0)))
4568 );
4569 assert_eq!(runner.initial_ap, Some(Relocatable::from((1, 2))));
4570 assert_eq!(runner.initial_fp, runner.initial_ap);
4571 assert_eq!(runner.execution_public_memory, Some(vec![0, 1]));
4572 }
4573
4574 #[test]
4575 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4576 fn initialize_main_entrypoint_proof_mode_empty_program_two_builtins() {
4577 let program = program!(
4578 start = Some(0),
4579 end = Some(0),
4580 main = Some(8),
4581 builtins = vec![BuiltinName::output, BuiltinName::ec_op],
4582 );
4583 let mut runner = cairo_runner!(program);
4584 runner.runner_mode = RunnerMode::ProofModeCanonical;
4585 runner.initialize_builtins(false).unwrap();
4586 runner.initialize_segments(None);
4587 assert_eq!(runner.execution_base, Some(Relocatable::from((1, 0))));
4588 assert_eq!(runner.program_base, Some(Relocatable::from((0, 0))));
4589 assert_eq!(
4590 runner.initialize_main_entrypoint(),
4591 Ok(Relocatable::from((0, 0)))
4592 );
4593 assert_eq!(runner.initial_ap, Some(Relocatable::from((1, 2))));
4594 assert_eq!(runner.initial_fp, runner.initial_ap);
4595 assert_eq!(runner.execution_public_memory, Some(vec![0, 1, 2, 3]));
4596 }
4597
4598 #[test]
4599 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4600 fn can_get_the_runner_program_builtins() {
4601 let program = program!(
4602 start = Some(0),
4603 end = Some(0),
4604 main = Some(8),
4605 builtins = vec![BuiltinName::output, BuiltinName::ec_op],
4606 );
4607 let runner = cairo_runner!(program);
4608
4609 assert_eq!(&program.builtins, runner.get_program_builtins());
4610 }
4611
4612 #[test]
4613 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4614 fn set_entrypoint_main_default() {
4615 let program = program!(
4616 identifiers = [(
4617 "__main__.main",
4618 Identifier {
4619 pc: Some(0),
4620 type_: None,
4621 value: None,
4622 full_name: None,
4623 members: None,
4624 cairo_type: None,
4625 size: None,
4626 destination: None,
4627 },
4628 )]
4629 .into_iter()
4630 .map(|(k, v)| (k.to_string(), v))
4631 .collect(),
4632 );
4633 let mut cairo_runner = cairo_runner!(program);
4634
4635 cairo_runner
4636 .set_entrypoint(None)
4637 .expect("Call to `set_entrypoint()` failed.");
4638 assert_eq!(cairo_runner.entrypoint, Some(0));
4639 }
4640
4641 #[test]
4642 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4643 fn set_entrypoint_main() {
4644 let program = program!(
4645 identifiers = [
4646 (
4647 "__main__.main",
4648 Identifier {
4649 pc: Some(0),
4650 type_: None,
4651 value: None,
4652 full_name: None,
4653 members: None,
4654 cairo_type: None,
4655 size: None,
4656 destination: None,
4657 },
4658 ),
4659 (
4660 "__main__.alternate_main",
4661 Identifier {
4662 pc: Some(1),
4663 type_: None,
4664 value: None,
4665 full_name: None,
4666 members: None,
4667 cairo_type: None,
4668 size: None,
4669 destination: None,
4670 },
4671 ),
4672 ]
4673 .into_iter()
4674 .map(|(k, v)| (k.to_string(), v))
4675 .collect(),
4676 );
4677 let mut cairo_runner = cairo_runner!(program);
4678
4679 cairo_runner
4680 .set_entrypoint(Some("alternate_main"))
4681 .expect("Call to `set_entrypoint()` failed.");
4682 assert_eq!(cairo_runner.entrypoint, Some(1));
4683 }
4684
4685 #[test]
4687 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4688 fn set_entrypoint_main_non_existent() {
4689 let program = program!(
4690 identifiers = [(
4691 "__main__.main",
4692 Identifier {
4693 pc: Some(0),
4694 type_: None,
4695 value: None,
4696 full_name: None,
4697 members: None,
4698 cairo_type: None,
4699 size: None,
4700 destination: None,
4701 },
4702 )]
4703 .into_iter()
4704 .map(|(k, v)| (k.to_string(), v))
4705 .collect(),
4706 );
4707 let mut cairo_runner = cairo_runner!(program);
4708
4709 cairo_runner
4710 .set_entrypoint(Some("nonexistent_main"))
4711 .expect_err("Call to `set_entrypoint()` succeeded (should've failed).");
4712 assert_eq!(cairo_runner.entrypoint, None);
4713 }
4714
4715 #[test]
4716 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4717 fn read_return_values_test() {
4718 let mut program = program!();
4719 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4720 vec_data![(1), (2), (3), (4), (5), (6), (7), (8)];
4721 let mut cairo_runner = cairo_runner!(program, LayoutName::plain, true);
4723 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4724 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4725 cairo_runner.run_ended = true;
4726 cairo_runner.segments_finalized = false;
4727 assert_eq!(cairo_runner.read_return_values(false), Ok(()));
4730 assert_eq!(
4731 cairo_runner
4732 .execution_public_memory
4733 .expect("missing execution public memory"),
4734 Vec::<usize>::new()
4735 );
4736 }
4737
4738 #[test]
4739 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4740 fn read_return_values_test_with_run_not_ended() {
4741 let mut program = program!();
4742 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4743 vec_data![(1), (2), (3), (4), (5), (6), (7), (8)];
4744 let mut cairo_runner = cairo_runner!(program, LayoutName::plain, true);
4746 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4747 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4748 cairo_runner.run_ended = false;
4749 assert_eq!(
4750 cairo_runner.read_return_values(false),
4751 Err(RunnerError::ReadReturnValuesNoEndRun)
4752 );
4753 }
4754
4755 #[test]
4756 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4757 fn read_return_values_test_with_segments_finalized() {
4758 let mut program = program!();
4759 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4760 vec_data![(1), (2), (3), (4), (5), (6), (7), (8)];
4761 let mut cairo_runner = cairo_runner!(program, LayoutName::plain, true);
4763 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4764 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4765 cairo_runner.run_ended = true;
4766 cairo_runner.segments_finalized = true;
4767 assert_eq!(
4768 cairo_runner.read_return_values(false),
4769 Err(RunnerError::FailedAddingReturnValues)
4770 );
4771 }
4772
4773 #[test]
4774 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4775 fn read_return_values_updates_builtin_stop_ptr_one_builtin_empty() {
4776 let mut program = program![BuiltinName::output];
4777 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4778 vec_data![(1), (2), (3), (4), (5), (6), (7), (8)];
4779 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, true);
4781 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4782 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4783 cairo_runner.run_ended = true;
4784 cairo_runner.segments_finalized = false;
4785 let output_builtin = OutputBuiltinRunner::new(true);
4786 cairo_runner.vm.builtin_runners.push(output_builtin.into());
4787 cairo_runner.vm.segments.memory.data = vec![
4788 vec![],
4789 vec![MemoryCell::new(MaybeRelocatable::from((0, 0)))],
4790 vec![],
4791 ];
4792 cairo_runner.vm.set_ap(1);
4793 cairo_runner.vm.segments.segment_used_sizes = Some(vec![0, 1, 0]);
4794 assert_eq!(cairo_runner.read_return_values(false), Ok(()));
4796 let output_builtin = match &cairo_runner.vm.builtin_runners[0] {
4797 BuiltinRunner::Output(runner) => runner,
4798 _ => unreachable!(),
4799 };
4800 assert_eq!(output_builtin.stop_ptr, Some(0))
4801 }
4802
4803 #[test]
4804 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4805 fn read_return_values_updates_builtin_stop_ptr_one_builtin_one_element() {
4806 let mut program = program![BuiltinName::output];
4807 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4808 vec_data![(1), (2), (3), (4), (5), (6), (7), (8)];
4809 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, true);
4811 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4812 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4813 cairo_runner.run_ended = true;
4814 cairo_runner.segments_finalized = false;
4815 let output_builtin = OutputBuiltinRunner::new(true);
4816 cairo_runner.vm.builtin_runners.push(output_builtin.into());
4817 cairo_runner.vm.segments.memory.data = vec![
4818 vec![MemoryCell::new(MaybeRelocatable::from((0, 0)))],
4819 vec![MemoryCell::new(MaybeRelocatable::from((0, 1)))],
4820 vec![],
4821 ];
4822 cairo_runner.vm.set_ap(1);
4823 cairo_runner.vm.segments.segment_used_sizes = Some(vec![1, 1, 0]);
4824 assert_eq!(cairo_runner.read_return_values(false), Ok(()));
4826 let output_builtin = match &cairo_runner.vm.builtin_runners[0] {
4827 BuiltinRunner::Output(runner) => runner,
4828 _ => unreachable!(),
4829 };
4830 assert_eq!(output_builtin.stop_ptr, Some(1))
4831 }
4832
4833 #[test]
4834 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4835 fn read_return_values_updates_builtin_stop_ptr_two_builtins() {
4836 let mut program = program![BuiltinName::output, BuiltinName::bitwise];
4837 Arc::get_mut(&mut program.shared_program_data).unwrap().data =
4838 vec_data![(1), (2), (3), (4), (5), (6), (7), (8)];
4839 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, true);
4841 cairo_runner.program_base = Some(Relocatable::from((0, 0)));
4842 cairo_runner.execution_base = Some(Relocatable::from((1, 0)));
4843 cairo_runner.run_ended = true;
4844 cairo_runner.segments_finalized = false;
4845 let output_builtin = OutputBuiltinRunner::new(true);
4846 let bitwise_builtin = BitwiseBuiltinRunner::new(Some(256), true);
4847 cairo_runner.vm.builtin_runners.push(output_builtin.into());
4848 cairo_runner.vm.builtin_runners.push(bitwise_builtin.into());
4849 cairo_runner.initialize_segments(None);
4850 cairo_runner.vm.segments.memory.data = vec![
4851 vec![MemoryCell::new(MaybeRelocatable::from((0, 0)))],
4852 vec![
4853 MemoryCell::new(MaybeRelocatable::from((2, 0))),
4854 MemoryCell::new(MaybeRelocatable::from((3, 5))),
4855 ],
4856 vec![],
4857 ];
4858 cairo_runner.vm.set_ap(2);
4859 cairo_runner.vm.segments.segment_used_sizes = Some(vec![0, 2, 0, 5]);
4861 assert_eq!(cairo_runner.read_return_values(false), Ok(()));
4863 let output_builtin = match &cairo_runner.vm.builtin_runners[0] {
4864 BuiltinRunner::Output(runner) => runner,
4865 _ => unreachable!(),
4866 };
4867 assert_eq!(output_builtin.stop_ptr, Some(0));
4868 assert_eq!(cairo_runner.read_return_values(false), Ok(()));
4869 let bitwise_builtin = match &cairo_runner.vm.builtin_runners[1] {
4870 BuiltinRunner::Bitwise(runner) => runner,
4871 _ => unreachable!(),
4872 };
4873 assert_eq!(bitwise_builtin.stop_ptr, Some(5));
4874 }
4875
4876 #[test]
4877 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4878 fn run_from_entrypoint_custom_program_test() {
4879 let program = Program::from_bytes(
4880 include_bytes!("../../../../cairo_programs/example_program.json"),
4881 None,
4882 )
4883 .unwrap();
4884 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
4885 let mut hint_processor = BuiltinHintProcessor::new_empty();
4886
4887 let main_entrypoint = program
4889 .shared_program_data
4890 .identifiers
4891 .get("__main__.main")
4892 .unwrap()
4893 .pc
4894 .unwrap();
4895
4896 cairo_runner.initialize_builtins(false).unwrap();
4897 cairo_runner.initialize_segments(None);
4898 assert_matches!(
4899 cairo_runner.run_from_entrypoint(
4900 main_entrypoint,
4901 &[
4902 &mayberelocatable!(2).into(),
4903 &MaybeRelocatable::from((2, 0)).into()
4904 ], true,
4906 None,
4907 &mut hint_processor,
4908 ),
4909 Ok(())
4910 );
4911
4912 let mut new_cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
4913 let mut hint_processor = BuiltinHintProcessor::new_empty();
4914
4915 new_cairo_runner.initialize_builtins(false).unwrap();
4916 new_cairo_runner.initialize_segments(None);
4917
4918 let fib_entrypoint = program
4919 .shared_program_data
4920 .identifiers
4921 .get("__main__.evaluate_fib")
4922 .unwrap()
4923 .pc
4924 .unwrap();
4925
4926 assert_matches!(
4927 new_cairo_runner.run_from_entrypoint(
4928 fib_entrypoint,
4929 &[
4930 &mayberelocatable!(2).into(),
4931 &MaybeRelocatable::from((2, 0)).into()
4932 ],
4933 true,
4934 None,
4935 &mut hint_processor,
4936 ),
4937 Ok(())
4938 );
4939 }
4940
4941 #[test]
4942 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4943 fn run_from_entrypoint_bitwise_test_check_memory_holes() {
4944 let program = Program::from_bytes(
4945 include_bytes!("../../../../cairo_programs/bitwise_builtin_test.json"),
4946 None,
4947 )
4948 .unwrap();
4949 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
4950 let mut hint_processor = BuiltinHintProcessor::new_empty();
4951
4952 let main_entrypoint = program
4954 .shared_program_data
4955 .identifiers
4956 .get("__main__.main")
4957 .unwrap()
4958 .pc
4959 .unwrap();
4960
4961 cairo_runner.initialize_function_runner().unwrap();
4962
4963 assert!(cairo_runner
4964 .run_from_entrypoint(
4965 main_entrypoint,
4966 &[
4967 &MaybeRelocatable::from((2, 0)).into() ],
4969 true,
4970 None,
4971 &mut hint_processor,
4972 )
4973 .is_ok());
4974
4975 assert!(cairo_runner.get_memory_holes().unwrap().is_zero());
4977 }
4978
4979 #[test]
4980 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4981 fn cairo_arg_from_single() {
4982 let expected = CairoArg::Single(MaybeRelocatable::from((0, 0)));
4983 let value = MaybeRelocatable::from((0, 0));
4984 assert_eq!(expected, value.into())
4985 }
4986
4987 #[test]
4988 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4989 fn cairo_arg_from_array() {
4990 let expected = CairoArg::Array(vec![MaybeRelocatable::from((0, 0))]);
4991 let value = vec![MaybeRelocatable::from((0, 0))];
4992 assert_eq!(expected, value.into())
4993 }
4994
4995 fn setup_execution_resources() -> (ExecutionResources, ExecutionResources) {
4996 let mut builtin_instance_counter: BTreeMap<BuiltinName, usize> = BTreeMap::new();
4997 builtin_instance_counter.insert(BuiltinName::output, 8);
4998
4999 let execution_resources_1 = ExecutionResources {
5000 n_steps: 100,
5001 n_memory_holes: 5,
5002 builtin_instance_counter: builtin_instance_counter.clone(),
5003 };
5004
5005 builtin_instance_counter.insert(BuiltinName::range_check, 8);
5007
5008 let execution_resources_2 = ExecutionResources {
5009 n_steps: 100,
5010 n_memory_holes: 5,
5011 builtin_instance_counter,
5012 };
5013
5014 (execution_resources_1, execution_resources_2)
5015 }
5016
5017 #[test]
5018 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5019 fn execution_resources_add() {
5020 let (execution_resources_1, execution_resources_2) = setup_execution_resources();
5021 let combined_resources = &execution_resources_1 + &execution_resources_2;
5022
5023 assert_eq!(combined_resources.n_steps, 200);
5024 assert_eq!(combined_resources.n_memory_holes, 10);
5025 assert_eq!(
5026 combined_resources
5027 .builtin_instance_counter
5028 .get(&BuiltinName::output)
5029 .unwrap(),
5030 &16
5031 );
5032 assert!(combined_resources
5033 .builtin_instance_counter
5034 .contains_key(&BuiltinName::range_check));
5035 }
5036
5037 #[test]
5038 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5039 fn execution_resources_sub() {
5040 let (execution_resources_1, execution_resources_2) = setup_execution_resources();
5041
5042 let combined_resources = &execution_resources_1 - &execution_resources_2;
5043
5044 assert_eq!(combined_resources.n_steps, 0);
5045 assert_eq!(combined_resources.n_memory_holes, 0);
5046 assert_eq!(
5047 combined_resources
5048 .builtin_instance_counter
5049 .get(&BuiltinName::output)
5050 .unwrap(),
5051 &0
5052 );
5053 assert!(combined_resources
5054 .builtin_instance_counter
5055 .contains_key(&BuiltinName::range_check));
5056 }
5057
5058 #[test]
5059 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5060 fn run_from_entrypoint_substitute_error_message_test() {
5061 let program = Program::from_bytes(
5062 include_bytes!("../../../../cairo_programs/bad_programs/error_msg_function.json"),
5063 None,
5064 )
5065 .unwrap();
5066 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, false, true);
5067 let mut hint_processor = BuiltinHintProcessor::new_empty();
5068
5069 let main_entrypoint = program
5071 .shared_program_data
5072 .identifiers
5073 .get("__main__.main")
5074 .unwrap()
5075 .pc
5076 .unwrap();
5077
5078 cairo_runner.initialize_builtins(false).unwrap();
5079 cairo_runner.initialize_segments(None);
5080
5081 let result =
5082 cairo_runner.run_from_entrypoint(main_entrypoint, &[], true, None, &mut hint_processor);
5083 match result {
5084 Err(CairoRunError::VmException(exception)) => {
5085 assert_eq!(
5086 exception.error_attr_value,
5087 Some(String::from("Error message: Test error\n"))
5088 )
5089 }
5090 Err(_) => panic!("Wrong error returned, expected VmException"),
5091 Ok(_) => panic!("Expected run to fail"),
5092 }
5093 }
5094
5095 #[test]
5096 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5097 fn get_builtins_final_stack_range_check_builtin() {
5098 let program = Program::from_bytes(
5099 include_bytes!("../../../../cairo_programs/assert_le_felt_hint.json"),
5100 Some("main"),
5101 )
5102 .unwrap();
5103 let mut runner = cairo_runner!(program);
5104 let end = runner.initialize(false).unwrap();
5105 runner
5106 .run_until_pc(end, &mut BuiltinHintProcessor::new_empty())
5107 .unwrap();
5108 runner.vm.segments.compute_effective_sizes();
5109 let initial_pointer = runner.vm.get_ap();
5110 let expected_pointer = (runner.vm.get_ap() - 1).unwrap();
5111 assert_eq!(
5112 runner.get_builtins_final_stack(initial_pointer),
5113 Ok(expected_pointer)
5114 );
5115 }
5116
5117 #[test]
5118 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5119 fn get_builtins_final_stack_4_builtins() {
5120 let program = Program::from_bytes(
5121 include_bytes!("../../../../cairo_programs/integration.json"),
5122 Some("main"),
5123 )
5124 .unwrap();
5125 let mut runner = cairo_runner!(program);
5126 let end = runner.initialize(false).unwrap();
5127 runner
5128 .run_until_pc(end, &mut BuiltinHintProcessor::new_empty())
5129 .unwrap();
5130 runner.vm.segments.compute_effective_sizes();
5131 let initial_pointer = runner.vm.get_ap();
5132 let expected_pointer = (runner.vm.get_ap() - 4).unwrap();
5133 assert_eq!(
5134 runner.get_builtins_final_stack(initial_pointer),
5135 Ok(expected_pointer)
5136 );
5137 }
5138
5139 #[test]
5140 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5141 fn get_builtins_final_stack_no_builtins() {
5142 let program = Program::from_bytes(
5143 include_bytes!("../../../../cairo_programs/fibonacci.json"),
5144 Some("main"),
5145 )
5146 .unwrap();
5147 let mut runner = cairo_runner!(program);
5148 let end = runner.initialize(false).unwrap();
5149 runner
5150 .run_until_pc(end, &mut BuiltinHintProcessor::new_empty())
5151 .unwrap();
5152 runner.vm.segments.compute_effective_sizes();
5153 let initial_pointer = runner.vm.get_ap();
5154 let expected_pointer = runner.vm.get_ap();
5155 assert_eq!(
5156 runner.get_builtins_final_stack(initial_pointer),
5157 Ok(expected_pointer)
5158 );
5159 }
5160
5161 #[test]
5162 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5163 fn filter_unused_builtins_test() {
5164 let program = Program::from_bytes(
5165 include_bytes!("../../../../cairo_programs/integration.json"),
5166 Some("main"),
5167 )
5168 .unwrap();
5169 let mut runner = cairo_runner!(program);
5170 let end = runner.initialize(false).unwrap();
5171 runner
5172 .run_until_pc(end, &mut BuiltinHintProcessor::new_empty())
5173 .unwrap();
5174 runner.vm.segments.compute_effective_sizes();
5175 let mut exec = runner.get_execution_resources().unwrap();
5176 exec.builtin_instance_counter.insert(BuiltinName::keccak, 0);
5177 assert_eq!(exec.builtin_instance_counter.len(), 5);
5178 let rsc = exec.filter_unused_builtins();
5179 assert_eq!(rsc.builtin_instance_counter.len(), 4);
5180 }
5181
5182 #[test]
5183 fn execution_resources_mul() {
5184 let execution_resources_1 = ExecutionResources {
5185 n_steps: 800,
5186 n_memory_holes: 0,
5187 builtin_instance_counter: BTreeMap::from([
5188 (BuiltinName::pedersen, 7),
5189 (BuiltinName::range_check, 16),
5190 ]),
5191 };
5192
5193 assert_eq!(
5194 &execution_resources_1 * 2,
5195 ExecutionResources {
5196 n_steps: 1600,
5197 n_memory_holes: 0,
5198 builtin_instance_counter: BTreeMap::from([
5199 (BuiltinName::pedersen, 14),
5200 (BuiltinName::range_check, 32)
5201 ])
5202 }
5203 );
5204
5205 let execution_resources_2 = ExecutionResources {
5206 n_steps: 545,
5207 n_memory_holes: 0,
5208 builtin_instance_counter: BTreeMap::from([(BuiltinName::range_check, 17)]),
5209 };
5210
5211 assert_eq!(
5212 &execution_resources_2 * 8,
5213 ExecutionResources {
5214 n_steps: 4360,
5215 n_memory_holes: 0,
5216 builtin_instance_counter: BTreeMap::from([(BuiltinName::range_check, 136)])
5217 }
5218 );
5219
5220 let execution_resources_3 = ExecutionResources {
5221 n_steps: 42,
5222 n_memory_holes: 0,
5223 builtin_instance_counter: BTreeMap::new(),
5224 };
5225
5226 assert_eq!(
5227 &execution_resources_3 * 18,
5228 ExecutionResources {
5229 n_steps: 756,
5230 n_memory_holes: 0,
5231 builtin_instance_counter: BTreeMap::new()
5232 }
5233 );
5234 }
5235
5236 #[test]
5237 fn test_get_program() {
5238 let program = program!(
5239 builtins = vec![BuiltinName::output],
5240 data = vec_data!((4), (6)),
5241 );
5242 let runner = cairo_runner!(program);
5243
5244 assert_eq!(runner.get_program().data_len(), 2)
5245 }
5246
5247 #[test]
5248 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5249 fn test_run_resources_none() {
5250 let program = Program::from_bytes(
5251 include_bytes!("../../../../cairo_programs/fibonacci.json"),
5252 Some("main"),
5253 )
5254 .unwrap();
5255 let mut runner = cairo_runner!(program);
5256 let end = runner.initialize(false).unwrap();
5257
5258 assert_matches!(
5260 runner.run_until_pc(end, &mut BuiltinHintProcessor::new_empty(),),
5261 Ok(())
5262 )
5263 }
5264
5265 #[test]
5266 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5267 fn test_run_resources_ok() {
5268 let program = Program::from_bytes(
5269 include_bytes!("../../../../cairo_programs/fibonacci.json"),
5270 Some("main"),
5271 )
5272 .unwrap();
5273 let mut runner = cairo_runner!(program);
5274 let end = runner.initialize(false).unwrap();
5275 let mut hint_processor = BuiltinHintProcessor::new(HashMap::new(), RunResources::new(81));
5276 assert_matches!(runner.run_until_pc(end, &mut hint_processor), Ok(()));
5278
5279 assert_eq!(hint_processor.run_resources().get_n_steps(), Some(1));
5280 }
5281
5282 #[test]
5283 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5284 fn test_run_resources_ok_2() {
5285 let program = Program::from_bytes(
5286 include_bytes!("../../../../cairo_programs/fibonacci.json"),
5287 Some("main"),
5288 )
5289 .unwrap();
5290 let mut runner = cairo_runner!(program);
5291 let end = runner.initialize(false).unwrap();
5292 let mut hint_processor = BuiltinHintProcessor::new(HashMap::new(), RunResources::new(80));
5293 assert_matches!(runner.run_until_pc(end, &mut hint_processor), Ok(()));
5295
5296 assert_eq!(hint_processor.run_resources(), &RunResources::new(0));
5297 }
5298
5299 #[test]
5300 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
5301 fn test_run_resources_error() {
5302 let program = Program::from_bytes(
5303 include_bytes!("../../../../cairo_programs/fibonacci.json"),
5304 Some("main"),
5305 )
5306 .unwrap();
5307 let mut runner = cairo_runner!(program);
5308 let end = runner.initialize(false).unwrap();
5309 let mut hint_processor = BuiltinHintProcessor::new(HashMap::new(), RunResources::new(9));
5310 assert_matches!(
5312 runner.run_until_pc(end, &mut hint_processor,),
5313 Err(VirtualMachineError::UnfinishedExecution)
5314 );
5315 assert_eq!(hint_processor.run_resources(), &RunResources::new(0));
5316 }
5317
5318 #[test]
5319 fn get_cairo_pie_no_program_base() {
5320 let runner = cairo_runner!(Default::default());
5321 assert_eq!(runner.get_cairo_pie(), Err(RunnerError::NoProgBase))
5322 }
5323
5324 #[test]
5325 fn get_cairo_pie_no_execution_base() {
5326 let mut runner = cairo_runner!(Default::default());
5327 runner.program_base = Some(Relocatable::from((0, 0)));
5328 assert_eq!(runner.get_cairo_pie(), Err(RunnerError::NoExecBase))
5329 }
5330
5331 #[test]
5332 fn get_cairo_pie_no_segment_sizes() {
5333 let mut runner = cairo_runner!(Default::default());
5334 runner.program_base = Some(Relocatable::from((0, 0)));
5335 runner.execution_base = Some(Relocatable::from((1, 0)));
5336 runner.vm.add_memory_segment();
5337 runner.vm.add_memory_segment();
5338 runner
5340 .vm
5341 .insert_value::<Relocatable>((1, 0).into(), (2, 0).into())
5342 .unwrap();
5343 runner
5345 .vm
5346 .insert_value::<Relocatable>((1, 1).into(), (3, 0).into())
5347 .unwrap();
5348 assert_eq!(
5349 runner.get_cairo_pie(),
5350 Err(RunnerError::UnexpectedRetFpSegmentSize)
5351 );
5352 }
5353
5354 #[test]
5355 fn get_cairo_pie_ret_pc_segment_size_not_zero() {
5356 let mut runner = cairo_runner!(Default::default());
5357 runner.program_base = Some(Relocatable::from((0, 0)));
5358 runner.execution_base = Some(Relocatable::from((1, 0)));
5359 runner.vm.add_memory_segment();
5360 runner.vm.add_memory_segment();
5361 runner
5363 .vm
5364 .insert_value::<Relocatable>((1, 0).into(), (2, 0).into())
5365 .unwrap();
5366 runner
5368 .vm
5369 .insert_value::<Relocatable>((1, 1).into(), (3, 0).into())
5370 .unwrap();
5371 runner.vm.segments.segment_sizes = HashMap::from([(0, 0), (1, 2), (2, 0), (3, 1)]);
5373 assert_eq!(
5374 runner.get_cairo_pie(),
5375 Err(RunnerError::UnexpectedRetPcSegmentSize)
5376 );
5377 }
5378
5379 #[test]
5380 fn get_cairo_pie_program_base_offset_not_zero() {
5381 let mut runner = cairo_runner!(Default::default());
5382 runner.program_base = Some(Relocatable::from((0, 1)));
5383 runner.execution_base = Some(Relocatable::from((1, 0)));
5384 runner.vm.add_memory_segment();
5385 runner.vm.add_memory_segment();
5386 runner
5388 .vm
5389 .insert_value::<Relocatable>((1, 0).into(), (2, 0).into())
5390 .unwrap();
5391 runner
5393 .vm
5394 .insert_value::<Relocatable>((1, 1).into(), (3, 0).into())
5395 .unwrap();
5396 runner.vm.segments.segment_sizes = HashMap::from([(0, 0), (1, 2), (2, 0), (3, 0)]);
5398 assert_eq!(
5399 runner.get_cairo_pie(),
5400 Err(RunnerError::ProgramBaseOffsetNotZero)
5401 );
5402 }
5403
5404 #[test]
5405 fn get_cairo_pie_execution_base_offset_not_zero() {
5406 let mut runner = cairo_runner!(Default::default());
5407 runner.program_base = Some(Relocatable::from((0, 0)));
5408 runner.execution_base = Some(Relocatable::from((1, 1)));
5409 runner.vm.add_memory_segment();
5410 runner.vm.add_memory_segment();
5411 runner
5413 .vm
5414 .insert_value::<Relocatable>((1, 1).into(), (2, 0).into())
5415 .unwrap();
5416 runner
5418 .vm
5419 .insert_value::<Relocatable>((1, 2).into(), (3, 0).into())
5420 .unwrap();
5421 runner.vm.segments.segment_sizes = HashMap::from([(0, 0), (1, 2), (2, 0), (3, 0)]);
5423 assert_eq!(
5424 runner.get_cairo_pie(),
5425 Err(RunnerError::ExecBaseOffsetNotZero)
5426 );
5427 }
5428
5429 #[test]
5430 fn get_cairo_pie_ret_fp_offset_not_zero() {
5431 let mut runner = cairo_runner!(Default::default());
5432 runner.program_base = Some(Relocatable::from((0, 0)));
5433 runner.execution_base = Some(Relocatable::from((1, 0)));
5434 runner.vm.add_memory_segment();
5435 runner.vm.add_memory_segment();
5436 runner
5438 .vm
5439 .insert_value::<Relocatable>((1, 0).into(), (2, 1).into())
5440 .unwrap();
5441 runner
5443 .vm
5444 .insert_value::<Relocatable>((1, 1).into(), (3, 0).into())
5445 .unwrap();
5446 runner.vm.segments.segment_sizes = HashMap::from([(0, 0), (1, 2), (2, 0), (3, 0)]);
5448 assert_eq!(runner.get_cairo_pie(), Err(RunnerError::RetFpOffsetNotZero));
5449 }
5450
5451 #[test]
5452 fn get_cairo_pie_ret_pc_offset_not_zero() {
5453 let mut runner = cairo_runner!(Default::default());
5454 runner.program_base = Some(Relocatable::from((0, 0)));
5455 runner.execution_base = Some(Relocatable::from((1, 0)));
5456 runner.vm.add_memory_segment();
5457 runner.vm.add_memory_segment();
5458 runner
5460 .vm
5461 .insert_value::<Relocatable>((1, 0).into(), (2, 0).into())
5462 .unwrap();
5463 runner
5465 .vm
5466 .insert_value::<Relocatable>((1, 1).into(), (3, 1).into())
5467 .unwrap();
5468 runner.vm.segments.segment_sizes = HashMap::from([(0, 0), (1, 2), (2, 0), (3, 0)]);
5470 assert_eq!(runner.get_cairo_pie(), Err(RunnerError::RetPcOffsetNotZero));
5471 }
5472
5473 #[test]
5474 fn get_cairo_pie_ok() {
5475 let mut runner = cairo_runner!(Default::default());
5476 runner.program_base = Some(Relocatable::from((0, 0)));
5477 runner.execution_base = Some(Relocatable::from((1, 0)));
5478 runner.vm.add_memory_segment();
5479 runner.vm.add_memory_segment();
5480 runner
5482 .vm
5483 .insert_value::<Relocatable>((1, 0).into(), (2, 0).into())
5484 .unwrap();
5485 runner
5487 .vm
5488 .insert_value::<Relocatable>((1, 1).into(), (3, 0).into())
5489 .unwrap();
5490 runner.vm.segments.segment_sizes = HashMap::from([(0, 0), (1, 2), (2, 0), (3, 0)]);
5492 }
5493
5494 #[test]
5495 fn get_air_private_input() {
5496 let program_content =
5497 include_bytes!("../../../../cairo_programs/proof_programs/common_signature.json");
5498 let runner = crate::cairo_run::cairo_run(
5499 program_content,
5500 &CairoRunConfig {
5501 proof_mode: true,
5502 fill_holes: true,
5503 layout: LayoutName::all_cairo,
5504 ..Default::default()
5505 },
5506 &mut BuiltinHintProcessor::new_empty(),
5507 )
5508 .unwrap();
5509 let air_private_input = runner.get_air_private_input();
5510 assert!(air_private_input.0[&BuiltinName::pedersen].is_empty());
5511 assert!(air_private_input.0[&BuiltinName::range_check].is_empty());
5512 assert!(air_private_input.0[&BuiltinName::bitwise].is_empty());
5513 assert!(air_private_input.0[&BuiltinName::ec_op].is_empty());
5514 assert!(air_private_input.0[&BuiltinName::keccak].is_empty());
5515 assert!(air_private_input.0[&BuiltinName::poseidon].is_empty());
5516 assert_eq!(
5517 air_private_input.0[&BuiltinName::ecdsa],
5518 vec![PrivateInput::Signature(PrivateInputSignature {
5519 index: 0,
5520 pubkey: felt_hex!(
5521 "0x3d60886c2353d93ec2862e91e23036cd9999a534481166e5a616a983070434d"
5522 ),
5523 msg: felt_hex!("0xa9e"),
5524 signature_input: SignatureInput {
5525 r: felt_hex!(
5526 "0x6d2e2e00dfceffd6a375db04764da249a5a1534c7584738dfe01cb3944a33ee"
5527 ),
5528 w: felt_hex!(
5529 "0x396362a34ff391372fca63f691e27753ce8f0c2271a614cbd240e1dc1596b28"
5530 )
5531 }
5532 })]
5533 );
5534 }
5535
5536 #[test]
5537 fn test_disable_trace_padding_without_proof_mode() {
5538 let program = program!();
5539 let result = CairoRunner::new(&program, LayoutName::plain, None, false, true, true);
5541 match result {
5542 Err(RunnerError::DisableTracePaddingWithoutProofMode) => { }
5543 _ => panic!("Expected DisableTracePaddingWithoutProofMode error"),
5544 }
5545 }
5546
5547 #[test]
5548 fn test_get_relocatable_trace() {
5549 let program_content =
5550 include_bytes!("../../../../cairo_programs/proof_programs/common_signature.json");
5551 let runner = crate::cairo_run::cairo_run(
5552 program_content,
5553 &CairoRunConfig {
5554 trace_enabled: true,
5555 layout: LayoutName::all_cairo,
5556 ..Default::default()
5557 },
5558 &mut BuiltinHintProcessor::new_empty(),
5559 )
5560 .unwrap();
5561 let relocatable_trace = runner.get_relocatable_trace().unwrap();
5562 let expected_trace = vec![
5563 TraceEntry {
5564 pc: (0, 15).into(),
5565 ap: 3,
5566 fp: 3,
5567 },
5568 TraceEntry {
5569 pc: (0, 16).into(),
5570 ap: 4,
5571 fp: 3,
5572 },
5573 TraceEntry {
5574 pc: (0, 18).into(),
5575 ap: 5,
5576 fp: 3,
5577 },
5578 TraceEntry {
5579 pc: (0, 20).into(),
5580 ap: 6,
5581 fp: 3,
5582 },
5583 TraceEntry {
5584 pc: (0, 22).into(),
5585 ap: 7,
5586 fp: 3,
5587 },
5588 TraceEntry {
5589 pc: (0, 24).into(),
5590 ap: 8,
5591 fp: 3,
5592 },
5593 TraceEntry {
5594 pc: (0, 10).into(),
5595 ap: 10,
5596 fp: 10,
5597 },
5598 TraceEntry {
5599 pc: (0, 11).into(),
5600 ap: 10,
5601 fp: 10,
5602 },
5603 TraceEntry {
5604 pc: (0, 12).into(),
5605 ap: 10,
5606 fp: 10,
5607 },
5608 TraceEntry {
5609 pc: (0, 14).into(),
5610 ap: 11,
5611 fp: 10,
5612 },
5613 TraceEntry {
5614 pc: (0, 26).into(),
5615 ap: 11,
5616 fp: 3,
5617 },
5618 ];
5619 assert_eq!(relocatable_trace, expected_trace);
5620 }
5621
5622 #[test]
5623 fn test_get_relocatable_memory() {
5624 let program_content =
5625 include_bytes!("../../../../cairo_programs/proof_programs/common_signature.json");
5626 let runner = crate::cairo_run::cairo_run(
5627 program_content,
5628 &CairoRunConfig {
5629 layout: LayoutName::all_cairo,
5630 ..Default::default()
5631 },
5632 &mut BuiltinHintProcessor::new_empty(),
5633 )
5634 .unwrap();
5635 let relocatable_memory = runner.get_relocatable_memory();
5636
5637 let expected_in_memory_0_3 = MaybeRelocatable::Int(13.into());
5638 let expected_in_memory_1_0 = MaybeRelocatable::RelocatableValue(Relocatable {
5639 segment_index: 2,
5640 offset: 0,
5641 });
5642
5643 assert_eq!(relocatable_memory[0][3], Some(expected_in_memory_0_3));
5644 assert_eq!(relocatable_memory[1][0], Some(expected_in_memory_1_0));
5645 }
5646
5647 #[test]
5648 fn test_get_builtin_segments() {
5649 let program_content =
5650 include_bytes!("../../../../cairo_programs/proof_programs/bitwise_builtin_test.json");
5651 let runner = crate::cairo_run::cairo_run(
5652 program_content,
5653 &CairoRunConfig {
5654 layout: LayoutName::all_cairo,
5655 ..Default::default()
5656 },
5657 &mut BuiltinHintProcessor::new_empty(),
5658 )
5659 .unwrap();
5660 let builtin_segments = runner.get_builtin_segments();
5661
5662 assert_eq!(builtin_segments[&2], BuiltinName::bitwise);
5663 }
5664
5665 #[test]
5666 fn end_run_fill_builtins() {
5667 let program = Program::from_bytes(
5668 include_bytes!("../../../../cairo_programs/proof_programs/keccak_uint256.json"),
5669 Some("main"),
5670 )
5671 .unwrap();
5672
5673 let mut hint_processor = BuiltinHintProcessor::new_empty();
5674 let proof_mode = true;
5675 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, proof_mode, true);
5676
5677 let end = cairo_runner.initialize(false).unwrap();
5678 cairo_runner
5679 .run_until_pc(end, &mut hint_processor)
5680 .expect("Call to `CairoRunner::run_until_pc()` failed.");
5681
5682 assert!(cairo_runner.vm.segments.memory.data[6].len() as u32 % CELLS_PER_BITWISE != 0);
5684 assert!(cairo_runner.vm.segments.memory.data[8].len() as u32 % CELLS_PER_KECCAK != 0);
5685
5686 assert_matches!(
5687 cairo_runner.end_run(false, false, &mut hint_processor, proof_mode),
5688 Ok(())
5689 );
5690
5691 assert!(cairo_runner.vm.segments.memory.data[6].len() as u32 % CELLS_PER_BITWISE == 0);
5693 assert!(cairo_runner.vm.segments.memory.data[8].len() as u32 % CELLS_PER_KECCAK == 0);
5694 assert!(cairo_runner.vm.segments.memory.data[6].last().is_some());
5695 assert!(cairo_runner.vm.segments.memory.data[8].last().is_some());
5696
5697 let builtin_segments = cairo_runner.get_builtin_segments();
5698 assert!(builtin_segments.get(&6) == Some(&BuiltinName::bitwise));
5699 assert!(builtin_segments.get(&8) == Some(&BuiltinName::keccak));
5700 }
5701
5702 #[test]
5703 fn end_run_fill_middle_holes() {
5704 let program = Program::from_bytes(
5705 include_bytes!("../../../../cairo_programs/proof_programs/poseidon_builtin_hole.json"),
5706 Some("main"),
5707 )
5708 .unwrap();
5709
5710 let mut hint_processor = BuiltinHintProcessor::new_empty();
5711 let mut cairo_runner = cairo_runner!(program, LayoutName::all_cairo, true, true);
5712
5713 let end = cairo_runner.initialize(false).unwrap();
5714 cairo_runner
5715 .run_until_pc(end, &mut hint_processor)
5716 .expect("Call to `CairoRunner::run_until_pc()` failed.");
5717
5718 assert!(cairo_runner.vm.segments.memory.data[9][4].is_none());
5721 assert_matches!(
5722 cairo_runner.end_run(false, false, &mut hint_processor, true),
5723 Ok(())
5724 );
5725
5726 assert!(!cairo_runner.vm.segments.memory.data[9][4].is_none());
5728
5729 let builtin_segments = cairo_runner.get_builtin_segments();
5730 assert!(builtin_segments.get(&9) == Some(&BuiltinName::poseidon));
5731 }
5732
5733 #[test]
5734 #[cfg(feature = "test_utils")]
5735 fn test_simulated_builtins() {
5736 let program_bytes = include_bytes!("../../../../cairo_programs/simulated_builtins.json");
5737 let program =
5738 Program::from_bytes(program_bytes, Some("main")).expect("failed to read program");
5739
5740 let program: &Program = &program;
5741 let mut cairo_runner =
5742 CairoRunner::new(program, LayoutName::plain, None, false, false, false)
5743 .expect("failed to create runner");
5744
5745 let end = cairo_runner
5747 .initialize(true)
5748 .expect("failed to initialize builtins");
5749
5750 let mut builtin_runner = BuiltinRunner::EcOp(EcOpBuiltinRunner::new(None, true));
5752 builtin_runner.initialize_segments(&mut cairo_runner.vm.segments);
5753 cairo_runner
5754 .vm
5755 .simulated_builtin_runners
5756 .push(builtin_runner);
5757
5758 let hint_processor: &mut dyn HintProcessor = &mut BuiltinHintProcessor::new_empty();
5759 cairo_runner
5760 .run_until_pc(end, hint_processor)
5761 .expect("failed to run program");
5762 }
5763}