1use std::{borrow::Cow, collections::HashMap, fmt};
2
3use crate::types::errors::math_errors::MathError;
4use crate::vm::runners::cairo_pie::CairoPieMemory;
5use crate::Felt252;
6use crate::{
7 types::relocatable::{MaybeRelocatable, Relocatable},
8 utils::from_relocatable_to_indexes,
9 vm::errors::memory_errors::MemoryError,
10};
11use bitvec::prelude as bv;
12use core::cmp::Ordering;
13use num_traits::ToPrimitive;
14
15pub struct ValidationRule(
16 #[allow(clippy::type_complexity)]
17 pub Box<dyn Fn(&Memory, Relocatable) -> Result<Vec<Relocatable>, MemoryError>>,
18);
19
20#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Debug)]
41#[repr(align(32))]
42pub(crate) struct MemoryCell([u64; 4]);
43
44impl MemoryCell {
45 pub const NONE_MASK: u64 = 1 << 63;
46 pub const ACCESS_MASK: u64 = 1 << 62;
47 pub const RELOCATABLE_MASK: u64 = 1 << 61;
48 pub const NONE: Self = Self([Self::NONE_MASK, 0, 0, 0]);
49
50 pub fn new(value: MaybeRelocatable) -> Self {
51 value.into()
52 }
53
54 pub fn is_none(&self) -> bool {
55 self.0[0] & Self::NONE_MASK == Self::NONE_MASK
56 }
57
58 pub fn is_some(&self) -> bool {
59 !self.is_none()
60 }
61
62 pub fn mark_accessed(&mut self) {
63 self.0[0] |= Self::ACCESS_MASK;
64 }
65
66 pub fn is_accessed(&self) -> bool {
67 self.0[0] & Self::ACCESS_MASK == Self::ACCESS_MASK
68 }
69
70 pub fn get_value(&self) -> Option<MaybeRelocatable> {
71 self.is_some().then(|| (*self).into())
72 }
73}
74
75impl From<MaybeRelocatable> for MemoryCell {
76 fn from(value: MaybeRelocatable) -> Self {
77 match value {
78 MaybeRelocatable::Int(x) => Self(x.to_raw()),
79 MaybeRelocatable::RelocatableValue(x) => Self([
80 Self::RELOCATABLE_MASK,
81 0,
82 usize::from_ne_bytes(x.segment_index.to_ne_bytes()) as u64,
84 x.offset as u64,
85 ]),
86 }
87 }
88}
89
90impl From<MemoryCell> for MaybeRelocatable {
91 fn from(cell: MemoryCell) -> Self {
92 debug_assert!(cell.is_some());
93 let flags = cell.0[0];
94 match flags & MemoryCell::RELOCATABLE_MASK {
95 MemoryCell::RELOCATABLE_MASK => Self::from((
96 isize::from_ne_bytes((cell.0[2] as usize).to_ne_bytes()),
98 cell.0[3] as usize,
99 )),
100 _ => {
101 let mut value = cell.0;
102 value[0] &= 0x0fffffffffffffff;
104 Self::Int(Felt252::from_raw(value))
105 }
106 }
107 }
108}
109
110pub struct AddressSet(Vec<bv::BitVec>);
111
112impl AddressSet {
113 pub(crate) fn new() -> Self {
114 Self(Vec::new())
115 }
116
117 pub(crate) fn contains(&self, addr: &Relocatable) -> bool {
118 let segment = addr.segment_index;
119 if segment.is_negative() {
120 return false;
121 }
122
123 self.0
124 .get(segment as usize)
125 .and_then(|segment| segment.get(addr.offset))
126 .map(|bit| *bit)
127 .unwrap_or(false)
128 }
129
130 pub(crate) fn extend(&mut self, addresses: &[Relocatable]) {
131 for addr in addresses {
132 let segment = addr.segment_index;
133 if segment.is_negative() {
134 continue;
135 }
136 let segment = segment as usize;
137 if segment >= self.0.len() {
138 self.0.resize(segment + 1, bv::BitVec::new());
139 }
140
141 let offset = addr.offset;
142 if offset >= self.0[segment].len() {
143 self.0[segment].resize(offset + 1, false);
144 }
145 self.0[segment].replace(offset, true);
146 }
147 }
148}
149
150#[cfg(test)]
151impl AddressSet {
152 pub(crate) fn len(&self) -> usize {
153 self.0
154 .iter()
155 .map(|segment| segment.iter().map(|bit| *bit as usize).sum::<usize>())
156 .sum()
157 }
158}
159
160pub struct Memory {
161 pub(crate) data: Vec<Vec<MemoryCell>>,
162 pub(crate) temp_data: Vec<Vec<MemoryCell>>,
168 #[cfg(not(feature = "extensive_hints"))]
171 pub(crate) relocation_rules: HashMap<usize, Relocatable>,
172 #[cfg(feature = "extensive_hints")]
173 pub(crate) relocation_rules: HashMap<usize, MaybeRelocatable>,
174 pub validated_addresses: AddressSet,
175 validation_rules: Vec<Option<ValidationRule>>,
176}
177
178impl Memory {
179 pub fn new() -> Memory {
180 Memory {
181 data: Vec::new(),
182 temp_data: Vec::new(),
183 relocation_rules: HashMap::new(),
184 validated_addresses: AddressSet::new(),
185 validation_rules: Vec::with_capacity(7),
186 }
187 }
188
189 fn get_segment(&mut self, key: Relocatable) -> Result<&mut Vec<MemoryCell>, MemoryError> {
190 let (value_index, _) = from_relocatable_to_indexes(key);
191 let data = if key.segment_index.is_negative() {
192 &mut self.temp_data
193 } else {
194 &mut self.data
195 };
196 let data_len = data.len();
197 data.get_mut(value_index)
198 .ok_or_else(|| MemoryError::UnallocatedSegment(Box::new((value_index, data_len))))
199 }
200
201 pub fn insert<V>(&mut self, key: Relocatable, val: V) -> Result<(), MemoryError>
206 where
207 MaybeRelocatable: From<V>,
208 {
209 let val = MaybeRelocatable::from(val);
210 let segment = self.get_segment(key)?;
211 let (_, value_offset) = from_relocatable_to_indexes(key);
212
213 let (len, capacity) = (segment.len(), segment.capacity());
216 if len <= value_offset {
217 let new_len = value_offset
218 .checked_add(1)
219 .ok_or(MemoryError::VecCapacityExceeded)?;
220 segment
221 .try_reserve(new_len.saturating_sub(capacity))
222 .map_err(|_| MemoryError::VecCapacityExceeded)?;
223 segment.resize(new_len, MemoryCell::NONE);
224 }
225 match segment[value_offset].get_value() {
228 None => segment[value_offset] = MemoryCell::new(val),
229 Some(current_cell) => {
230 if current_cell != val {
231 return Err(MemoryError::InconsistentMemory(Box::new((
233 key,
234 current_cell,
235 val,
236 ))));
237 }
238 }
239 };
240 self.validate_memory_cell(key)
241 }
242
243 pub(crate) fn delete_unaccessed(&mut self, addr: Relocatable) -> Result<(), MemoryError> {
244 let (_, offset) = from_relocatable_to_indexes(addr);
245 let segment = self.get_segment(addr)?;
246
247 if offset >= segment.len() {
249 return Err(MemoryError::UnsetUnallocatedCell(addr));
250 }
251
252 if segment[offset].is_accessed() {
254 return Err(MemoryError::UnsetAccessedCell(addr));
255 }
256
257 segment[offset] = MemoryCell::NONE;
259 Ok(())
260 }
261
262 pub(crate) fn get<'a, 'b: 'a, K: 'a>(&'b self, key: &'a K) -> Option<Cow<'b, MaybeRelocatable>>
264 where
265 Relocatable: TryFrom<&'a K>,
266 {
267 let relocatable: Relocatable = key.try_into().ok()?;
268 let value = self
269 .get_segment_cells(relocatable.segment_index)?
270 .get(relocatable.offset)?
271 .get_value()?;
272 Some(Cow::Owned(self.relocate_value(&value).ok()?.into_owned()))
273 }
274
275 #[cfg(not(feature = "extensive_hints"))]
277 fn relocate_address(
278 addr: Relocatable,
279 relocation_rules: &HashMap<usize, Relocatable>,
280 ) -> Result<MaybeRelocatable, MemoryError> {
281 if addr.segment_index < 0 {
282 if let Some(x) = relocation_rules.get(&(-(addr.segment_index + 1) as usize)) {
285 return Ok((*x + addr.offset)?.into());
286 }
287 }
288 Ok(addr.into())
289 }
290
291 #[cfg(feature = "extensive_hints")]
292 fn relocate_address(
293 addr: Relocatable,
294 relocation_rules: &HashMap<usize, MaybeRelocatable>,
295 ) -> Result<MaybeRelocatable, MemoryError> {
296 if addr.segment_index < 0 {
297 if let Some(x) = relocation_rules.get(&(-(addr.segment_index + 1) as usize)) {
300 return Ok(match x {
301 MaybeRelocatable::RelocatableValue(r) => (*r + addr.offset)?.into(),
302 MaybeRelocatable::Int(i) => i.into(),
303 });
304 }
305 }
306 Ok(addr.into())
307 }
308
309 #[cfg(not(feature = "extensive_hints"))]
310 fn flatten_relocation_rules(&mut self) -> Result<(), MemoryError> {
311 let keys: Vec<usize> = self.relocation_rules.keys().copied().collect();
312 let max_hops = self.relocation_rules.len().saturating_add(1);
313 for key in keys {
314 let mut dst = *self
315 .relocation_rules
316 .get(&key)
317 .expect("key taken from keys vec must exist");
318
319 let mut hops = 0;
320 while dst.segment_index < 0 {
321 let next_key = (-(dst.segment_index + 1)) as usize;
322 let next = *self
323 .relocation_rules
324 .get(&next_key)
325 .ok_or(MemoryError::UnmappedTemporarySegment(dst.segment_index))?;
326 dst = (next + dst.offset).map_err(MemoryError::Math)?;
327 hops += 1;
328 if hops > max_hops {
329 return Err(MemoryError::Relocation); }
331 }
332 self.relocation_rules.insert(key, dst);
333 }
334 Ok(())
335 }
336
337 #[cfg(feature = "extensive_hints")]
338 fn flatten_relocation_rules(&mut self) -> Result<(), MemoryError> {
339 let keys: Vec<usize> = self.relocation_rules.keys().copied().collect();
340 let max_hops = self.relocation_rules.len().saturating_add(1);
341 for key in keys {
342 let mut dst = self
343 .relocation_rules
344 .get(&key)
345 .expect("key taken from keys vec must exist")
346 .clone();
347
348 let mut hops = 0;
349 loop {
350 match dst {
351 MaybeRelocatable::RelocatableValue(relocatable)
352 if relocatable.segment_index < 0 =>
353 {
354 let next_key = (-(relocatable.segment_index + 1)) as usize;
355 let next = self
356 .relocation_rules
357 .get(&next_key)
358 .ok_or(MemoryError::UnmappedTemporarySegment(
359 relocatable.segment_index,
360 ))?
361 .clone();
362
363 match next {
364 MaybeRelocatable::RelocatableValue(next_relocatable) => {
365 dst = MaybeRelocatable::RelocatableValue(
366 (next_relocatable + relocatable.offset)
367 .map_err(MemoryError::Math)?,
368 );
369 }
370 MaybeRelocatable::Int(i) => {
371 if relocatable.offset != 0 {
372 return Err(MemoryError::NonZeroOffset(relocatable.offset));
373 }
374 dst = MaybeRelocatable::Int(i);
375 }
376 }
377 }
378 _ => break,
379 }
380 hops += 1;
381 if hops > max_hops {
382 return Err(MemoryError::Relocation);
383 }
384 }
385 self.relocation_rules.insert(key, dst);
386 }
387 Ok(())
388 }
389
390 pub fn relocate_memory(&mut self) -> Result<(), MemoryError> {
392 if self.relocation_rules.is_empty() || self.temp_data.is_empty() {
393 return Ok(());
394 }
395
396 self.flatten_relocation_rules()?;
398
399 for segment in self.data.iter_mut().chain(self.temp_data.iter_mut()) {
401 for cell in segment.iter_mut() {
402 let value = cell.get_value();
403 match value {
404 Some(MaybeRelocatable::RelocatableValue(addr)) if addr.segment_index < 0 => {
405 let mut new_cell = MemoryCell::new(Memory::relocate_address(
406 addr,
407 &self.relocation_rules,
408 )?);
409 if cell.is_accessed() {
410 new_cell.mark_accessed();
411 }
412 *cell = new_cell;
413 }
414 _ => {}
415 }
416 }
417 }
418 for index in (0..self.temp_data.len()).rev() {
420 if let Some(base_addr) = self.relocation_rules.get(&index) {
421 let data_segment = self.temp_data.remove(index);
422
423 #[cfg(feature = "extensive_hints")]
424 let base_addr = match base_addr {
425 MaybeRelocatable::RelocatableValue(addr) => addr,
426 MaybeRelocatable::Int(_) => {
427 continue;
428 }
429 };
430
431 let mut addr = *base_addr;
433 if let Some(s) = self.data.get_mut(addr.segment_index as usize) {
434 s.reserve_exact(data_segment.len())
435 }
436 for cell in data_segment {
437 if let Some(v) = cell.get_value() {
438 self.insert(addr, v)?;
440 if cell.is_accessed() {
442 self.mark_as_accessed(addr)
443 }
444 }
445 addr = (addr + 1)?;
446 }
447 }
448 }
449 self.relocation_rules.clear();
450 Ok(())
451 }
452
453 #[cfg(not(feature = "extensive_hints"))]
464 pub(crate) fn add_relocation_rule(
465 &mut self,
466 src_ptr: Relocatable,
467 dst_ptr: Relocatable,
468 ) -> Result<(), MemoryError> {
469 if src_ptr.segment_index >= 0 {
470 return Err(MemoryError::AddressNotInTemporarySegment(
471 src_ptr.segment_index,
472 ));
473 }
474 if src_ptr.offset != 0 {
475 return Err(MemoryError::NonZeroOffset(src_ptr.offset));
476 }
477
478 let segment_index = -(src_ptr.segment_index + 1) as usize;
481 if self.relocation_rules.contains_key(&segment_index) {
482 return Err(MemoryError::DuplicatedRelocation(src_ptr.segment_index));
483 }
484
485 self.relocation_rules.insert(segment_index, dst_ptr);
486 Ok(())
487 }
488 #[cfg(feature = "extensive_hints")]
489 pub(crate) fn add_relocation_rule(
490 &mut self,
491 src_ptr: Relocatable,
492 dst: MaybeRelocatable,
493 ) -> Result<(), MemoryError> {
494 if src_ptr.segment_index >= 0 {
495 return Err(MemoryError::AddressNotInTemporarySegment(
496 src_ptr.segment_index,
497 ));
498 }
499 if src_ptr.offset != 0 {
500 return Err(MemoryError::NonZeroOffset(src_ptr.offset));
501 }
502
503 let segment_index = -(src_ptr.segment_index + 1) as usize;
506 if self.relocation_rules.contains_key(&segment_index) {
507 return Err(MemoryError::DuplicatedRelocation(src_ptr.segment_index));
508 }
509
510 self.relocation_rules.insert(segment_index, dst);
511 Ok(())
512 }
513
514 pub fn get_integer(&'_ self, key: Relocatable) -> Result<Cow<'_, Felt252>, MemoryError> {
517 match self
518 .get(&key)
519 .ok_or_else(|| MemoryError::UnknownMemoryCell(Box::new(key)))?
520 {
521 Cow::Borrowed(MaybeRelocatable::Int(int)) => Ok(Cow::Borrowed(int)),
522 Cow::Owned(MaybeRelocatable::Int(int)) => Ok(Cow::Owned(int)),
523 _ => Err(MemoryError::ExpectedInteger(Box::new(key))),
524 }
525 }
526
527 pub fn get_u32(&self, key: Relocatable) -> Result<u32, MemoryError> {
530 let felt = self.get_integer(key)?.into_owned();
531 felt.to_u32()
532 .ok_or_else(|| MemoryError::Math(MathError::Felt252ToU32Conversion(Box::new(felt))))
533 }
534
535 pub fn get_usize(&self, key: Relocatable) -> Result<usize, MemoryError> {
538 let felt = self.get_integer(key)?.into_owned();
539 felt.to_usize()
540 .ok_or_else(|| MemoryError::Math(MathError::Felt252ToUsizeConversion(Box::new(felt))))
541 }
542
543 pub fn get_relocatable(&self, key: Relocatable) -> Result<Relocatable, MemoryError> {
546 match self
547 .get(&key)
548 .ok_or_else(|| MemoryError::UnknownMemoryCell(Box::new(key)))?
549 {
550 Cow::Borrowed(MaybeRelocatable::RelocatableValue(rel)) => Ok(*rel),
551 Cow::Owned(MaybeRelocatable::RelocatableValue(rel)) => Ok(rel),
552 _ => Err(MemoryError::ExpectedRelocatable(Box::new(key))),
553 }
554 }
555
556 pub fn get_maybe_relocatable(&self, key: Relocatable) -> Result<MaybeRelocatable, MemoryError> {
559 match self
560 .get(&key)
561 .ok_or_else(|| MemoryError::UnknownMemoryCell(Box::new(key)))?
562 {
563 Cow::Borrowed(maybe_rel) => Ok(maybe_rel.clone()),
565 Cow::Owned(maybe_rel) => Ok(maybe_rel),
566 }
567 }
568
569 pub fn insert_value<T: Into<MaybeRelocatable>>(
572 &mut self,
573 key: Relocatable,
574 val: T,
575 ) -> Result<(), MemoryError> {
576 self.insert(key, &val.into())
577 }
578
579 pub fn add_validation_rule(&mut self, segment_index: usize, rule: ValidationRule) {
580 if segment_index >= self.validation_rules.len() {
581 self.validation_rules
583 .resize_with(segment_index + 1, || None);
584 }
585 self.validation_rules[segment_index] = Some(rule);
586 }
587
588 fn validate_memory_cell(&mut self, addr: Relocatable) -> Result<(), MemoryError> {
589 if let Some(Some(rule)) = addr
590 .segment_index
591 .to_usize()
592 .and_then(|x| self.validation_rules.get(x))
593 {
594 if !self.validated_addresses.contains(&addr) {
595 self.validated_addresses
596 .extend(rule.0(self, addr)?.as_slice());
597 }
598 }
599 Ok(())
600 }
601
602 pub fn validate_existing_memory(&mut self) -> Result<(), MemoryError> {
604 for (index, rule) in self.validation_rules.iter().enumerate() {
605 if index >= self.data.len() {
606 continue;
607 }
608 let Some(rule) = rule else {
609 continue;
610 };
611 for offset in 0..self.data[index].len() {
612 let addr = Relocatable::from((index as isize, offset));
613 if !self.validated_addresses.contains(&addr) {
614 self.validated_addresses
615 .extend(rule.0(self, addr)?.as_slice());
616 }
617 }
618 }
619 Ok(())
620 }
621
622 fn get_segment_cells(&self, idx: isize) -> Option<&[MemoryCell]> {
623 if idx.is_negative() {
624 self.temp_data.get(-(idx + 1) as usize).map(Vec::as_slice)
625 } else {
626 self.data.get(idx as usize).map(Vec::as_slice)
627 }
628 }
629
630 pub(crate) fn memcmp(
640 &self,
641 lhs: Relocatable,
642 rhs: Relocatable,
643 len: usize,
644 ) -> (Ordering, usize) {
645 match (
646 self.get_segment_cells(lhs.segment_index),
647 self.get_segment_cells(rhs.segment_index),
648 ) {
649 (None, None) => {
650 return (Ordering::Equal, 0);
651 }
652 (Some(_), None) => {
653 return (Ordering::Greater, 0);
654 }
655 (None, Some(_)) => {
656 return (Ordering::Less, 0);
657 }
658 (Some(lhs_segment), Some(rhs_segment)) => {
659 let (lhs_start, rhs_start) = (lhs.offset, rhs.offset);
660 for i in 0..len {
661 let (lhs, rhs) = (
662 lhs_segment.get(lhs_start + i),
663 rhs_segment.get(rhs_start + i),
664 );
665 let ord = lhs.cmp(&rhs);
666 if ord == Ordering::Equal {
667 continue;
668 }
669 return (ord, i);
670 }
671 }
672 };
673 (Ordering::Equal, len)
674 }
675
676 pub(crate) fn mem_eq(&self, lhs: Relocatable, rhs: Relocatable, len: usize) -> bool {
685 if lhs == rhs {
686 return true;
687 }
688 match (
689 self.get_segment_cells(lhs.segment_index)
690 .and_then(|s| s.get(lhs.offset..)),
691 self.get_segment_cells(rhs.segment_index)
692 .and_then(|s| s.get(rhs.offset..)),
693 ) {
694 (Some(lhs), Some(rhs)) => {
695 let (lhs_len, rhs_len) = (lhs.len().min(len), rhs.len().min(len));
696 if lhs_len != rhs_len {
697 return false;
698 }
699 lhs[..lhs_len] == rhs[..rhs_len]
700 }
701 (None, None) => true,
702 _ => false,
703 }
704 }
705
706 pub fn get_range(
709 &'_ self,
710 addr: Relocatable,
711 size: usize,
712 ) -> Vec<Option<Cow<'_, MaybeRelocatable>>> {
713 let mut values = Vec::new();
714
715 for i in 0..size {
716 values.push((addr + i).ok().and_then(|x| self.get(&x)));
717 }
718
719 values
720 }
721
722 pub fn get_continuous_range(
725 &self,
726 addr: Relocatable,
727 size: usize,
728 ) -> Result<Vec<MaybeRelocatable>, MemoryError> {
729 let mut values = Vec::with_capacity(size);
730
731 for i in 0..size {
732 values.push(match self.get(&(addr + i)?) {
733 Some(elem) => elem.into_owned(),
734 None => return Err(MemoryError::GetRangeMemoryGap(Box::new((addr, size)))),
735 });
736 }
737
738 Ok(values)
739 }
740
741 pub fn get_integer_range(
745 &'_ self,
746 addr: Relocatable,
747 size: usize,
748 ) -> Result<Vec<Cow<'_, Felt252>>, MemoryError> {
749 let mut values = Vec::new();
750
751 for i in 0..size {
752 values.push(self.get_integer((addr + i)?)?);
753 }
754
755 Ok(values)
756 }
757
758 pub fn get_u32_range(&self, addr: Relocatable, size: usize) -> Result<Vec<u32>, MemoryError> {
761 let mut values = Vec::new();
762
763 for i in 0..size {
764 values.push(self.get_u32((addr + i)?)?);
765 }
766
767 Ok(values)
768 }
769
770 fn get_cell(&self, addr: Relocatable) -> Option<&MemoryCell> {
771 let (i, j) = from_relocatable_to_indexes(addr);
772 let data = if addr.segment_index < 0 {
773 &self.temp_data
774 } else {
775 &self.data
776 };
777 data.get(i)?.get(j)
778 }
779
780 #[cfg(test)]
781 pub(crate) fn get_cell_for_testing(&self, addr: Relocatable) -> Option<&MemoryCell> {
782 self.get_cell(addr)
783 }
784
785 pub fn is_accessed(&self, addr: &Relocatable) -> Result<bool, MemoryError> {
786 Ok(self
787 .get_cell(*addr)
788 .ok_or(MemoryError::UnknownMemoryCell(Box::new(*addr)))?
789 .is_accessed())
790 }
791
792 pub fn mark_as_accessed(&mut self, addr: Relocatable) {
793 let (i, j) = from_relocatable_to_indexes(addr);
794 let data = if addr.segment_index < 0 {
795 &mut self.temp_data
796 } else {
797 &mut self.data
798 };
799 let cell = data.get_mut(i).and_then(|x| x.get_mut(j));
800 if let Some(cell) = cell {
801 cell.mark_accessed()
802 }
803 }
804
805 pub fn get_amount_of_accessed_addresses_for_segment(
806 &self,
807 segment_index: usize,
808 ) -> Option<usize> {
809 let segment = self.data.get(segment_index)?;
810 Some(
811 segment
812 .iter()
813 .filter(|x| x.is_some() && x.is_accessed())
814 .count(),
815 )
816 }
817
818 pub(crate) fn insert_as_accessed<V>(
821 &mut self,
822 key: Relocatable,
823 val: V,
824 ) -> Result<(), MemoryError>
825 where
826 MaybeRelocatable: From<V>,
827 {
828 self.insert(key, val)?;
829 self.mark_as_accessed(key);
830 Ok(())
831 }
832}
833
834impl From<&Memory> for CairoPieMemory {
835 fn from(mem: &Memory) -> CairoPieMemory {
836 let mut pie_memory = Vec::default();
837 for (i, segment) in mem.data.iter().enumerate() {
838 for (j, cell) in segment.iter().enumerate() {
839 if let Some(value) = cell.get_value() {
840 pie_memory.push(((i, j), value))
841 }
842 }
843 }
844 CairoPieMemory(pie_memory)
845 }
846}
847
848impl fmt::Display for Memory {
849 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
850 for (i, segment) in self.temp_data.iter().enumerate() {
851 for (j, cell) in segment.iter().enumerate() {
852 if let Some(elem) = cell.get_value() {
853 let temp_segment = i + 1;
854 writeln!(f, "(-{temp_segment},{j}) : {elem}")?;
855 }
856 }
857 }
858 for (i, segment) in self.data.iter().enumerate() {
859 for (j, cell) in segment.iter().enumerate() {
860 if let Some(elem) = cell.get_value() {
861 writeln!(f, "({i},{j}) : {elem}")?;
862 }
863 }
864 }
865 Ok(())
866 }
867}
868
869pub(crate) trait RelocateValue<'a, Input: 'a, Output: 'a> {
871 fn relocate_value(&self, value: Input) -> Result<Output, MemoryError>;
872}
873
874#[cfg(not(feature = "extensive_hints"))]
875impl RelocateValue<'_, Relocatable, Relocatable> for Memory {
876 fn relocate_value(&self, addr: Relocatable) -> Result<Relocatable, MemoryError> {
877 if addr.segment_index < 0 {
878 if let Some(x) = self
881 .relocation_rules
882 .get(&(-(addr.segment_index + 1) as usize))
883 {
884 return (*x + addr.offset).map_err(MemoryError::Math);
885 }
886 }
887 Ok(addr)
888 }
889}
890#[cfg(feature = "extensive_hints")]
891impl RelocateValue<'_, Relocatable, MaybeRelocatable> for Memory {
892 fn relocate_value(&self, addr: Relocatable) -> Result<MaybeRelocatable, MemoryError> {
893 if addr.segment_index < 0 {
894 if let Some(x) = self
897 .relocation_rules
898 .get(&(-(addr.segment_index + 1) as usize))
899 {
900 return Ok(match x {
901 MaybeRelocatable::RelocatableValue(r) => {
902 (*r + addr.offset).map_err(MemoryError::Math)?.into()
903 }
904 MaybeRelocatable::Int(i) => i.into(),
905 });
906 }
907 }
908 Ok(addr.into())
909 }
910}
911
912impl<'a> RelocateValue<'a, &'a Felt252, &'a Felt252> for Memory {
913 fn relocate_value(&self, value: &'a Felt252) -> Result<&'a Felt252, MemoryError> {
914 Ok(value)
915 }
916}
917
918impl<'a> RelocateValue<'a, &'a MaybeRelocatable, Cow<'a, MaybeRelocatable>> for Memory {
919 fn relocate_value(
920 &self,
921 value: &'a MaybeRelocatable,
922 ) -> Result<Cow<'a, MaybeRelocatable>, MemoryError> {
923 Ok(match value {
924 MaybeRelocatable::Int(_) => Cow::Borrowed(value),
925 MaybeRelocatable::RelocatableValue(addr) => {
926 #[cfg(not(feature = "extensive_hints"))]
927 let v = self.relocate_value(*addr)?.into();
928 #[cfg(feature = "extensive_hints")]
929 let v = self.relocate_value(*addr)?;
930
931 Cow::Owned(v)
932 }
933 })
934 }
935}
936
937impl Default for Memory {
938 fn default() -> Self {
939 Self::new()
940 }
941}
942
943#[cfg(test)]
944mod memory_tests {
945
946 use super::*;
947 use crate::{
948 felt_hex, relocatable,
949 utils::test_utils::*,
950 vm::{
951 runners::builtin_runner::{
952 RangeCheckBuiltinRunner, SignatureBuiltinRunner, RC_N_PARTS_STANDARD,
953 },
954 vm_memory::memory_segments::MemorySegmentManager,
955 },
956 };
957 use assert_matches::assert_matches;
958
959 use crate::vm::errors::memory_errors::MemoryError;
960
961 use crate::utils::test_utils::memory_from_memory;
962 use crate::utils::test_utils::memory_inner;
963
964 #[test]
965 fn insert_and_get_succesful() {
966 let key = Relocatable::from((0, 0));
967 let val = MaybeRelocatable::from(Felt252::from(5_u64));
968 let mut memory = Memory::new();
969 memory.data.push(Vec::new());
970 memory.insert(key, &val).unwrap();
971 assert_eq!(
972 memory.get(&key).unwrap().as_ref(),
973 &MaybeRelocatable::from(Felt252::from(5_u64))
974 );
975 }
976
977 #[test]
978 fn get_valuef_from_temp_segment() {
979 let mut memory = Memory::new();
980 memory.temp_data = vec![vec![
981 MemoryCell::NONE,
982 MemoryCell::NONE,
983 MemoryCell::new(mayberelocatable!(8)),
984 ]];
985 assert_eq!(
986 memory.get(&mayberelocatable!(-1, 2)).unwrap().as_ref(),
987 &mayberelocatable!(8),
988 );
989 }
990
991 #[test]
992 fn insert_value_in_temp_segment() {
993 let key = Relocatable::from((-1, 3));
994 let val = MaybeRelocatable::from(Felt252::from(8_u64));
995 let mut memory = Memory::new();
996 memory.temp_data.push(Vec::new());
997 memory.insert(key, &val).unwrap();
998 assert_eq!(
999 memory.temp_data[0][3],
1000 MemoryCell::new(MaybeRelocatable::from(Felt252::from(8_u64)))
1001 );
1002 }
1003
1004 #[test]
1005 fn insert_and_get_from_temp_segment_succesful() {
1006 let key = Relocatable::from((-1, 0));
1007 let val = MaybeRelocatable::from(Felt252::from(5_u64));
1008 let mut memory = Memory::new();
1009 memory.temp_data.push(Vec::new());
1010 memory.insert(key, &val).unwrap();
1011 assert_eq!(
1012 memory.get(&key).unwrap().as_ref(),
1013 &MaybeRelocatable::from(Felt252::from(5_u64)),
1014 );
1015 }
1016
1017 #[test]
1018 fn insert_and_get_from_temp_segment_failed() {
1019 let key = relocatable!(-1, 1);
1020 let mut memory = Memory::new();
1021 memory.temp_data = vec![vec![
1022 MemoryCell::NONE,
1023 MemoryCell::new(mayberelocatable!(8)),
1024 ]];
1025 assert_eq!(
1026 memory.insert(key, &mayberelocatable!(5)),
1027 Err(MemoryError::InconsistentMemory(Box::new((
1028 relocatable!(-1, 1),
1029 mayberelocatable!(8),
1030 mayberelocatable!(5)
1031 ))))
1032 );
1033 }
1034
1035 #[test]
1036 fn get_non_allocated_memory() {
1037 let key = Relocatable::from((0, 0));
1038 let memory = Memory::new();
1039 assert_eq!(memory.get(&key), None);
1040 }
1041
1042 #[test]
1043 fn get_non_existant_element() {
1044 let key = Relocatable::from((0, 0));
1045 let memory = Memory::new();
1046 assert_eq!(memory.get(&key), None);
1047 }
1048
1049 #[test]
1050 fn insert_non_allocated_memory() {
1051 let key = Relocatable::from((0, 0));
1052 let val = MaybeRelocatable::from(Felt252::from(5_u64));
1053 let mut memory = Memory::new();
1054 let error = memory.insert(key, &val);
1055 assert_eq!(
1056 error,
1057 Err(MemoryError::UnallocatedSegment(Box::new((0, 0))))
1058 );
1059 }
1060
1061 #[test]
1062 fn insert_inconsistent_memory() {
1063 let key = Relocatable::from((0, 0));
1064 let val_a = MaybeRelocatable::from(Felt252::from(5_u64));
1065 let val_b = MaybeRelocatable::from(Felt252::from(6_u64));
1066 let mut memory = Memory::new();
1067 memory.data.push(Vec::new());
1068 memory
1069 .insert(key, &val_a)
1070 .expect("Unexpected memory insert fail");
1071 let error = memory.insert(key, &val_b);
1072 assert_eq!(
1073 error,
1074 Err(MemoryError::InconsistentMemory(Box::new((
1075 key, val_a, val_b
1076 ))))
1077 );
1078 }
1079
1080 #[test]
1081 fn insert_non_contiguous_element() {
1082 let key_a = Relocatable::from((0, 0));
1083 let key_b = Relocatable::from((0, 2));
1084 let val = MaybeRelocatable::from(Felt252::from(5_u64));
1085 let mut memory = Memory::new();
1086 memory.data.push(Vec::new());
1087 memory.insert(key_a, &val).unwrap();
1088 memory.insert(key_b, &val).unwrap();
1089 assert_eq!(memory.get(&key_b).unwrap().as_ref(), &val);
1090 }
1091
1092 #[test]
1093 fn insert_non_contiguous_element_memory_gaps_none() {
1094 let key_a = Relocatable::from((0, 0));
1095 let key_b = Relocatable::from((0, 5));
1096 let val = MaybeRelocatable::from(Felt252::from(5_u64));
1097 let mut memory = Memory::new();
1098 memory.data.push(Vec::new());
1099 memory.insert(key_a, &val).unwrap();
1100 memory.insert(key_b, &val).unwrap();
1101 assert_eq!(memory.get(&key_b).unwrap().as_ref(), &val);
1102 assert_eq!(memory.get(&MaybeRelocatable::from((0, 1))), None);
1103 assert_eq!(memory.get(&MaybeRelocatable::from((0, 2))), None);
1104 assert_eq!(memory.get(&MaybeRelocatable::from((0, 3))), None);
1105 assert_eq!(memory.get(&MaybeRelocatable::from((0, 4))), None);
1106 }
1107
1108 #[test]
1109 fn validate_existing_memory_for_range_check_within_bounds() {
1110 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
1111 let mut segments = MemorySegmentManager::new();
1112 builtin.initialize_segments(&mut segments);
1113 builtin.add_validation_rule(&mut segments.memory);
1114 for _ in 0..3 {
1115 segments.add();
1116 }
1117
1118 segments
1119 .memory
1120 .insert(
1121 Relocatable::from((0, 0)),
1122 &MaybeRelocatable::from(Felt252::from(45_u64)),
1123 )
1124 .unwrap();
1125 segments.memory.validate_existing_memory().unwrap();
1126 assert!(segments
1127 .memory
1128 .validated_addresses
1129 .contains(&Relocatable::from((0, 0))));
1130 }
1131
1132 #[test]
1133 fn validate_existing_memory_for_range_check_outside_bounds() {
1134 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
1135 let mut segments = MemorySegmentManager::new();
1136 segments.add();
1137 builtin.initialize_segments(&mut segments);
1138 segments
1139 .memory
1140 .insert(
1141 Relocatable::from((1, 0)),
1142 &MaybeRelocatable::from(Felt252::from(-10)),
1143 )
1144 .unwrap();
1145 builtin.add_validation_rule(&mut segments.memory);
1146 let error = segments.memory.validate_existing_memory();
1147 assert_eq!(
1148 error,
1149 Err(MemoryError::RangeCheckNumOutOfBounds(Box::new((
1150 Felt252::from(-10),
1151 Felt252::TWO.pow(128_u128)
1152 ))))
1153 );
1154 }
1155
1156 #[test]
1157 fn validate_existing_memory_for_invalid_signature() {
1158 let mut builtin = SignatureBuiltinRunner::new(Some(512), true);
1159 let mut segments = MemorySegmentManager::new();
1160 builtin.initialize_segments(&mut segments);
1161 segments.memory = memory![
1162 (
1163 (0, 0),
1164 (
1165 "874739451078007766457464989774322083649278607533249481151382481072868806602",
1166 10
1167 )
1168 ),
1169 (
1170 (0, 1),
1171 (
1172 "-1472574760335685482768423018116732869320670550222259018541069375211356613248",
1173 10
1174 )
1175 )
1176 ];
1177 builtin.add_validation_rule(&mut segments.memory);
1178 let error = segments.memory.validate_existing_memory();
1179 assert_eq!(
1180 error,
1181 Err(MemoryError::SignatureNotFound(Box::new((0, 0).into())))
1182 );
1183 }
1184
1185 #[test]
1186 fn validate_existing_memory_for_valid_signature() {
1187 let mut builtin = SignatureBuiltinRunner::new(Some(512), true);
1188
1189 let signature_r =
1190 felt_hex!("0x411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20");
1191 let signature_s =
1192 felt_hex!("0x405c3191ab3883ef2b763af35bc5f5d15b3b4e99461d70e84c654a351a7c81b");
1193
1194 builtin
1195 .add_signature(Relocatable::from((1, 0)), &(signature_r, signature_s))
1196 .unwrap();
1197
1198 let mut segments = MemorySegmentManager::new();
1199
1200 segments.memory = memory![
1201 (
1202 (1, 0),
1203 (
1204 "874739451078007766457464989774322083649278607533249481151382481072868806602",
1205 10
1206 )
1207 ),
1208 ((1, 1), 2)
1209 ];
1210
1211 builtin.initialize_segments(&mut segments);
1212
1213 builtin.add_validation_rule(&mut segments.memory);
1214
1215 let result = segments.memory.validate_existing_memory();
1216
1217 assert_eq!(result, Ok(()))
1218 }
1219
1220 #[test]
1221 fn validate_existing_memory_for_range_check_relocatable_value() {
1222 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
1223 let mut segments = MemorySegmentManager::new();
1224 builtin.initialize_segments(&mut segments);
1225 segments.memory = memory![((0, 0), (0, 4))];
1226 builtin.add_validation_rule(&mut segments.memory);
1227 let error = segments.memory.validate_existing_memory();
1228 assert_eq!(
1229 error,
1230 Err(MemoryError::RangeCheckFoundNonInt(Box::new(relocatable!(
1231 0, 0
1232 ))))
1233 );
1234 }
1235
1236 #[test]
1237 fn validate_existing_memory_for_range_check_out_of_bounds_diff_segment() {
1238 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
1239 let mut segments = MemorySegmentManager::new();
1240 segments.memory = Memory::new();
1241 segments.add();
1242 builtin.initialize_segments(&mut segments);
1243 segments
1244 .memory
1245 .insert(
1246 Relocatable::from((0, 0)),
1247 &MaybeRelocatable::from(Felt252::from(-45_i128)),
1248 )
1249 .unwrap();
1250 builtin.add_validation_rule(&mut segments.memory);
1251 assert_eq!(segments.memory.validate_existing_memory(), Ok(()));
1252 }
1253
1254 #[test]
1255 fn get_integer_valid() {
1256 let memory = memory![((0, 0), 10)];
1257 assert_eq!(
1258 memory
1259 .get_integer(Relocatable::from((0, 0)))
1260 .unwrap()
1261 .as_ref(),
1262 &Felt252::from(10)
1263 );
1264 }
1265
1266 #[test]
1267 fn get_integer_invalid_expected_integer() {
1268 let mut segments = MemorySegmentManager::new();
1269 segments.add();
1270 segments
1271 .memory
1272 .insert(Relocatable::from((0, 0)), &MaybeRelocatable::from((0, 10)))
1273 .unwrap();
1274 assert_matches!(
1275 segments.memory.get_integer(Relocatable::from((0, 0))),
1276 Err(MemoryError::ExpectedInteger(
1277 bx
1278 )) if *bx == Relocatable::from((0, 0))
1279 );
1280 }
1281
1282 #[test]
1283 fn get_u32_too_big() {
1284 let mut segments = MemorySegmentManager::new();
1285 segments.add();
1286 segments
1287 .memory
1288 .insert(Relocatable::from((0, 0)), &Felt252::from(1_u64 << 32))
1289 .unwrap();
1290 assert_matches!(
1291 segments.memory.get_u32(Relocatable::from((0, 0))),
1292 Err(MemoryError::Math(MathError::Felt252ToU32Conversion(
1293 bx
1294 ))) if *bx == Felt252::from(1_u64 << 32)
1295 );
1296 }
1297
1298 #[test]
1299 fn get_maybe_relocatable_valid_relocatable() {
1300 let memory = memory![((0, 0), (1, 0))];
1301 assert_eq!(
1302 memory
1303 .get_maybe_relocatable(Relocatable::from((0, 0)))
1304 .unwrap(),
1305 Relocatable::from((1, 0)).into()
1306 );
1307 }
1308
1309 #[test]
1310 fn get_maybe_relocatable_valid_integer() {
1311 let memory = memory![((0, 0), 10)];
1312 assert_eq!(
1313 memory
1314 .get_maybe_relocatable(Relocatable::from((0, 0)))
1315 .unwrap(),
1316 10.into()
1317 );
1318 }
1319
1320 #[test]
1321 fn default_memory() {
1322 let mem: Memory = Default::default();
1323 assert_eq!(mem.data.len(), 0);
1324 }
1325
1326 #[test]
1327 fn insert_and_get_temporary_succesful() {
1328 let mut memory = Memory::new();
1329 memory.temp_data.push(Vec::new());
1330
1331 let key = Relocatable::from((-1, 0));
1332 let val = MaybeRelocatable::from(Felt252::from(5));
1333 memory.insert(key, &val).unwrap();
1334
1335 assert_eq!(memory.get(&key).unwrap().as_ref(), &val);
1336 }
1337
1338 #[test]
1339 fn add_relocation_rule() {
1340 let mut memory = Memory::new();
1341
1342 assert_eq!(
1343 memory.add_relocation_rule((-1, 0).into(), (1, 2).into()),
1344 Ok(()),
1345 );
1346 assert_eq!(
1347 memory.add_relocation_rule((-2, 0).into(), (-1, 1).into()),
1348 Ok(()),
1349 );
1350 assert_eq!(
1351 memory.add_relocation_rule((5, 0).into(), (0, 0).into()),
1352 Err(MemoryError::AddressNotInTemporarySegment(5)),
1353 );
1354 assert_eq!(
1355 memory.add_relocation_rule((-3, 6).into(), (0, 0).into()),
1356 Err(MemoryError::NonZeroOffset(6)),
1357 );
1358 assert_eq!(
1359 memory.add_relocation_rule((-1, 0).into(), (0, 0).into()),
1360 Err(MemoryError::DuplicatedRelocation(-1)),
1361 );
1362 }
1363
1364 #[test]
1365 fn relocate_value_bigint() {
1366 let mut memory = Memory::new();
1367 memory
1368 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1369 .unwrap();
1370 memory
1371 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1372 .unwrap();
1373
1374 assert_eq!(
1376 memory
1377 .relocate_value(&MaybeRelocatable::Int(Felt252::from(0)))
1378 .unwrap(),
1379 Cow::Owned(MaybeRelocatable::Int(Felt252::from(0))),
1380 );
1381 }
1382
1383 #[test]
1384 fn relocate_value_mayberelocatable() {
1385 let mut memory = Memory::new();
1386 memory
1387 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1388 .unwrap();
1389 memory
1390 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1391 .unwrap();
1392
1393 assert_eq!(
1395 memory
1396 .relocate_value(&MaybeRelocatable::RelocatableValue((0, 0).into()))
1397 .unwrap(),
1398 Cow::Owned(MaybeRelocatable::RelocatableValue((0, 0).into())),
1399 );
1400 assert_eq!(
1401 memory
1402 .relocate_value(&MaybeRelocatable::RelocatableValue((5, 0).into()))
1403 .unwrap(),
1404 Cow::Owned(MaybeRelocatable::RelocatableValue((5, 0).into())),
1405 );
1406 }
1407
1408 #[test]
1409 fn relocate_value_mayberelocatable_temporary_segment_no_rules() {
1410 let mut memory = Memory::new();
1411 memory
1412 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1413 .unwrap();
1414 memory
1415 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1416 .unwrap();
1417
1418 assert_eq!(
1421 memory
1422 .relocate_value(&MaybeRelocatable::RelocatableValue((-5, 0).into()))
1423 .unwrap(),
1424 Cow::Owned(MaybeRelocatable::RelocatableValue((-5, 0).into())),
1425 );
1426 }
1427
1428 #[test]
1429 fn relocate_value_mayberelocatable_temporary_segment_rules() {
1430 let mut memory = Memory::new();
1431 memory
1432 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1433 .unwrap();
1434 memory
1435 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1436 .unwrap();
1437
1438 assert_eq!(
1441 memory
1442 .relocate_value(&MaybeRelocatable::RelocatableValue((-1, 0).into()))
1443 .unwrap(),
1444 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 0).into())),
1445 );
1446 assert_eq!(
1447 memory
1448 .relocate_value(&MaybeRelocatable::RelocatableValue((-2, 0).into()))
1449 .unwrap(),
1450 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 2).into())),
1451 );
1452 assert_eq!(
1453 memory
1454 .relocate_value(&MaybeRelocatable::RelocatableValue((-1, 5).into()))
1455 .unwrap(),
1456 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 5).into())),
1457 );
1458 assert_eq!(
1459 memory
1460 .relocate_value(&MaybeRelocatable::RelocatableValue((-2, 5).into()))
1461 .unwrap(),
1462 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 7).into())),
1463 );
1464 }
1465
1466 #[test]
1467 fn get_range_for_continuous_memory() {
1468 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)];
1469
1470 let value1 = MaybeRelocatable::from(Felt252::from(2));
1471 let value2 = MaybeRelocatable::from(Felt252::from(3));
1472 let value3 = MaybeRelocatable::from(Felt252::from(4));
1473
1474 let expected_vec = vec![
1475 Some(Cow::Borrowed(&value1)),
1476 Some(Cow::Borrowed(&value2)),
1477 Some(Cow::Borrowed(&value3)),
1478 ];
1479 assert_eq!(memory.get_range(Relocatable::from((1, 0)), 3), expected_vec);
1480 }
1481
1482 #[test]
1483 fn get_range_for_non_continuous_memory() {
1484 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 3), 4)];
1485
1486 let value1 = MaybeRelocatable::from(Felt252::from(2));
1487 let value2 = MaybeRelocatable::from(Felt252::from(3));
1488 let value3 = MaybeRelocatable::from(Felt252::from(4));
1489
1490 let expected_vec = vec![
1491 Some(Cow::Borrowed(&value1)),
1492 Some(Cow::Borrowed(&value2)),
1493 None,
1494 Some(Cow::Borrowed(&value3)),
1495 ];
1496 assert_eq!(memory.get_range(Relocatable::from((1, 0)), 4), expected_vec);
1497 }
1498
1499 #[test]
1500 fn get_continuous_range_for_continuous_memory() {
1501 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)];
1502
1503 let value1 = MaybeRelocatable::from(Felt252::from(2));
1504 let value2 = MaybeRelocatable::from(Felt252::from(3));
1505 let value3 = MaybeRelocatable::from(Felt252::from(4));
1506
1507 let expected_vec = vec![value1, value2, value3];
1508 assert_eq!(
1509 memory.get_continuous_range(Relocatable::from((1, 0)), 3),
1510 Ok(expected_vec)
1511 );
1512 }
1513
1514 #[test]
1515 fn get_continuous_range_for_non_continuous_memory() {
1516 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 3), 4)];
1517
1518 assert_eq!(
1519 memory.get_continuous_range(Relocatable::from((1, 0)), 3),
1520 Err(MemoryError::GetRangeMemoryGap(Box::new(((1, 0).into(), 3))))
1521 );
1522 }
1523
1524 #[test]
1525 fn get_u32_range_ok() {
1526 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967295), ((0, 3), 3)];
1527 let expected_vector = vec![1, 4294967295];
1528 assert_eq!(memory.get_u32_range((0, 1).into(), 2), Ok(expected_vector));
1529 }
1530
1531 #[test]
1532 fn get_u32_range_relocatable() {
1533 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), (0, 0)), ((0, 3), 3)];
1534 assert_matches!(memory.get_u32_range((0, 1).into(), 2), Err(MemoryError::ExpectedInteger(bx)) if *bx == (0, 2).into());
1535 }
1536
1537 #[test]
1538 fn get_u32_range_over_32_bits() {
1539 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967296), ((0, 3), 3)];
1540 assert_matches!(memory.get_u32_range((0, 1).into(), 2), Err(MemoryError::Math(MathError::Felt252ToU32Conversion(bx))) if *bx == Felt252::from(4294967296_u64));
1541 }
1542
1543 #[test]
1544 fn get_u32_range_memory_gap() {
1545 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 3), 3)];
1546 assert_matches!(memory.get_u32_range((0, 1).into(), 3), Err(MemoryError::UnknownMemoryCell(bx)) if *bx == (0, 2).into());
1547 }
1548
1549 #[test]
1551 fn relocate_memory_empty_relocation_rules() {
1552 let mut memory = memory![((0, 0), 1), ((0, 1), 2), ((0, 2), 3)];
1553
1554 assert_eq!(memory.relocate_memory(), Ok(()));
1555 check_memory!(memory, ((0, 0), 1), ((0, 1), 2), ((0, 2), 3));
1556 }
1557
1558 #[test]
1559 fn relocate_memory_new_segment_with_gap() {
1560 let mut memory = memory![
1561 ((0, 0), 1),
1562 ((0, 1), (-1, 0)),
1563 ((0, 2), 3),
1564 ((1, 0), (-1, 1)),
1565 ((1, 1), 5),
1566 ((1, 2), (-1, 2)),
1567 ((-1, 0), 7),
1568 ((-1, 1), 8),
1569 ((-1, 2), 9)
1570 ];
1571 memory
1572 .add_relocation_rule((-1, 0).into(), (2, 1).into())
1573 .unwrap();
1574 memory.data.push(vec![]);
1575
1576 assert_eq!(memory.relocate_memory(), Ok(()));
1577 check_memory!(
1578 memory,
1579 ((0, 0), 1),
1580 ((0, 1), (2, 1)),
1581 ((0, 2), 3),
1582 ((1, 0), (2, 2)),
1583 ((1, 1), 5),
1584 ((1, 2), (2, 3)),
1585 ((2, 1), 7),
1586 ((2, 2), 8),
1587 ((2, 3), 9)
1588 );
1589 assert!(memory.temp_data.is_empty());
1590 }
1591
1592 #[test]
1593 fn relocate_memory_new_segment() {
1594 let mut memory = memory![
1595 ((0, 0), 1),
1596 ((0, 1), (-1, 0)),
1597 ((0, 2), 3),
1598 ((1, 0), (-1, 1)),
1599 ((1, 1), 5),
1600 ((1, 2), (-1, 2)),
1601 ((-1, 0), 7),
1602 ((-1, 1), 8),
1603 ((-1, 2), 9)
1604 ];
1605 memory
1606 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1607 .unwrap();
1608 memory.data.push(vec![]);
1609
1610 assert_eq!(memory.relocate_memory(), Ok(()));
1611
1612 check_memory!(
1613 memory,
1614 ((0, 0), 1),
1615 ((0, 1), (2, 0)),
1616 ((0, 2), 3),
1617 ((1, 0), (2, 1)),
1618 ((1, 1), 5),
1619 ((1, 2), (2, 2)),
1620 ((2, 0), 7),
1621 ((2, 1), 8),
1622 ((2, 2), 9)
1623 );
1624 assert!(memory.temp_data.is_empty());
1625 }
1626
1627 #[test]
1628 fn relocate_memory_new_segment_unallocated() {
1629 let mut memory = memory![
1630 ((0, 0), 1),
1631 ((0, 1), (-1, 0)),
1632 ((0, 2), 3),
1633 ((1, 0), (-1, 1)),
1634 ((1, 1), 5),
1635 ((1, 2), (-1, 2)),
1636 ((-1, 0), 7),
1637 ((-1, 1), 8),
1638 ((-1, 2), 9)
1639 ];
1640 memory
1641 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1642 .unwrap();
1643
1644 assert_eq!(
1645 memory.relocate_memory(),
1646 Err(MemoryError::UnallocatedSegment(Box::new((2, 2))))
1647 );
1648 }
1649
1650 #[test]
1651 fn relocate_memory_into_existing_segment() {
1652 let mut memory = memory![
1653 ((0, 0), 1),
1654 ((0, 1), (-1, 0)),
1655 ((0, 2), 3),
1656 ((1, 0), (-1, 1)),
1657 ((1, 1), 5),
1658 ((1, 2), (-1, 2)),
1659 ((-1, 0), 7),
1660 ((-1, 1), 8),
1661 ((-1, 2), 9)
1662 ];
1663 memory
1664 .add_relocation_rule((-1, 0).into(), (1, 3).into())
1665 .unwrap();
1666
1667 assert_eq!(memory.relocate_memory(), Ok(()));
1668
1669 check_memory!(
1670 memory,
1671 ((0, 0), 1),
1672 ((0, 1), (1, 3)),
1673 ((0, 2), 3),
1674 ((1, 0), (1, 4)),
1675 ((1, 1), 5),
1676 ((1, 2), (1, 5)),
1677 ((1, 3), 7),
1678 ((1, 4), 8),
1679 ((1, 5), 9)
1680 );
1681 assert!(memory.temp_data.is_empty());
1682 }
1683
1684 #[test]
1685 fn relocate_memory_into_existing_segment_inconsistent_memory() {
1686 let mut memory = memory![
1687 ((0, 0), 1),
1688 ((0, 1), (-1, 0)),
1689 ((0, 2), 3),
1690 ((1, 0), (-1, 1)),
1691 ((1, 1), 5),
1692 ((1, 2), (-1, 2)),
1693 ((-1, 0), 7),
1694 ((-1, 1), 8),
1695 ((-1, 2), 9)
1696 ];
1697 memory
1698 .add_relocation_rule((-1, 0).into(), (1, 0).into())
1699 .unwrap();
1700
1701 assert_eq!(
1702 memory.relocate_memory(),
1703 Err(MemoryError::InconsistentMemory(Box::new((
1704 (1, 0).into(),
1705 (1, 1).into(),
1706 7.into(),
1707 ))))
1708 );
1709 }
1710
1711 #[test]
1712 fn relocate_memory_new_segment_2_temporary_segments_one_relocated() {
1713 let mut memory = memory![
1714 ((0, 0), 1),
1715 ((0, 1), (-1, 0)),
1716 ((0, 2), 3),
1717 ((1, 0), (-1, 1)),
1718 ((1, 1), 5),
1719 ((1, 2), (-1, 2)),
1720 ((-1, 0), 7),
1721 ((-1, 1), 8),
1722 ((-1, 2), 9),
1723 ((-2, 0), 10),
1724 ((-2, 1), 11)
1725 ];
1726 memory
1727 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1728 .unwrap();
1729 memory.data.push(vec![]);
1730
1731 assert_eq!(memory.relocate_memory(), Ok(()));
1732 check_memory!(
1733 memory,
1734 ((0, 0), 1),
1735 ((0, 1), (2, 0)),
1736 ((0, 2), 3),
1737 ((1, 0), (2, 1)),
1738 ((1, 1), 5),
1739 ((1, 2), (2, 2)),
1740 ((2, 0), 7),
1741 ((2, 1), 8),
1742 ((2, 2), 9),
1743 ((-1, 0), 10),
1744 ((-1, 1), 11)
1745 );
1746 }
1747
1748 #[test]
1749 fn relocate_memory_new_segment_2_temporary_segments_relocated() {
1750 let mut memory = memory![
1751 ((0, 0), 1),
1752 ((0, 1), (-1, 0)),
1753 ((0, 2), 3),
1754 ((1, 0), (-1, 1)),
1755 ((1, 1), 5),
1756 ((1, 2), (-1, 2)),
1757 ((-1, 0), 7),
1758 ((-1, 1), 8),
1759 ((-1, 2), 9),
1760 ((-2, 0), 10),
1761 ((-2, 1), 11)
1762 ];
1763 memory.data.push(vec![]);
1764 memory
1765 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1766 .unwrap();
1767 memory.data.push(vec![]);
1768 memory
1769 .add_relocation_rule((-2, 0).into(), (3, 0).into())
1770 .unwrap();
1771
1772 assert_eq!(memory.relocate_memory(), Ok(()));
1773
1774 check_memory!(
1775 memory,
1776 ((0, 0), 1),
1777 ((0, 1), (2, 0)),
1778 ((0, 2), 3),
1779 ((1, 0), (2, 1)),
1780 ((1, 1), 5),
1781 ((1, 2), (2, 2)),
1782 ((2, 0), 7),
1783 ((2, 1), 8),
1784 ((2, 2), 9),
1785 ((3, 0), 10),
1786 ((3, 1), 11)
1787 );
1788 assert!(memory.temp_data.is_empty());
1789 }
1790
1791 #[test]
1792 fn test_memory_display() {
1793 let memory = memory![
1794 ((0, 0), 1),
1795 ((0, 1), (-1, 0)),
1796 ((0, 2), 3),
1797 ((1, 0), (-1, 1)),
1798 ((1, 1), 5),
1799 ((1, 2), (-1, 2)),
1800 ((-1, 0), (-1, 0)),
1801 ((-1, 1), 8),
1802 ((-1, 2), 9)
1803 ];
1804
1805 assert_eq!(
1806 format!("{}", memory),
1807 "(-1,0) : -1:0\n(-1,1) : 8\n(-1,2) : 9\n(0,0) : 1\n(0,1) : -1:0\n(0,2) : 3\n(1,0) : -1:1\n(1,1) : 5\n(1,2) : -1:2\n");
1808 }
1809
1810 #[test]
1811 fn relocate_memory_into_existing_segment_temporary_values_in_temporary_memory() {
1812 let mut memory = memory![
1813 ((0, 0), 1),
1814 ((0, 1), (-1, 0)),
1815 ((0, 2), 3),
1816 ((1, 0), (-1, 1)),
1817 ((1, 1), 5),
1818 ((1, 2), (-1, 2)),
1819 ((-1, 0), (-1, 0)),
1820 ((-1, 1), 8),
1821 ((-1, 2), 9)
1822 ];
1823 memory
1824 .add_relocation_rule((-1, 0).into(), (1, 3).into())
1825 .unwrap();
1826
1827 assert_eq!(memory.relocate_memory(), Ok(()));
1828 check_memory!(
1829 memory,
1830 ((0, 0), 1),
1831 ((0, 1), (1, 3)),
1832 ((0, 2), 3),
1833 ((1, 0), (1, 4)),
1834 ((1, 1), 5),
1835 ((1, 2), (1, 5)),
1836 ((1, 3), (1, 3)),
1837 ((1, 4), 8),
1838 ((1, 5), 9)
1839 );
1840 assert!(memory.temp_data.is_empty());
1841 }
1842
1843 #[test]
1844 fn relocate_address_with_rules() {
1845 let mut memory = Memory::new();
1846 memory
1847 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1848 .unwrap();
1849 memory
1850 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1851 .unwrap();
1852
1853 assert_eq!(
1854 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1855 MaybeRelocatable::RelocatableValue((2, 0).into()),
1856 );
1857 assert_eq!(
1858 Memory::relocate_address((-2, 1).into(), &memory.relocation_rules).unwrap(),
1859 MaybeRelocatable::RelocatableValue((2, 3).into()),
1860 );
1861 }
1862
1863 #[test]
1864 fn relocate_address_no_rules() {
1865 let memory = Memory::new();
1866 assert_eq!(
1867 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1868 MaybeRelocatable::RelocatableValue((-1, 0).into()),
1869 );
1870 assert_eq!(
1871 Memory::relocate_address((-2, 1).into(), &memory.relocation_rules).unwrap(),
1872 MaybeRelocatable::RelocatableValue((-2, 1).into()),
1873 );
1874 }
1875
1876 #[test]
1877 fn relocate_address_real_addr() {
1878 let memory = Memory::new();
1879 assert_eq!(
1880 Memory::relocate_address((1, 0).into(), &memory.relocation_rules).unwrap(),
1881 MaybeRelocatable::RelocatableValue((1, 0).into()),
1882 );
1883 assert_eq!(
1884 Memory::relocate_address((1, 1).into(), &memory.relocation_rules).unwrap(),
1885 MaybeRelocatable::RelocatableValue((1, 1).into()),
1886 );
1887 }
1888
1889 #[test]
1890 #[cfg(feature = "extensive_hints")]
1891 fn relocate_address_to_integer() {
1892 let mut memory = Memory::new();
1893 memory
1894 .add_relocation_rule((-1, 0).into(), 0.into())
1895 .unwrap();
1896 memory
1897 .add_relocation_rule((-2, 0).into(), 42.into())
1898 .unwrap();
1899
1900 assert_eq!(
1901 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1902 MaybeRelocatable::Int(0.into()),
1903 );
1904 assert_eq!(
1905 Memory::relocate_address((-2, 0).into(), &memory.relocation_rules).unwrap(),
1906 MaybeRelocatable::Int(42.into()),
1907 );
1908 }
1909
1910 #[test]
1911 #[cfg(feature = "extensive_hints")]
1912 fn relocate_address_integer_no_duplicates() {
1913 let mut memory = Memory::new();
1914 memory
1915 .add_relocation_rule((-1, 0).into(), 1.into())
1916 .unwrap();
1917 assert_eq!(
1918 memory.add_relocation_rule((-1, 0).into(), 42.into()),
1919 Err(MemoryError::DuplicatedRelocation(-1))
1920 );
1921 assert_eq!(
1922 memory.add_relocation_rule((-1, 0).into(), (2, 0).into()),
1923 Err(MemoryError::DuplicatedRelocation(-1))
1924 );
1925
1926 assert_eq!(
1927 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1928 MaybeRelocatable::Int(1.into()),
1929 );
1930
1931 memory
1932 .add_relocation_rule((-2, 0).into(), (3, 0).into())
1933 .unwrap();
1934 assert_eq!(
1935 memory.add_relocation_rule((-2, 0).into(), 1.into()),
1936 Err(MemoryError::DuplicatedRelocation(-2))
1937 );
1938
1939 assert_eq!(
1940 Memory::relocate_address((-2, 0).into(), &memory.relocation_rules).unwrap(),
1941 MaybeRelocatable::RelocatableValue((3, 0).into()),
1942 );
1943 }
1944
1945 #[test]
1946 fn mark_address_as_accessed() {
1947 let mut memory = memory![((0, 0), 0)];
1948 assert!(!memory.data[0][0].is_accessed());
1949 memory.mark_as_accessed(relocatable!(0, 0));
1950 assert!(memory.data[0][0].is_accessed());
1951 }
1952
1953 #[test]
1954 fn get_amount_of_accessed_addresses_for_segment_valid() {
1955 let mut memory = memory![((0, 0), 0)];
1956 assert_eq!(
1957 memory.get_amount_of_accessed_addresses_for_segment(0),
1958 Some(0)
1959 );
1960 memory.mark_as_accessed(relocatable!(0, 0));
1961 assert_eq!(
1962 memory.get_amount_of_accessed_addresses_for_segment(0),
1963 Some(1)
1964 );
1965 }
1966
1967 #[test]
1968 fn get_amount_of_accessed_addresses_for_segment_invalid_segment() {
1969 let memory = memory![((0, 0), 0)];
1970 assert_eq!(memory.get_amount_of_accessed_addresses_for_segment(1), None);
1971 }
1972
1973 #[test]
1974 fn memory_cell_new_is_not_accessed() {
1975 let cell = MemoryCell::new(mayberelocatable!(1));
1976 assert!(!cell.is_accessed())
1977 }
1978
1979 #[test]
1980 fn memory_cell_mark_accessed() {
1981 let mut cell = MemoryCell::new(mayberelocatable!(1));
1982 cell.mark_accessed();
1983 assert!(cell.is_accessed())
1984 }
1985
1986 #[test]
1987 fn memory_cell_get_value() {
1988 let cell = MemoryCell::new(mayberelocatable!(1));
1989 assert_eq!(cell.get_value(), Some(mayberelocatable!(1)));
1990 }
1991
1992 use core::cmp::Ordering::*;
1993
1994 fn check_memcmp(
1995 lhs: (isize, usize),
1996 rhs: (isize, usize),
1997 len: usize,
1998 ord: Ordering,
1999 pos: usize,
2000 ) {
2001 let mem = memory![
2002 ((-2, 0), 1),
2003 ((-2, 1), (1, 1)),
2004 ((-2, 3), 0),
2005 ((-2, 4), 0),
2006 ((-1, 0), 1),
2007 ((-1, 1), (1, 1)),
2008 ((-1, 3), 0),
2009 ((-1, 4), 3),
2010 ((0, 0), 1),
2011 ((0, 1), (1, 1)),
2012 ((0, 3), 0),
2013 ((0, 4), 0),
2014 ((1, 0), 1),
2015 ((1, 1), (1, 1)),
2016 ((1, 3), 0),
2017 ((1, 4), 3)
2018 ];
2019 assert_eq!((ord, pos), mem.memcmp(lhs.into(), rhs.into(), len));
2020 }
2021
2022 #[test]
2023 fn insert_alloc_fails_gracefully() {
2024 let mut mem = memory![((0, 0), 1)];
2025 let err = mem.insert((0, usize::MAX >> 1).into(), Felt252::ONE);
2026 assert_eq!(err, Err(MemoryError::VecCapacityExceeded));
2027 }
2028
2029 #[test]
2030 fn insert_overflow_fails_gracefully() {
2031 let mut mem = memory![((0, 0), 1)];
2032 let err = mem.insert((0, usize::MAX).into(), Felt252::ONE);
2033 assert_eq!(err, Err(MemoryError::VecCapacityExceeded));
2034 }
2035
2036 #[test]
2037 fn memcmp() {
2038 check_memcmp((0, 0), (0, 0), 3, Equal, 3);
2039 check_memcmp((0, 0), (1, 0), 3, Equal, 3);
2040 check_memcmp((0, 0), (1, 0), 5, Less, 4);
2041 check_memcmp((1, 0), (0, 0), 5, Greater, 4);
2042 check_memcmp((2, 2), (2, 5), 8, Equal, 0);
2043 check_memcmp((0, 0), (2, 5), 8, Greater, 0);
2044 check_memcmp((2, 5), (0, 0), 8, Less, 0);
2045 check_memcmp((-2, 0), (-2, 0), 3, Equal, 3);
2046 check_memcmp((-2, 0), (-1, 0), 3, Equal, 3);
2047 check_memcmp((-2, 0), (-1, 0), 5, Less, 4);
2048 check_memcmp((-1, 0), (-2, 0), 5, Greater, 4);
2049 check_memcmp((-3, 2), (-3, 5), 8, Equal, 0);
2050 check_memcmp((-2, 0), (-3, 5), 8, Greater, 0);
2051 check_memcmp((-3, 5), (-2, 0), 8, Less, 0);
2052 }
2053
2054 #[test]
2055 fn cairo_pie_memory_from_memory() {
2056 let memory = memory![((8, 9), 3), ((1, 2), 5), ((7, 6), (1, 2))];
2057
2058 assert_eq!(
2059 CairoPieMemory::from(&memory),
2060 CairoPieMemory(vec![
2061 ((1, 2), MaybeRelocatable::from(5)),
2062 ((7, 6), MaybeRelocatable::from((1, 2))),
2063 ((8, 9), MaybeRelocatable::from(3))
2064 ])
2065 )
2066 }
2067
2068 #[test]
2069 #[cfg(not(feature = "extensive_hints"))]
2070 fn flatten_relocation_rules_chain_happy() {
2071 let mut mem = Memory::new();
2072 mem.temp_data = vec![vec![], vec![]];
2074
2075 mem.relocation_rules.insert(0, Relocatable::from((-2, 3)));
2078 mem.relocation_rules.insert(1, Relocatable::from((10, 4)));
2079 mem.relocation_rules.insert(2, Relocatable::from((7, 1)));
2081
2082 assert_eq!(mem.flatten_relocation_rules(), Ok(()));
2083 assert_eq!(
2084 *mem.relocation_rules.get(&0).unwrap(),
2085 Relocatable::from((10, 7))
2086 );
2087 assert_eq!(
2088 *mem.relocation_rules.get(&1).unwrap(),
2089 Relocatable::from((10, 4))
2090 );
2091 assert_eq!(
2092 *mem.relocation_rules.get(&2).unwrap(),
2093 Relocatable::from((7, 1))
2094 );
2095 }
2096
2097 #[test]
2098 #[cfg(not(feature = "extensive_hints"))]
2099 fn flatten_relocation_rules_cycle_err() {
2100 let mut mem = Memory::new();
2101 mem.temp_data = vec![vec![]];
2102
2103 mem.relocation_rules.insert(0, Relocatable::from((-1, 0)));
2105
2106 assert_eq!(mem.flatten_relocation_rules(), Err(MemoryError::Relocation));
2107 }
2108
2109 #[test]
2110 #[cfg(feature = "extensive_hints")]
2111 fn flatten_relocation_rules_chain_happy_extensive_reloc_and_int() {
2112 let mut mem = Memory::new();
2113 mem.temp_data = vec![vec![], vec![], vec![], vec![], vec![]];
2114
2115 mem.relocation_rules.insert(
2120 0,
2121 MaybeRelocatable::RelocatableValue(Relocatable::from((-2, 3))),
2122 );
2123 mem.relocation_rules.insert(
2124 1,
2125 MaybeRelocatable::RelocatableValue(Relocatable::from((10, 4))),
2126 );
2127
2128 mem.relocation_rules.insert(
2134 2,
2135 MaybeRelocatable::RelocatableValue(Relocatable::from((-4, 0))),
2136 );
2137 mem.relocation_rules.insert(
2138 3,
2139 MaybeRelocatable::RelocatableValue(Relocatable::from((-5, 0))),
2140 );
2141 mem.relocation_rules
2142 .insert(4, MaybeRelocatable::Int(Felt252::from(99)));
2143
2144 assert_eq!(mem.flatten_relocation_rules(), Ok(()));
2145
2146 assert_eq!(
2147 mem.relocation_rules.get(&0),
2148 Some(&MaybeRelocatable::RelocatableValue(Relocatable::from((
2149 10, 7
2150 ))))
2151 );
2152 assert_eq!(
2153 mem.relocation_rules.get(&1),
2154 Some(&MaybeRelocatable::RelocatableValue(Relocatable::from((
2155 10, 4
2156 ))))
2157 );
2158 assert_eq!(
2159 mem.relocation_rules.get(&2),
2160 Some(&MaybeRelocatable::Int(Felt252::from(99)))
2161 );
2162 }
2163
2164 #[test]
2165 #[cfg(feature = "extensive_hints")]
2166 fn flatten_relocation_rules_int_with_non_zero_offset_err() {
2167 let mut mem = Memory::new();
2168 mem.temp_data = vec![vec![], vec![], vec![]];
2170
2171 mem.relocation_rules.insert(
2175 0,
2176 MaybeRelocatable::RelocatableValue(Relocatable::from((-2, 5))),
2177 );
2178 mem.relocation_rules.insert(
2179 1,
2180 MaybeRelocatable::RelocatableValue(Relocatable::from((-3, 0))),
2181 );
2182 mem.relocation_rules
2183 .insert(2, MaybeRelocatable::Int(Felt252::from(7)));
2184
2185 assert_eq!(
2186 mem.flatten_relocation_rules(),
2187 Err(MemoryError::NonZeroOffset(5))
2188 );
2189 }
2190
2191 #[test]
2192 #[cfg(feature = "extensive_hints")]
2193 fn flatten_relocation_rules_cycle_err_extensive() {
2194 let mut mem = Memory::new();
2195 mem.temp_data = vec![vec![], vec![]];
2196
2197 mem.relocation_rules.insert(
2201 0,
2202 MaybeRelocatable::RelocatableValue(Relocatable::from((-1, 0))),
2203 );
2204 mem.relocation_rules.insert(
2205 1,
2206 MaybeRelocatable::RelocatableValue(Relocatable::from((-2, 0))),
2207 );
2208
2209 assert_eq!(mem.flatten_relocation_rules(), Err(MemoryError::Relocation));
2210 }
2211
2212 #[test]
2213 #[cfg(not(feature = "extensive_hints"))]
2214 fn flatten_relocation_rules_missing_next_err() {
2215 let mut mem = Memory::new();
2216 mem.temp_data = vec![vec![], vec![], vec![]];
2217
2218 mem.relocation_rules.insert(0, Relocatable::from((-4, 1)));
2221
2222 assert_eq!(
2223 mem.flatten_relocation_rules(),
2224 Err(MemoryError::UnmappedTemporarySegment(-4))
2225 );
2226 }
2227
2228 #[test]
2229 #[cfg(feature = "extensive_hints")]
2230 fn flatten_relocation_rules_missing_next_err_extensive() {
2231 let mut mem = Memory::new();
2232 mem.temp_data = vec![vec![], vec![], vec![]];
2233
2234 mem.relocation_rules.insert(
2237 0,
2238 MaybeRelocatable::RelocatableValue(Relocatable::from((-4, 0))),
2239 );
2240
2241 assert_eq!(
2242 mem.flatten_relocation_rules(),
2243 Err(MemoryError::UnmappedTemporarySegment(-4))
2244 );
2245 }
2246
2247 #[test]
2248 #[cfg(not(feature = "extensive_hints"))]
2249 fn relocate_memory_temp_chain_multi_hop() {
2250 let mut memory = Memory::new();
2251
2252 memory.temp_data = vec![
2256 vec![
2257 MemoryCell::new(mayberelocatable!(100)),
2258 MemoryCell::new(mayberelocatable!(200)),
2259 ],
2260 vec![
2261 MemoryCell::new(mayberelocatable!(7)),
2262 MemoryCell::new(mayberelocatable!(8)),
2263 MemoryCell::new(mayberelocatable!(9)),
2264 ],
2265 ];
2266
2267 memory
2272 .relocation_rules
2273 .insert(0, Relocatable::from((-2, 3)));
2274 memory
2275 .relocation_rules
2276 .insert(1, Relocatable::from((5, 10)));
2277
2278 memory.data.push(vec![
2284 MemoryCell::new(mayberelocatable!(-1, 0)),
2285 MemoryCell::new(mayberelocatable!(-1, 1)),
2286 MemoryCell::new(mayberelocatable!(-2, 0)),
2287 ]);
2288
2289 while memory.data.len() <= 5 {
2291 memory.data.push(Vec::new());
2292 }
2293
2294 assert_eq!(memory.relocate_memory(), Ok(()));
2295
2296 check_memory!(
2298 memory,
2299 ((0, 0), (5, 13)),
2300 ((0, 1), (5, 14)),
2301 ((0, 2), (5, 10)),
2302 ((5, 10), 7),
2303 ((5, 11), 8),
2304 ((5, 12), 9),
2305 ((5, 13), 100),
2306 ((5, 14), 200)
2307 );
2308 assert!(memory.temp_data.is_empty());
2309 }
2310
2311 #[test]
2312 #[cfg(feature = "extensive_hints")]
2313 fn relocate_memory_temp_chain_to_int_multi_hop() {
2314 let mut memory = Memory::new();
2315
2316 memory.temp_data = vec![
2320 vec![MemoryCell::new(mayberelocatable!(123))],
2321 vec![MemoryCell::new(mayberelocatable!(456))],
2322 ];
2323
2324 memory.relocation_rules.insert(
2329 0,
2330 MaybeRelocatable::RelocatableValue(Relocatable::from((-2, 0))),
2331 );
2332 memory
2333 .relocation_rules
2334 .insert(1, MaybeRelocatable::Int(Felt252::from(99)));
2335
2336 memory
2339 .data
2340 .push(vec![MemoryCell::new(mayberelocatable!(-1, 0))]);
2341
2342 assert_eq!(memory.relocate_memory(), Ok(()));
2343
2344 assert_eq!(
2346 memory.data[0][0].get_value(),
2347 Some(MaybeRelocatable::Int(Felt252::from(99)))
2348 );
2349
2350 assert!(memory.temp_data.is_empty());
2352 }
2353
2354 #[test]
2355 fn add_validation_rule_out_of_order_no_shift_and_correct_validation() {
2356 let mut memory = Memory::new();
2357 memory.data.resize(4, Vec::new());
2358
2359 memory
2360 .insert_value(Relocatable::from((3, 0)), Felt252::from(3))
2361 .unwrap();
2362 memory
2363 .insert_value(Relocatable::from((1, 0)), Felt252::from(1))
2364 .unwrap();
2365
2366 let rule_seg3 = ValidationRule(Box::new(
2367 |memory: &Memory, addr: Relocatable| -> Result<Vec<Relocatable>, MemoryError> {
2368 memory.get_integer(addr)?;
2369 Ok(vec![addr])
2370 },
2371 ));
2372 let rule_seg1 = ValidationRule(Box::new(
2373 |memory: &Memory, addr: Relocatable| -> Result<Vec<Relocatable>, MemoryError> {
2374 memory.get_integer(addr)?;
2375 Ok(vec![addr])
2376 },
2377 ));
2378
2379 memory.add_validation_rule(3, rule_seg3);
2380 memory.add_validation_rule(1, rule_seg1);
2381
2382 assert!(memory.validation_rules[3].is_some());
2383 assert!(memory.validation_rules[1].is_some());
2384
2385 assert_eq!(memory.validate_existing_memory(), Ok(()));
2386 assert!(memory
2387 .validated_addresses
2388 .contains(&Relocatable::from((3, 0))));
2389 assert!(memory
2390 .validated_addresses
2391 .contains(&Relocatable::from((1, 0))));
2392 }
2393}