1use crate::stdlib::{borrow::Cow, collections::HashMap, fmt, prelude::*};
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)]
40#[repr(align(32))]
41pub(crate) struct MemoryCell([u64; 4]);
42
43impl MemoryCell {
44 pub const NONE_MASK: u64 = 1 << 63;
45 pub const ACCESS_MASK: u64 = 1 << 62;
46 pub const RELOCATABLE_MASK: u64 = 1 << 61;
47 pub const NONE: Self = Self([Self::NONE_MASK, 0, 0, 0]);
48
49 pub fn new(value: MaybeRelocatable) -> Self {
50 value.into()
51 }
52
53 pub fn is_none(&self) -> bool {
54 self.0[0] & Self::NONE_MASK == Self::NONE_MASK
55 }
56
57 pub fn is_some(&self) -> bool {
58 !self.is_none()
59 }
60
61 pub fn mark_accessed(&mut self) {
62 self.0[0] |= Self::ACCESS_MASK;
63 }
64
65 pub fn is_accessed(&self) -> bool {
66 self.0[0] & Self::ACCESS_MASK == Self::ACCESS_MASK
67 }
68
69 pub fn get_value(&self) -> Option<MaybeRelocatable> {
70 self.is_some().then(|| (*self).into())
71 }
72}
73
74impl From<MaybeRelocatable> for MemoryCell {
75 fn from(value: MaybeRelocatable) -> Self {
76 match value {
77 MaybeRelocatable::Int(x) => Self(x.to_raw()),
78 MaybeRelocatable::RelocatableValue(x) => Self([
79 Self::RELOCATABLE_MASK,
80 0,
81 usize::from_ne_bytes(x.segment_index.to_ne_bytes()) as u64,
83 x.offset as u64,
84 ]),
85 }
86 }
87}
88
89impl From<MemoryCell> for MaybeRelocatable {
90 fn from(cell: MemoryCell) -> Self {
91 debug_assert!(cell.is_some());
92 let flags = cell.0[0];
93 match flags & MemoryCell::RELOCATABLE_MASK {
94 MemoryCell::RELOCATABLE_MASK => Self::from((
95 isize::from_ne_bytes((cell.0[2] as usize).to_ne_bytes()),
97 cell.0[3] as usize,
98 )),
99 _ => {
100 let mut value = cell.0;
101 value[0] &= 0x0fffffffffffffff;
103 Self::Int(Felt252::from_raw(value))
104 }
105 }
106 }
107}
108
109pub struct AddressSet(Vec<bv::BitVec>);
110
111impl AddressSet {
112 pub(crate) fn new() -> Self {
113 Self(Vec::new())
114 }
115
116 pub(crate) fn contains(&self, addr: &Relocatable) -> bool {
117 let segment = addr.segment_index;
118 if segment.is_negative() {
119 return false;
120 }
121
122 self.0
123 .get(segment as usize)
124 .and_then(|segment| segment.get(addr.offset))
125 .map(|bit| *bit)
126 .unwrap_or(false)
127 }
128
129 pub(crate) fn extend(&mut self, addresses: &[Relocatable]) {
130 for addr in addresses {
131 let segment = addr.segment_index;
132 if segment.is_negative() {
133 continue;
134 }
135 let segment = segment as usize;
136 if segment >= self.0.len() {
137 self.0.resize(segment + 1, bv::BitVec::new());
138 }
139
140 let offset = addr.offset;
141 if offset >= self.0[segment].len() {
142 self.0[segment].resize(offset + 1, false);
143 }
144 self.0[segment].replace(offset, true);
145 }
146 }
147}
148
149#[cfg(test)]
150impl AddressSet {
151 pub(crate) fn len(&self) -> usize {
152 self.0
153 .iter()
154 .map(|segment| segment.iter().map(|bit| *bit as usize).sum::<usize>())
155 .sum()
156 }
157}
158
159pub struct Memory {
160 pub(crate) data: Vec<Vec<MemoryCell>>,
161 pub(crate) temp_data: Vec<Vec<MemoryCell>>,
162 #[cfg(not(feature = "extensive_hints"))]
165 pub(crate) relocation_rules: HashMap<usize, Relocatable>,
166 #[cfg(feature = "extensive_hints")]
167 pub(crate) relocation_rules: HashMap<usize, MaybeRelocatable>,
168 pub validated_addresses: AddressSet,
169 validation_rules: Vec<Option<ValidationRule>>,
170}
171
172impl Memory {
173 pub fn new() -> Memory {
174 Memory {
175 data: Vec::new(),
176 temp_data: Vec::new(),
177 relocation_rules: HashMap::new(),
178 validated_addresses: AddressSet::new(),
179 validation_rules: Vec::with_capacity(7),
180 }
181 }
182
183 pub fn insert<V>(&mut self, key: Relocatable, val: V) -> Result<(), MemoryError>
188 where
189 MaybeRelocatable: From<V>,
190 {
191 let val = MaybeRelocatable::from(val);
192 let (value_index, value_offset) = from_relocatable_to_indexes(key);
193
194 let data = if key.segment_index.is_negative() {
195 &mut self.temp_data
196 } else {
197 &mut self.data
198 };
199
200 let data_len = data.len();
201 let segment = data
202 .get_mut(value_index)
203 .ok_or_else(|| MemoryError::UnallocatedSegment(Box::new((value_index, data_len))))?;
204
205 let (len, capacity) = (segment.len(), segment.capacity());
208 if len <= value_offset {
209 let new_len = value_offset
210 .checked_add(1)
211 .ok_or(MemoryError::VecCapacityExceeded)?;
212 segment
213 .try_reserve(new_len.saturating_sub(capacity))
214 .map_err(|_| MemoryError::VecCapacityExceeded)?;
215 segment.resize(new_len, MemoryCell::NONE);
216 }
217 match segment[value_offset].get_value() {
220 None => segment[value_offset] = MemoryCell::new(val),
221 Some(current_cell) => {
222 if current_cell != val {
223 return Err(MemoryError::InconsistentMemory(Box::new((
225 key,
226 current_cell,
227 val,
228 ))));
229 }
230 }
231 };
232 self.validate_memory_cell(key)
233 }
234
235 pub(crate) fn get<'a, 'b: 'a, K: 'a>(&'b self, key: &'a K) -> Option<Cow<MaybeRelocatable>>
237 where
238 Relocatable: TryFrom<&'a K>,
239 {
240 let relocatable: Relocatable = key.try_into().ok()?;
241
242 let data = if relocatable.segment_index.is_negative() {
243 &self.temp_data
244 } else {
245 &self.data
246 };
247 let (i, j) = from_relocatable_to_indexes(relocatable);
248 let value = data.get(i)?.get(j)?.get_value()?;
249 Some(Cow::Owned(self.relocate_value(&value).ok()?.into_owned()))
250 }
251
252 #[cfg(not(feature = "extensive_hints"))]
254 fn relocate_address(
255 addr: Relocatable,
256 relocation_rules: &HashMap<usize, Relocatable>,
257 ) -> Result<MaybeRelocatable, MemoryError> {
258 if addr.segment_index < 0 {
259 if let Some(x) = relocation_rules.get(&(-(addr.segment_index + 1) as usize)) {
262 return Ok((*x + addr.offset)?.into());
263 }
264 }
265 Ok(addr.into())
266 }
267 #[cfg(feature = "extensive_hints")]
268 fn relocate_address(
269 addr: Relocatable,
270 relocation_rules: &HashMap<usize, MaybeRelocatable>,
271 ) -> Result<MaybeRelocatable, MemoryError> {
272 if addr.segment_index < 0 {
273 if let Some(x) = relocation_rules.get(&(-(addr.segment_index + 1) as usize)) {
276 return Ok(match x {
277 MaybeRelocatable::RelocatableValue(r) => (*r + addr.offset)?.into(),
278 MaybeRelocatable::Int(i) => i.into(),
279 });
280 }
281 }
282 Ok(addr.into())
283 }
284
285 pub fn relocate_memory(&mut self) -> Result<(), MemoryError> {
287 if self.relocation_rules.is_empty() || self.temp_data.is_empty() {
288 return Ok(());
289 }
290 for segment in self.data.iter_mut().chain(self.temp_data.iter_mut()) {
292 for cell in segment.iter_mut() {
293 let value = cell.get_value();
294 match value {
295 Some(MaybeRelocatable::RelocatableValue(addr)) if addr.segment_index < 0 => {
296 let mut new_cell = MemoryCell::new(Memory::relocate_address(
297 addr,
298 &self.relocation_rules,
299 )?);
300 if cell.is_accessed() {
301 new_cell.mark_accessed();
302 }
303 *cell = new_cell;
304 }
305 _ => {}
306 }
307 }
308 }
309 for index in (0..self.temp_data.len()).rev() {
311 if let Some(base_addr) = self.relocation_rules.get(&index) {
312 let data_segment = self.temp_data.remove(index);
313
314 #[cfg(feature = "extensive_hints")]
315 let base_addr = match base_addr {
316 MaybeRelocatable::RelocatableValue(addr) => addr,
317 MaybeRelocatable::Int(_) => {
318 continue;
319 }
320 };
321
322 let mut addr = *base_addr;
324 if let Some(s) = self.data.get_mut(addr.segment_index as usize) {
325 s.reserve_exact(data_segment.len())
326 }
327 for cell in data_segment {
328 if let Some(v) = cell.get_value() {
329 self.insert(addr, v)?;
331 if cell.is_accessed() {
333 self.mark_as_accessed(addr)
334 }
335 }
336 addr = (addr + 1)?;
337 }
338 }
339 }
340 self.relocation_rules.clear();
341 Ok(())
342 }
343 #[cfg(not(feature = "extensive_hints"))]
354 pub(crate) fn add_relocation_rule(
355 &mut self,
356 src_ptr: Relocatable,
357 dst_ptr: Relocatable,
358 ) -> Result<(), MemoryError> {
359 if src_ptr.segment_index >= 0 {
360 return Err(MemoryError::AddressNotInTemporarySegment(
361 src_ptr.segment_index,
362 ));
363 }
364 if src_ptr.offset != 0 {
365 return Err(MemoryError::NonZeroOffset(src_ptr.offset));
366 }
367
368 let segment_index = -(src_ptr.segment_index + 1) as usize;
371 if self.relocation_rules.contains_key(&segment_index) {
372 return Err(MemoryError::DuplicatedRelocation(src_ptr.segment_index));
373 }
374
375 self.relocation_rules.insert(segment_index, dst_ptr);
376 Ok(())
377 }
378 #[cfg(feature = "extensive_hints")]
379 pub(crate) fn add_relocation_rule(
380 &mut self,
381 src_ptr: Relocatable,
382 dst: MaybeRelocatable,
383 ) -> Result<(), MemoryError> {
384 if src_ptr.segment_index >= 0 {
385 return Err(MemoryError::AddressNotInTemporarySegment(
386 src_ptr.segment_index,
387 ));
388 }
389 if src_ptr.offset != 0 {
390 return Err(MemoryError::NonZeroOffset(src_ptr.offset));
391 }
392
393 let segment_index = -(src_ptr.segment_index + 1) as usize;
396 if self.relocation_rules.contains_key(&segment_index) {
397 return Err(MemoryError::DuplicatedRelocation(src_ptr.segment_index));
398 }
399
400 self.relocation_rules.insert(segment_index, dst);
401 Ok(())
402 }
403
404 pub fn get_integer(&self, key: Relocatable) -> Result<Cow<Felt252>, MemoryError> {
407 match self
408 .get(&key)
409 .ok_or_else(|| MemoryError::UnknownMemoryCell(Box::new(key)))?
410 {
411 Cow::Borrowed(MaybeRelocatable::Int(int)) => Ok(Cow::Borrowed(int)),
412 Cow::Owned(MaybeRelocatable::Int(int)) => Ok(Cow::Owned(int)),
413 _ => Err(MemoryError::ExpectedInteger(Box::new(key))),
414 }
415 }
416
417 pub fn get_u32(&self, key: Relocatable) -> Result<u32, MemoryError> {
420 let felt = self.get_integer(key)?.into_owned();
421 felt.to_u32()
422 .ok_or_else(|| MemoryError::Math(MathError::Felt252ToU32Conversion(Box::new(felt))))
423 }
424
425 pub fn get_usize(&self, key: Relocatable) -> Result<usize, MemoryError> {
428 let felt = self.get_integer(key)?.into_owned();
429 felt.to_usize()
430 .ok_or_else(|| MemoryError::Math(MathError::Felt252ToUsizeConversion(Box::new(felt))))
431 }
432
433 pub fn get_relocatable(&self, key: Relocatable) -> Result<Relocatable, MemoryError> {
436 match self
437 .get(&key)
438 .ok_or_else(|| MemoryError::UnknownMemoryCell(Box::new(key)))?
439 {
440 Cow::Borrowed(MaybeRelocatable::RelocatableValue(rel)) => Ok(*rel),
441 Cow::Owned(MaybeRelocatable::RelocatableValue(rel)) => Ok(rel),
442 _ => Err(MemoryError::ExpectedRelocatable(Box::new(key))),
443 }
444 }
445
446 pub fn insert_value<T: Into<MaybeRelocatable>>(
449 &mut self,
450 key: Relocatable,
451 val: T,
452 ) -> Result<(), MemoryError> {
453 self.insert(key, &val.into())
454 }
455
456 pub fn add_validation_rule(&mut self, segment_index: usize, rule: ValidationRule) {
457 if segment_index >= self.validation_rules.len() {
458 self.validation_rules
460 .resize_with(segment_index + 1, || None);
461 }
462 self.validation_rules.insert(segment_index, Some(rule));
463 }
464
465 fn validate_memory_cell(&mut self, addr: Relocatable) -> Result<(), MemoryError> {
466 if let Some(Some(rule)) = addr
467 .segment_index
468 .to_usize()
469 .and_then(|x| self.validation_rules.get(x))
470 {
471 if !self.validated_addresses.contains(&addr) {
472 self.validated_addresses
473 .extend(rule.0(self, addr)?.as_slice());
474 }
475 }
476 Ok(())
477 }
478
479 pub fn validate_existing_memory(&mut self) -> Result<(), MemoryError> {
481 for (index, rule) in self.validation_rules.iter().enumerate() {
482 if index >= self.data.len() {
483 continue;
484 }
485 let Some(rule) = rule else {
486 continue;
487 };
488 for offset in 0..self.data[index].len() {
489 let addr = Relocatable::from((index as isize, offset));
490 if !self.validated_addresses.contains(&addr) {
491 self.validated_addresses
492 .extend(rule.0(self, addr)?.as_slice());
493 }
494 }
495 }
496 Ok(())
497 }
498
499 pub(crate) fn memcmp(
508 &self,
509 lhs: Relocatable,
510 rhs: Relocatable,
511 len: usize,
512 ) -> (Ordering, usize) {
513 let get_segment = |idx: isize| {
514 if idx.is_negative() {
515 self.temp_data.get(-(idx + 1) as usize)
516 } else {
517 self.data.get(idx as usize)
518 }
519 };
520 match (
521 get_segment(lhs.segment_index),
522 get_segment(rhs.segment_index),
523 ) {
524 (None, None) => {
525 return (Ordering::Equal, 0);
526 }
527 (Some(_), None) => {
528 return (Ordering::Greater, 0);
529 }
530 (None, Some(_)) => {
531 return (Ordering::Less, 0);
532 }
533 (Some(lhs_segment), Some(rhs_segment)) => {
534 let (lhs_start, rhs_start) = (lhs.offset, rhs.offset);
535 for i in 0..len {
536 let (lhs, rhs) = (
537 lhs_segment.get(lhs_start + i),
538 rhs_segment.get(rhs_start + i),
539 );
540 let ord = lhs.cmp(&rhs);
541 if ord == Ordering::Equal {
542 continue;
543 }
544 return (ord, i);
545 }
546 }
547 };
548 (Ordering::Equal, len)
549 }
550
551 pub(crate) fn mem_eq(&self, lhs: Relocatable, rhs: Relocatable, len: usize) -> bool {
560 if lhs == rhs {
561 return true;
562 }
563 let get_segment = |idx: isize| {
564 if idx.is_negative() {
565 self.temp_data.get(-(idx + 1) as usize)
566 } else {
567 self.data.get(idx as usize)
568 }
569 };
570 match (
571 get_segment(lhs.segment_index).and_then(|s| s.get(lhs.offset..)),
572 get_segment(rhs.segment_index).and_then(|s| s.get(rhs.offset..)),
573 ) {
574 (Some(lhs), Some(rhs)) => {
575 let (lhs_len, rhs_len) = (lhs.len().min(len), rhs.len().min(len));
576 if lhs_len != rhs_len {
577 return false;
578 }
579 lhs[..lhs_len] == rhs[..rhs_len]
580 }
581 (None, None) => true,
582 _ => false,
583 }
584 }
585
586 pub fn get_range(&self, addr: Relocatable, size: usize) -> Vec<Option<Cow<MaybeRelocatable>>> {
589 let mut values = Vec::new();
590
591 for i in 0..size {
592 values.push((addr + i).ok().and_then(|x| self.get(&x)));
593 }
594
595 values
596 }
597
598 pub fn get_continuous_range(
601 &self,
602 addr: Relocatable,
603 size: usize,
604 ) -> Result<Vec<MaybeRelocatable>, MemoryError> {
605 let mut values = Vec::with_capacity(size);
606
607 for i in 0..size {
608 values.push(match self.get(&(addr + i)?) {
609 Some(elem) => elem.into_owned(),
610 None => return Err(MemoryError::GetRangeMemoryGap(Box::new((addr, size)))),
611 });
612 }
613
614 Ok(values)
615 }
616
617 pub fn get_integer_range(
621 &self,
622 addr: Relocatable,
623 size: usize,
624 ) -> Result<Vec<Cow<Felt252>>, MemoryError> {
625 let mut values = Vec::new();
626
627 for i in 0..size {
628 values.push(self.get_integer((addr + i)?)?);
629 }
630
631 Ok(values)
632 }
633
634 pub fn get_u32_range(&self, addr: Relocatable, size: usize) -> Result<Vec<u32>, MemoryError> {
637 let mut values = Vec::new();
638
639 for i in 0..size {
640 values.push(self.get_u32((addr + i)?)?);
641 }
642
643 Ok(values)
644 }
645
646 pub fn mark_as_accessed(&mut self, addr: Relocatable) {
647 let (i, j) = from_relocatable_to_indexes(addr);
648 let data = if addr.segment_index < 0 {
649 &mut self.temp_data
650 } else {
651 &mut self.data
652 };
653 let cell = data.get_mut(i).and_then(|x| x.get_mut(j));
654 if let Some(cell) = cell {
655 cell.mark_accessed()
656 }
657 }
658
659 pub fn get_amount_of_accessed_addresses_for_segment(
660 &self,
661 segment_index: usize,
662 ) -> Option<usize> {
663 let segment = self.data.get(segment_index)?;
664 Some(
665 segment
666 .iter()
667 .filter(|x| x.is_some() && x.is_accessed())
668 .count(),
669 )
670 }
671
672 pub(crate) fn insert_as_accessed<V>(
675 &mut self,
676 key: Relocatable,
677 val: V,
678 ) -> Result<(), MemoryError>
679 where
680 MaybeRelocatable: From<V>,
681 {
682 self.insert(key, val)?;
683 self.mark_as_accessed(key);
684 Ok(())
685 }
686}
687
688impl From<&Memory> for CairoPieMemory {
689 fn from(mem: &Memory) -> CairoPieMemory {
690 let mut pie_memory = Vec::default();
691 for (i, segment) in mem.data.iter().enumerate() {
692 for (j, cell) in segment.iter().enumerate() {
693 if let Some(value) = cell.get_value() {
694 pie_memory.push(((i, j), value))
695 }
696 }
697 }
698 CairoPieMemory(pie_memory)
699 }
700}
701
702impl fmt::Display for Memory {
703 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
704 for (i, segment) in self.temp_data.iter().enumerate() {
705 for (j, cell) in segment.iter().enumerate() {
706 if let Some(elem) = cell.get_value() {
707 let temp_segment = i + 1;
708 writeln!(f, "(-{temp_segment},{j}) : {elem}")?;
709 }
710 }
711 }
712 for (i, segment) in self.data.iter().enumerate() {
713 for (j, cell) in segment.iter().enumerate() {
714 if let Some(elem) = cell.get_value() {
715 writeln!(f, "({i},{j}) : {elem}")?;
716 }
717 }
718 }
719 Ok(())
720 }
721}
722
723pub(crate) trait RelocateValue<'a, Input: 'a, Output: 'a> {
725 fn relocate_value(&self, value: Input) -> Result<Output, MemoryError>;
726}
727
728#[cfg(not(feature = "extensive_hints"))]
729impl RelocateValue<'_, Relocatable, Relocatable> for Memory {
730 fn relocate_value(&self, addr: Relocatable) -> Result<Relocatable, MemoryError> {
731 if addr.segment_index < 0 {
732 if let Some(x) = self
735 .relocation_rules
736 .get(&(-(addr.segment_index + 1) as usize))
737 {
738 return (*x + addr.offset).map_err(MemoryError::Math);
739 }
740 }
741 Ok(addr)
742 }
743}
744#[cfg(feature = "extensive_hints")]
745impl RelocateValue<'_, Relocatable, MaybeRelocatable> for Memory {
746 fn relocate_value(&self, addr: Relocatable) -> Result<MaybeRelocatable, MemoryError> {
747 if addr.segment_index < 0 {
748 if let Some(x) = self
751 .relocation_rules
752 .get(&(-(addr.segment_index + 1) as usize))
753 {
754 return Ok(match x {
755 MaybeRelocatable::RelocatableValue(r) => {
756 (*r + addr.offset).map_err(MemoryError::Math)?.into()
757 }
758 MaybeRelocatable::Int(i) => i.into(),
759 });
760 }
761 }
762 Ok(addr.into())
763 }
764}
765
766impl<'a> RelocateValue<'a, &'a Felt252, &'a Felt252> for Memory {
767 fn relocate_value(&self, value: &'a Felt252) -> Result<&'a Felt252, MemoryError> {
768 Ok(value)
769 }
770}
771
772impl<'a> RelocateValue<'a, &'a MaybeRelocatable, Cow<'a, MaybeRelocatable>> for Memory {
773 fn relocate_value(
774 &self,
775 value: &'a MaybeRelocatable,
776 ) -> Result<Cow<'a, MaybeRelocatable>, MemoryError> {
777 Ok(match value {
778 MaybeRelocatable::Int(_) => Cow::Borrowed(value),
779 MaybeRelocatable::RelocatableValue(addr) => {
780 #[cfg(not(feature = "extensive_hints"))]
781 let v = self.relocate_value(*addr)?.into();
782 #[cfg(feature = "extensive_hints")]
783 let v = self.relocate_value(*addr)?;
784
785 Cow::Owned(v)
786 }
787 })
788 }
789}
790
791impl Default for Memory {
792 fn default() -> Self {
793 Self::new()
794 }
795}
796
797#[cfg(test)]
798mod memory_tests {
799
800 use super::*;
801 use crate::{
802 felt_hex, relocatable,
803 utils::test_utils::*,
804 vm::{
805 runners::builtin_runner::{
806 RangeCheckBuiltinRunner, SignatureBuiltinRunner, RC_N_PARTS_STANDARD,
807 },
808 vm_memory::memory_segments::MemorySegmentManager,
809 },
810 };
811 use assert_matches::assert_matches;
812
813 use crate::vm::errors::memory_errors::MemoryError;
814
815 use crate::utils::test_utils::memory_from_memory;
816 use crate::utils::test_utils::memory_inner;
817
818 #[cfg(target_arch = "wasm32")]
819 use wasm_bindgen_test::*;
820
821 #[test]
822 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
823 fn insert_and_get_succesful() {
824 let key = Relocatable::from((0, 0));
825 let val = MaybeRelocatable::from(Felt252::from(5_u64));
826 let mut memory = Memory::new();
827 memory.data.push(Vec::new());
828 memory.insert(key, &val).unwrap();
829 assert_eq!(
830 memory.get(&key).unwrap().as_ref(),
831 &MaybeRelocatable::from(Felt252::from(5_u64))
832 );
833 }
834
835 #[test]
836 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
837 fn get_valuef_from_temp_segment() {
838 let mut memory = Memory::new();
839 memory.temp_data = vec![vec![
840 MemoryCell::NONE,
841 MemoryCell::NONE,
842 MemoryCell::new(mayberelocatable!(8)),
843 ]];
844 assert_eq!(
845 memory.get(&mayberelocatable!(-1, 2)).unwrap().as_ref(),
846 &mayberelocatable!(8),
847 );
848 }
849
850 #[test]
851 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
852 fn insert_value_in_temp_segment() {
853 let key = Relocatable::from((-1, 3));
854 let val = MaybeRelocatable::from(Felt252::from(8_u64));
855 let mut memory = Memory::new();
856 memory.temp_data.push(Vec::new());
857 memory.insert(key, &val).unwrap();
858 assert_eq!(
859 memory.temp_data[0][3],
860 MemoryCell::new(MaybeRelocatable::from(Felt252::from(8_u64)))
861 );
862 }
863
864 #[test]
865 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
866 fn insert_and_get_from_temp_segment_succesful() {
867 let key = Relocatable::from((-1, 0));
868 let val = MaybeRelocatable::from(Felt252::from(5_u64));
869 let mut memory = Memory::new();
870 memory.temp_data.push(Vec::new());
871 memory.insert(key, &val).unwrap();
872 assert_eq!(
873 memory.get(&key).unwrap().as_ref(),
874 &MaybeRelocatable::from(Felt252::from(5_u64)),
875 );
876 }
877
878 #[test]
879 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
880 fn insert_and_get_from_temp_segment_failed() {
881 let key = relocatable!(-1, 1);
882 let mut memory = Memory::new();
883 memory.temp_data = vec![vec![
884 MemoryCell::NONE,
885 MemoryCell::new(mayberelocatable!(8)),
886 ]];
887 assert_eq!(
888 memory.insert(key, &mayberelocatable!(5)),
889 Err(MemoryError::InconsistentMemory(Box::new((
890 relocatable!(-1, 1),
891 mayberelocatable!(8),
892 mayberelocatable!(5)
893 ))))
894 );
895 }
896
897 #[test]
898 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
899 fn get_non_allocated_memory() {
900 let key = Relocatable::from((0, 0));
901 let memory = Memory::new();
902 assert_eq!(memory.get(&key), None);
903 }
904
905 #[test]
906 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
907 fn get_non_existant_element() {
908 let key = Relocatable::from((0, 0));
909 let memory = Memory::new();
910 assert_eq!(memory.get(&key), None);
911 }
912
913 #[test]
914 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
915 fn insert_non_allocated_memory() {
916 let key = Relocatable::from((0, 0));
917 let val = MaybeRelocatable::from(Felt252::from(5_u64));
918 let mut memory = Memory::new();
919 let error = memory.insert(key, &val);
920 assert_eq!(
921 error,
922 Err(MemoryError::UnallocatedSegment(Box::new((0, 0))))
923 );
924 }
925
926 #[test]
927 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
928 fn insert_inconsistent_memory() {
929 let key = Relocatable::from((0, 0));
930 let val_a = MaybeRelocatable::from(Felt252::from(5_u64));
931 let val_b = MaybeRelocatable::from(Felt252::from(6_u64));
932 let mut memory = Memory::new();
933 memory.data.push(Vec::new());
934 memory
935 .insert(key, &val_a)
936 .expect("Unexpected memory insert fail");
937 let error = memory.insert(key, &val_b);
938 assert_eq!(
939 error,
940 Err(MemoryError::InconsistentMemory(Box::new((
941 key, val_a, val_b
942 ))))
943 );
944 }
945
946 #[test]
947 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
948 fn insert_non_contiguous_element() {
949 let key_a = Relocatable::from((0, 0));
950 let key_b = Relocatable::from((0, 2));
951 let val = MaybeRelocatable::from(Felt252::from(5_u64));
952 let mut memory = Memory::new();
953 memory.data.push(Vec::new());
954 memory.insert(key_a, &val).unwrap();
955 memory.insert(key_b, &val).unwrap();
956 assert_eq!(memory.get(&key_b).unwrap().as_ref(), &val);
957 }
958
959 #[test]
960 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
961 fn insert_non_contiguous_element_memory_gaps_none() {
962 let key_a = Relocatable::from((0, 0));
963 let key_b = Relocatable::from((0, 5));
964 let val = MaybeRelocatable::from(Felt252::from(5_u64));
965 let mut memory = Memory::new();
966 memory.data.push(Vec::new());
967 memory.insert(key_a, &val).unwrap();
968 memory.insert(key_b, &val).unwrap();
969 assert_eq!(memory.get(&key_b).unwrap().as_ref(), &val);
970 assert_eq!(memory.get(&MaybeRelocatable::from((0, 1))), None);
971 assert_eq!(memory.get(&MaybeRelocatable::from((0, 2))), None);
972 assert_eq!(memory.get(&MaybeRelocatable::from((0, 3))), None);
973 assert_eq!(memory.get(&MaybeRelocatable::from((0, 4))), None);
974 }
975
976 #[test]
977 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
978 fn validate_existing_memory_for_range_check_within_bounds() {
979 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
980 let mut segments = MemorySegmentManager::new();
981 builtin.initialize_segments(&mut segments);
982 builtin.add_validation_rule(&mut segments.memory);
983 for _ in 0..3 {
984 segments.add();
985 }
986
987 segments
988 .memory
989 .insert(
990 Relocatable::from((0, 0)),
991 &MaybeRelocatable::from(Felt252::from(45_u64)),
992 )
993 .unwrap();
994 segments.memory.validate_existing_memory().unwrap();
995 assert!(segments
996 .memory
997 .validated_addresses
998 .contains(&Relocatable::from((0, 0))));
999 }
1000
1001 #[test]
1002 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1003 fn validate_existing_memory_for_range_check_outside_bounds() {
1004 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
1005 let mut segments = MemorySegmentManager::new();
1006 segments.add();
1007 builtin.initialize_segments(&mut segments);
1008 segments
1009 .memory
1010 .insert(
1011 Relocatable::from((1, 0)),
1012 &MaybeRelocatable::from(Felt252::from(-10)),
1013 )
1014 .unwrap();
1015 builtin.add_validation_rule(&mut segments.memory);
1016 let error = segments.memory.validate_existing_memory();
1017 assert_eq!(
1018 error,
1019 Err(MemoryError::RangeCheckNumOutOfBounds(Box::new((
1020 Felt252::from(-10),
1021 Felt252::TWO.pow(128_u128)
1022 ))))
1023 );
1024 }
1025
1026 #[test]
1027 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1028 fn validate_existing_memory_for_invalid_signature() {
1029 let mut builtin = SignatureBuiltinRunner::new(Some(512), true);
1030 let mut segments = MemorySegmentManager::new();
1031 builtin.initialize_segments(&mut segments);
1032 segments.memory = memory![
1033 (
1034 (0, 0),
1035 (
1036 "874739451078007766457464989774322083649278607533249481151382481072868806602",
1037 10
1038 )
1039 ),
1040 (
1041 (0, 1),
1042 (
1043 "-1472574760335685482768423018116732869320670550222259018541069375211356613248",
1044 10
1045 )
1046 )
1047 ];
1048 builtin.add_validation_rule(&mut segments.memory);
1049 let error = segments.memory.validate_existing_memory();
1050 assert_eq!(
1051 error,
1052 Err(MemoryError::SignatureNotFound(Box::new((0, 0).into())))
1053 );
1054 }
1055
1056 #[test]
1057 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1058 fn validate_existing_memory_for_valid_signature() {
1059 let mut builtin = SignatureBuiltinRunner::new(Some(512), true);
1060
1061 let signature_r =
1062 felt_hex!("0x411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b20");
1063 let signature_s =
1064 felt_hex!("0x405c3191ab3883ef2b763af35bc5f5d15b3b4e99461d70e84c654a351a7c81b");
1065
1066 builtin
1067 .add_signature(Relocatable::from((1, 0)), &(signature_r, signature_s))
1068 .unwrap();
1069
1070 let mut segments = MemorySegmentManager::new();
1071
1072 segments.memory = memory![
1073 (
1074 (1, 0),
1075 (
1076 "874739451078007766457464989774322083649278607533249481151382481072868806602",
1077 10
1078 )
1079 ),
1080 ((1, 1), 2)
1081 ];
1082
1083 builtin.initialize_segments(&mut segments);
1084
1085 builtin.add_validation_rule(&mut segments.memory);
1086
1087 let result = segments.memory.validate_existing_memory();
1088
1089 assert_eq!(result, Ok(()))
1090 }
1091
1092 #[test]
1093 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1094 fn validate_existing_memory_for_range_check_relocatable_value() {
1095 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
1096 let mut segments = MemorySegmentManager::new();
1097 builtin.initialize_segments(&mut segments);
1098 segments.memory = memory![((0, 0), (0, 4))];
1099 builtin.add_validation_rule(&mut segments.memory);
1100 let error = segments.memory.validate_existing_memory();
1101 assert_eq!(
1102 error,
1103 Err(MemoryError::RangeCheckFoundNonInt(Box::new(relocatable!(
1104 0, 0
1105 ))))
1106 );
1107 }
1108
1109 #[test]
1110 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1111 fn validate_existing_memory_for_range_check_out_of_bounds_diff_segment() {
1112 let mut builtin = RangeCheckBuiltinRunner::<RC_N_PARTS_STANDARD>::new(Some(8), true);
1113 let mut segments = MemorySegmentManager::new();
1114 segments.memory = Memory::new();
1115 segments.add();
1116 builtin.initialize_segments(&mut segments);
1117 segments
1118 .memory
1119 .insert(
1120 Relocatable::from((0, 0)),
1121 &MaybeRelocatable::from(Felt252::from(-45_i128)),
1122 )
1123 .unwrap();
1124 builtin.add_validation_rule(&mut segments.memory);
1125 assert_eq!(segments.memory.validate_existing_memory(), Ok(()));
1126 }
1127
1128 #[test]
1129 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1130 fn get_integer_valid() {
1131 let memory = memory![((0, 0), 10)];
1132 assert_eq!(
1133 memory
1134 .get_integer(Relocatable::from((0, 0)))
1135 .unwrap()
1136 .as_ref(),
1137 &Felt252::from(10)
1138 );
1139 }
1140
1141 #[test]
1142 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1143 fn get_integer_invalid_expected_integer() {
1144 let mut segments = MemorySegmentManager::new();
1145 segments.add();
1146 segments
1147 .memory
1148 .insert(Relocatable::from((0, 0)), &MaybeRelocatable::from((0, 10)))
1149 .unwrap();
1150 assert_matches!(
1151 segments.memory.get_integer(Relocatable::from((0, 0))),
1152 Err(MemoryError::ExpectedInteger(
1153 bx
1154 )) if *bx == Relocatable::from((0, 0))
1155 );
1156 }
1157
1158 #[test]
1159 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1160 fn get_u32_too_big() {
1161 let mut segments = MemorySegmentManager::new();
1162 segments.add();
1163 segments
1164 .memory
1165 .insert(Relocatable::from((0, 0)), &Felt252::from(1_u64 << 32))
1166 .unwrap();
1167 assert_matches!(
1168 segments.memory.get_u32(Relocatable::from((0, 0))),
1169 Err(MemoryError::Math(MathError::Felt252ToU32Conversion(
1170 bx
1171 ))) if *bx == Felt252::from(1_u64 << 32)
1172 );
1173 }
1174
1175 #[test]
1176 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1177 fn default_memory() {
1178 let mem: Memory = Default::default();
1179 assert_eq!(mem.data.len(), 0);
1180 }
1181
1182 #[test]
1183 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1184 fn insert_and_get_temporary_succesful() {
1185 let mut memory = Memory::new();
1186 memory.temp_data.push(Vec::new());
1187
1188 let key = Relocatable::from((-1, 0));
1189 let val = MaybeRelocatable::from(Felt252::from(5));
1190 memory.insert(key, &val).unwrap();
1191
1192 assert_eq!(memory.get(&key).unwrap().as_ref(), &val);
1193 }
1194
1195 #[test]
1196 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1197 fn add_relocation_rule() {
1198 let mut memory = Memory::new();
1199
1200 assert_eq!(
1201 memory.add_relocation_rule((-1, 0).into(), (1, 2).into()),
1202 Ok(()),
1203 );
1204 assert_eq!(
1205 memory.add_relocation_rule((-2, 0).into(), (-1, 1).into()),
1206 Ok(()),
1207 );
1208 assert_eq!(
1209 memory.add_relocation_rule((5, 0).into(), (0, 0).into()),
1210 Err(MemoryError::AddressNotInTemporarySegment(5)),
1211 );
1212 assert_eq!(
1213 memory.add_relocation_rule((-3, 6).into(), (0, 0).into()),
1214 Err(MemoryError::NonZeroOffset(6)),
1215 );
1216 assert_eq!(
1217 memory.add_relocation_rule((-1, 0).into(), (0, 0).into()),
1218 Err(MemoryError::DuplicatedRelocation(-1)),
1219 );
1220 }
1221
1222 #[test]
1223 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1224 fn relocate_value_bigint() {
1225 let mut memory = Memory::new();
1226 memory
1227 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1228 .unwrap();
1229 memory
1230 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1231 .unwrap();
1232
1233 assert_eq!(
1235 memory
1236 .relocate_value(&MaybeRelocatable::Int(Felt252::from(0)))
1237 .unwrap(),
1238 Cow::Owned(MaybeRelocatable::Int(Felt252::from(0))),
1239 );
1240 }
1241
1242 #[test]
1243 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1244 fn relocate_value_mayberelocatable() {
1245 let mut memory = Memory::new();
1246 memory
1247 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1248 .unwrap();
1249 memory
1250 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1251 .unwrap();
1252
1253 assert_eq!(
1255 memory
1256 .relocate_value(&MaybeRelocatable::RelocatableValue((0, 0).into()))
1257 .unwrap(),
1258 Cow::Owned(MaybeRelocatable::RelocatableValue((0, 0).into())),
1259 );
1260 assert_eq!(
1261 memory
1262 .relocate_value(&MaybeRelocatable::RelocatableValue((5, 0).into()))
1263 .unwrap(),
1264 Cow::Owned(MaybeRelocatable::RelocatableValue((5, 0).into())),
1265 );
1266 }
1267
1268 #[test]
1269 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1270 fn relocate_value_mayberelocatable_temporary_segment_no_rules() {
1271 let mut memory = Memory::new();
1272 memory
1273 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1274 .unwrap();
1275 memory
1276 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1277 .unwrap();
1278
1279 assert_eq!(
1282 memory
1283 .relocate_value(&MaybeRelocatable::RelocatableValue((-5, 0).into()))
1284 .unwrap(),
1285 Cow::Owned(MaybeRelocatable::RelocatableValue((-5, 0).into())),
1286 );
1287 }
1288
1289 #[test]
1290 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1291 fn relocate_value_mayberelocatable_temporary_segment_rules() {
1292 let mut memory = Memory::new();
1293 memory
1294 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1295 .unwrap();
1296 memory
1297 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1298 .unwrap();
1299
1300 assert_eq!(
1303 memory
1304 .relocate_value(&MaybeRelocatable::RelocatableValue((-1, 0).into()))
1305 .unwrap(),
1306 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 0).into())),
1307 );
1308 assert_eq!(
1309 memory
1310 .relocate_value(&MaybeRelocatable::RelocatableValue((-2, 0).into()))
1311 .unwrap(),
1312 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 2).into())),
1313 );
1314 assert_eq!(
1315 memory
1316 .relocate_value(&MaybeRelocatable::RelocatableValue((-1, 5).into()))
1317 .unwrap(),
1318 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 5).into())),
1319 );
1320 assert_eq!(
1321 memory
1322 .relocate_value(&MaybeRelocatable::RelocatableValue((-2, 5).into()))
1323 .unwrap(),
1324 Cow::Owned(MaybeRelocatable::RelocatableValue((2, 7).into())),
1325 );
1326 }
1327
1328 #[test]
1329 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1330 fn get_range_for_continuous_memory() {
1331 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)];
1332
1333 let value1 = MaybeRelocatable::from(Felt252::from(2));
1334 let value2 = MaybeRelocatable::from(Felt252::from(3));
1335 let value3 = MaybeRelocatable::from(Felt252::from(4));
1336
1337 let expected_vec = vec![
1338 Some(Cow::Borrowed(&value1)),
1339 Some(Cow::Borrowed(&value2)),
1340 Some(Cow::Borrowed(&value3)),
1341 ];
1342 assert_eq!(memory.get_range(Relocatable::from((1, 0)), 3), expected_vec);
1343 }
1344
1345 #[test]
1346 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1347 fn get_range_for_non_continuous_memory() {
1348 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 3), 4)];
1349
1350 let value1 = MaybeRelocatable::from(Felt252::from(2));
1351 let value2 = MaybeRelocatable::from(Felt252::from(3));
1352 let value3 = MaybeRelocatable::from(Felt252::from(4));
1353
1354 let expected_vec = vec![
1355 Some(Cow::Borrowed(&value1)),
1356 Some(Cow::Borrowed(&value2)),
1357 None,
1358 Some(Cow::Borrowed(&value3)),
1359 ];
1360 assert_eq!(memory.get_range(Relocatable::from((1, 0)), 4), expected_vec);
1361 }
1362
1363 #[test]
1364 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1365 fn get_continuous_range_for_continuous_memory() {
1366 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 2), 4)];
1367
1368 let value1 = MaybeRelocatable::from(Felt252::from(2));
1369 let value2 = MaybeRelocatable::from(Felt252::from(3));
1370 let value3 = MaybeRelocatable::from(Felt252::from(4));
1371
1372 let expected_vec = vec![value1, value2, value3];
1373 assert_eq!(
1374 memory.get_continuous_range(Relocatable::from((1, 0)), 3),
1375 Ok(expected_vec)
1376 );
1377 }
1378
1379 #[test]
1380 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1381 fn get_continuous_range_for_non_continuous_memory() {
1382 let memory = memory![((1, 0), 2), ((1, 1), 3), ((1, 3), 4)];
1383
1384 assert_eq!(
1385 memory.get_continuous_range(Relocatable::from((1, 0)), 3),
1386 Err(MemoryError::GetRangeMemoryGap(Box::new(((1, 0).into(), 3))))
1387 );
1388 }
1389
1390 #[test]
1391 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1392 fn get_u32_range_ok() {
1393 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967295), ((0, 3), 3)];
1394 let expected_vector = vec![1, 4294967295];
1395 assert_eq!(memory.get_u32_range((0, 1).into(), 2), Ok(expected_vector));
1396 }
1397
1398 #[test]
1399 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1400 fn get_u32_range_relocatable() {
1401 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), (0, 0)), ((0, 3), 3)];
1402 assert_matches!(memory.get_u32_range((0, 1).into(), 2), Err(MemoryError::ExpectedInteger(bx)) if *bx == (0, 2).into());
1403 }
1404
1405 #[test]
1406 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1407 fn get_u32_range_over_32_bits() {
1408 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967296), ((0, 3), 3)];
1409 assert_matches!(memory.get_u32_range((0, 1).into(), 2), Err(MemoryError::Math(MathError::Felt252ToU32Conversion(bx))) if *bx == Felt252::from(4294967296_u64));
1410 }
1411
1412 #[test]
1413 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1414 fn get_u32_range_memory_gap() {
1415 let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 3), 3)];
1416 assert_matches!(memory.get_u32_range((0, 1).into(), 3), Err(MemoryError::UnknownMemoryCell(bx)) if *bx == (0, 2).into());
1417 }
1418
1419 #[test]
1421 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1422 fn relocate_memory_empty_relocation_rules() {
1423 let mut memory = memory![((0, 0), 1), ((0, 1), 2), ((0, 2), 3)];
1424
1425 assert_eq!(memory.relocate_memory(), Ok(()));
1426 check_memory!(memory, ((0, 0), 1), ((0, 1), 2), ((0, 2), 3));
1427 }
1428
1429 #[test]
1430 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1431 fn relocate_memory_new_segment_with_gap() {
1432 let mut memory = memory![
1433 ((0, 0), 1),
1434 ((0, 1), (-1, 0)),
1435 ((0, 2), 3),
1436 ((1, 0), (-1, 1)),
1437 ((1, 1), 5),
1438 ((1, 2), (-1, 2)),
1439 ((-1, 0), 7),
1440 ((-1, 1), 8),
1441 ((-1, 2), 9)
1442 ];
1443 memory
1444 .add_relocation_rule((-1, 0).into(), (2, 1).into())
1445 .unwrap();
1446 memory.data.push(vec![]);
1447
1448 assert_eq!(memory.relocate_memory(), Ok(()));
1449 check_memory!(
1450 memory,
1451 ((0, 0), 1),
1452 ((0, 1), (2, 1)),
1453 ((0, 2), 3),
1454 ((1, 0), (2, 2)),
1455 ((1, 1), 5),
1456 ((1, 2), (2, 3)),
1457 ((2, 1), 7),
1458 ((2, 2), 8),
1459 ((2, 3), 9)
1460 );
1461 assert!(memory.temp_data.is_empty());
1462 }
1463
1464 #[test]
1465 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1466 fn relocate_memory_new_segment() {
1467 let mut memory = memory![
1468 ((0, 0), 1),
1469 ((0, 1), (-1, 0)),
1470 ((0, 2), 3),
1471 ((1, 0), (-1, 1)),
1472 ((1, 1), 5),
1473 ((1, 2), (-1, 2)),
1474 ((-1, 0), 7),
1475 ((-1, 1), 8),
1476 ((-1, 2), 9)
1477 ];
1478 memory
1479 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1480 .unwrap();
1481 memory.data.push(vec![]);
1482
1483 assert_eq!(memory.relocate_memory(), Ok(()));
1484
1485 check_memory!(
1486 memory,
1487 ((0, 0), 1),
1488 ((0, 1), (2, 0)),
1489 ((0, 2), 3),
1490 ((1, 0), (2, 1)),
1491 ((1, 1), 5),
1492 ((1, 2), (2, 2)),
1493 ((2, 0), 7),
1494 ((2, 1), 8),
1495 ((2, 2), 9)
1496 );
1497 assert!(memory.temp_data.is_empty());
1498 }
1499
1500 #[test]
1501 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1502 fn relocate_memory_new_segment_unallocated() {
1503 let mut memory = memory![
1504 ((0, 0), 1),
1505 ((0, 1), (-1, 0)),
1506 ((0, 2), 3),
1507 ((1, 0), (-1, 1)),
1508 ((1, 1), 5),
1509 ((1, 2), (-1, 2)),
1510 ((-1, 0), 7),
1511 ((-1, 1), 8),
1512 ((-1, 2), 9)
1513 ];
1514 memory
1515 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1516 .unwrap();
1517
1518 assert_eq!(
1519 memory.relocate_memory(),
1520 Err(MemoryError::UnallocatedSegment(Box::new((2, 2))))
1521 );
1522 }
1523
1524 #[test]
1525 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1526 fn relocate_memory_into_existing_segment() {
1527 let mut memory = memory![
1528 ((0, 0), 1),
1529 ((0, 1), (-1, 0)),
1530 ((0, 2), 3),
1531 ((1, 0), (-1, 1)),
1532 ((1, 1), 5),
1533 ((1, 2), (-1, 2)),
1534 ((-1, 0), 7),
1535 ((-1, 1), 8),
1536 ((-1, 2), 9)
1537 ];
1538 memory
1539 .add_relocation_rule((-1, 0).into(), (1, 3).into())
1540 .unwrap();
1541
1542 assert_eq!(memory.relocate_memory(), Ok(()));
1543
1544 check_memory!(
1545 memory,
1546 ((0, 0), 1),
1547 ((0, 1), (1, 3)),
1548 ((0, 2), 3),
1549 ((1, 0), (1, 4)),
1550 ((1, 1), 5),
1551 ((1, 2), (1, 5)),
1552 ((1, 3), 7),
1553 ((1, 4), 8),
1554 ((1, 5), 9)
1555 );
1556 assert!(memory.temp_data.is_empty());
1557 }
1558
1559 #[test]
1560 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1561 fn relocate_memory_into_existing_segment_inconsistent_memory() {
1562 let mut memory = memory![
1563 ((0, 0), 1),
1564 ((0, 1), (-1, 0)),
1565 ((0, 2), 3),
1566 ((1, 0), (-1, 1)),
1567 ((1, 1), 5),
1568 ((1, 2), (-1, 2)),
1569 ((-1, 0), 7),
1570 ((-1, 1), 8),
1571 ((-1, 2), 9)
1572 ];
1573 memory
1574 .add_relocation_rule((-1, 0).into(), (1, 0).into())
1575 .unwrap();
1576
1577 assert_eq!(
1578 memory.relocate_memory(),
1579 Err(MemoryError::InconsistentMemory(Box::new((
1580 (1, 0).into(),
1581 (1, 1).into(),
1582 7.into(),
1583 ))))
1584 );
1585 }
1586
1587 #[test]
1588 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1589 fn relocate_memory_new_segment_2_temporary_segments_one_relocated() {
1590 let mut memory = memory![
1591 ((0, 0), 1),
1592 ((0, 1), (-1, 0)),
1593 ((0, 2), 3),
1594 ((1, 0), (-1, 1)),
1595 ((1, 1), 5),
1596 ((1, 2), (-1, 2)),
1597 ((-1, 0), 7),
1598 ((-1, 1), 8),
1599 ((-1, 2), 9),
1600 ((-2, 0), 10),
1601 ((-2, 1), 11)
1602 ];
1603 memory
1604 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1605 .unwrap();
1606 memory.data.push(vec![]);
1607
1608 assert_eq!(memory.relocate_memory(), Ok(()));
1609 check_memory!(
1610 memory,
1611 ((0, 0), 1),
1612 ((0, 1), (2, 0)),
1613 ((0, 2), 3),
1614 ((1, 0), (2, 1)),
1615 ((1, 1), 5),
1616 ((1, 2), (2, 2)),
1617 ((2, 0), 7),
1618 ((2, 1), 8),
1619 ((2, 2), 9),
1620 ((-1, 0), 10),
1621 ((-1, 1), 11)
1622 );
1623 }
1624
1625 #[test]
1626 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1627 fn relocate_memory_new_segment_2_temporary_segments_relocated() {
1628 let mut memory = memory![
1629 ((0, 0), 1),
1630 ((0, 1), (-1, 0)),
1631 ((0, 2), 3),
1632 ((1, 0), (-1, 1)),
1633 ((1, 1), 5),
1634 ((1, 2), (-1, 2)),
1635 ((-1, 0), 7),
1636 ((-1, 1), 8),
1637 ((-1, 2), 9),
1638 ((-2, 0), 10),
1639 ((-2, 1), 11)
1640 ];
1641 memory.data.push(vec![]);
1642 memory
1643 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1644 .unwrap();
1645 memory.data.push(vec![]);
1646 memory
1647 .add_relocation_rule((-2, 0).into(), (3, 0).into())
1648 .unwrap();
1649
1650 assert_eq!(memory.relocate_memory(), Ok(()));
1651
1652 check_memory!(
1653 memory,
1654 ((0, 0), 1),
1655 ((0, 1), (2, 0)),
1656 ((0, 2), 3),
1657 ((1, 0), (2, 1)),
1658 ((1, 1), 5),
1659 ((1, 2), (2, 2)),
1660 ((2, 0), 7),
1661 ((2, 1), 8),
1662 ((2, 2), 9),
1663 ((3, 0), 10),
1664 ((3, 1), 11)
1665 );
1666 assert!(memory.temp_data.is_empty());
1667 }
1668
1669 #[test]
1670 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1671 fn test_memory_display() {
1672 let memory = memory![
1673 ((0, 0), 1),
1674 ((0, 1), (-1, 0)),
1675 ((0, 2), 3),
1676 ((1, 0), (-1, 1)),
1677 ((1, 1), 5),
1678 ((1, 2), (-1, 2)),
1679 ((-1, 0), (-1, 0)),
1680 ((-1, 1), 8),
1681 ((-1, 2), 9)
1682 ];
1683
1684 assert_eq!(
1685 format!("{}", memory),
1686 "(-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");
1687 }
1688
1689 #[test]
1690 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1691 fn relocate_memory_into_existing_segment_temporary_values_in_temporary_memory() {
1692 let mut memory = memory![
1693 ((0, 0), 1),
1694 ((0, 1), (-1, 0)),
1695 ((0, 2), 3),
1696 ((1, 0), (-1, 1)),
1697 ((1, 1), 5),
1698 ((1, 2), (-1, 2)),
1699 ((-1, 0), (-1, 0)),
1700 ((-1, 1), 8),
1701 ((-1, 2), 9)
1702 ];
1703 memory
1704 .add_relocation_rule((-1, 0).into(), (1, 3).into())
1705 .unwrap();
1706
1707 assert_eq!(memory.relocate_memory(), Ok(()));
1708 check_memory!(
1709 memory,
1710 ((0, 0), 1),
1711 ((0, 1), (1, 3)),
1712 ((0, 2), 3),
1713 ((1, 0), (1, 4)),
1714 ((1, 1), 5),
1715 ((1, 2), (1, 5)),
1716 ((1, 3), (1, 3)),
1717 ((1, 4), 8),
1718 ((1, 5), 9)
1719 );
1720 assert!(memory.temp_data.is_empty());
1721 }
1722
1723 #[test]
1724 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1725 fn relocate_address_with_rules() {
1726 let mut memory = Memory::new();
1727 memory
1728 .add_relocation_rule((-1, 0).into(), (2, 0).into())
1729 .unwrap();
1730 memory
1731 .add_relocation_rule((-2, 0).into(), (2, 2).into())
1732 .unwrap();
1733
1734 assert_eq!(
1735 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1736 MaybeRelocatable::RelocatableValue((2, 0).into()),
1737 );
1738 assert_eq!(
1739 Memory::relocate_address((-2, 1).into(), &memory.relocation_rules).unwrap(),
1740 MaybeRelocatable::RelocatableValue((2, 3).into()),
1741 );
1742 }
1743
1744 #[test]
1745 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1746 fn relocate_address_no_rules() {
1747 let memory = Memory::new();
1748 assert_eq!(
1749 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1750 MaybeRelocatable::RelocatableValue((-1, 0).into()),
1751 );
1752 assert_eq!(
1753 Memory::relocate_address((-2, 1).into(), &memory.relocation_rules).unwrap(),
1754 MaybeRelocatable::RelocatableValue((-2, 1).into()),
1755 );
1756 }
1757
1758 #[test]
1759 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1760 fn relocate_address_real_addr() {
1761 let memory = Memory::new();
1762 assert_eq!(
1763 Memory::relocate_address((1, 0).into(), &memory.relocation_rules).unwrap(),
1764 MaybeRelocatable::RelocatableValue((1, 0).into()),
1765 );
1766 assert_eq!(
1767 Memory::relocate_address((1, 1).into(), &memory.relocation_rules).unwrap(),
1768 MaybeRelocatable::RelocatableValue((1, 1).into()),
1769 );
1770 }
1771
1772 #[test]
1773 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1774 #[cfg(feature = "extensive_hints")]
1775 fn relocate_address_to_integer() {
1776 let mut memory = Memory::new();
1777 memory
1778 .add_relocation_rule((-1, 0).into(), 0.into())
1779 .unwrap();
1780 memory
1781 .add_relocation_rule((-2, 0).into(), 42.into())
1782 .unwrap();
1783
1784 assert_eq!(
1785 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1786 MaybeRelocatable::Int(0.into()),
1787 );
1788 assert_eq!(
1789 Memory::relocate_address((-2, 0).into(), &memory.relocation_rules).unwrap(),
1790 MaybeRelocatable::Int(42.into()),
1791 );
1792 }
1793
1794 #[test]
1795 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1796 #[cfg(feature = "extensive_hints")]
1797 fn relocate_address_integer_no_duplicates() {
1798 let mut memory = Memory::new();
1799 memory
1800 .add_relocation_rule((-1, 0).into(), 1.into())
1801 .unwrap();
1802 assert_eq!(
1803 memory.add_relocation_rule((-1, 0).into(), 42.into()),
1804 Err(MemoryError::DuplicatedRelocation(-1))
1805 );
1806 assert_eq!(
1807 memory.add_relocation_rule((-1, 0).into(), (2, 0).into()),
1808 Err(MemoryError::DuplicatedRelocation(-1))
1809 );
1810
1811 assert_eq!(
1812 Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(),
1813 MaybeRelocatable::Int(1.into()),
1814 );
1815
1816 memory
1817 .add_relocation_rule((-2, 0).into(), (3, 0).into())
1818 .unwrap();
1819 assert_eq!(
1820 memory.add_relocation_rule((-2, 0).into(), 1.into()),
1821 Err(MemoryError::DuplicatedRelocation(-2))
1822 );
1823
1824 assert_eq!(
1825 Memory::relocate_address((-2, 0).into(), &memory.relocation_rules).unwrap(),
1826 MaybeRelocatable::RelocatableValue((3, 0).into()),
1827 );
1828 }
1829
1830 #[test]
1831 fn mark_address_as_accessed() {
1832 let mut memory = memory![((0, 0), 0)];
1833 assert!(!memory.data[0][0].is_accessed());
1834 memory.mark_as_accessed(relocatable!(0, 0));
1835 assert!(memory.data[0][0].is_accessed());
1836 }
1837
1838 #[test]
1839 fn get_amount_of_accessed_addresses_for_segment_valid() {
1840 let mut memory = memory![((0, 0), 0)];
1841 assert_eq!(
1842 memory.get_amount_of_accessed_addresses_for_segment(0),
1843 Some(0)
1844 );
1845 memory.mark_as_accessed(relocatable!(0, 0));
1846 assert_eq!(
1847 memory.get_amount_of_accessed_addresses_for_segment(0),
1848 Some(1)
1849 );
1850 }
1851
1852 #[test]
1853 fn get_amount_of_accessed_addresses_for_segment_invalid_segment() {
1854 let memory = memory![((0, 0), 0)];
1855 assert_eq!(memory.get_amount_of_accessed_addresses_for_segment(1), None);
1856 }
1857
1858 #[test]
1859 fn memory_cell_new_is_not_accessed() {
1860 let cell = MemoryCell::new(mayberelocatable!(1));
1861 assert!(!cell.is_accessed())
1862 }
1863
1864 #[test]
1865 fn memory_cell_mark_accessed() {
1866 let mut cell = MemoryCell::new(mayberelocatable!(1));
1867 cell.mark_accessed();
1868 assert!(cell.is_accessed())
1869 }
1870
1871 #[test]
1872 fn memory_cell_get_value() {
1873 let cell = MemoryCell::new(mayberelocatable!(1));
1874 assert_eq!(cell.get_value(), Some(mayberelocatable!(1)));
1875 }
1876
1877 use core::cmp::Ordering::*;
1878
1879 fn check_memcmp(
1880 lhs: (isize, usize),
1881 rhs: (isize, usize),
1882 len: usize,
1883 ord: Ordering,
1884 pos: usize,
1885 ) {
1886 let mem = memory![
1887 ((-2, 0), 1),
1888 ((-2, 1), (1, 1)),
1889 ((-2, 3), 0),
1890 ((-2, 4), 0),
1891 ((-1, 0), 1),
1892 ((-1, 1), (1, 1)),
1893 ((-1, 3), 0),
1894 ((-1, 4), 3),
1895 ((0, 0), 1),
1896 ((0, 1), (1, 1)),
1897 ((0, 3), 0),
1898 ((0, 4), 0),
1899 ((1, 0), 1),
1900 ((1, 1), (1, 1)),
1901 ((1, 3), 0),
1902 ((1, 4), 3)
1903 ];
1904 assert_eq!((ord, pos), mem.memcmp(lhs.into(), rhs.into(), len));
1905 }
1906
1907 #[test]
1908 fn insert_alloc_fails_gracefully() {
1909 let mut mem = memory![((0, 0), 1)];
1910 let err = mem.insert((0, usize::MAX >> 1).into(), Felt252::ONE);
1911 assert_eq!(err, Err(MemoryError::VecCapacityExceeded));
1912 }
1913
1914 #[test]
1915 fn insert_overflow_fails_gracefully() {
1916 let mut mem = memory![((0, 0), 1)];
1917 let err = mem.insert((0, usize::MAX).into(), Felt252::ONE);
1918 assert_eq!(err, Err(MemoryError::VecCapacityExceeded));
1919 }
1920
1921 #[test]
1922 fn memcmp() {
1923 check_memcmp((0, 0), (0, 0), 3, Equal, 3);
1924 check_memcmp((0, 0), (1, 0), 3, Equal, 3);
1925 check_memcmp((0, 0), (1, 0), 5, Less, 4);
1926 check_memcmp((1, 0), (0, 0), 5, Greater, 4);
1927 check_memcmp((2, 2), (2, 5), 8, Equal, 0);
1928 check_memcmp((0, 0), (2, 5), 8, Greater, 0);
1929 check_memcmp((2, 5), (0, 0), 8, Less, 0);
1930 check_memcmp((-2, 0), (-2, 0), 3, Equal, 3);
1931 check_memcmp((-2, 0), (-1, 0), 3, Equal, 3);
1932 check_memcmp((-2, 0), (-1, 0), 5, Less, 4);
1933 check_memcmp((-1, 0), (-2, 0), 5, Greater, 4);
1934 check_memcmp((-3, 2), (-3, 5), 8, Equal, 0);
1935 check_memcmp((-2, 0), (-3, 5), 8, Greater, 0);
1936 check_memcmp((-3, 5), (-2, 0), 8, Less, 0);
1937 }
1938
1939 #[test]
1940 fn cairo_pie_memory_from_memory() {
1941 let memory = memory![((8, 9), 3), ((1, 2), 5), ((7, 6), (1, 2))];
1942
1943 assert_eq!(
1944 CairoPieMemory::from(&memory),
1945 CairoPieMemory(vec![
1946 ((1, 2), MaybeRelocatable::from(5)),
1947 ((7, 6), MaybeRelocatable::from((1, 2))),
1948 ((8, 9), MaybeRelocatable::from(3))
1949 ])
1950 )
1951 }
1952}