Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add get_u32_range to impl VirtualMachine add get_u32 and get_u32_range to impl Memory #1936

Merged
merged 1 commit into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#### Upcoming Changes

* feat: add `get_u32_range` to `impl VirtualMachine` add `get_u32` and `get_u32_range` to `impl Memory` [#1936](https://github.com/lambdaclass/cairo-vm/pull/1936)

* feat: add the field `opcode_extension` to the structure of `Instruction` [#1933](https://github.com/lambdaclass/cairo-vm/pull/1933)

* fix(BREAKING): Fix no trace padding flow in proof mode [#1909](https://github.com/lambdaclass/cairo-vm/pull/1909)
Expand Down
39 changes: 39 additions & 0 deletions vm/src/vm/vm_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,12 @@ impl VirtualMachine {
self.segments.memory.get_integer_range(addr, size)
}

/// Gets n u32 values from memory starting from addr (n being size).
/// Returns an error if any of the values inside the range is missing (memory gap) or is not a u32.
pub fn get_u32_range(&self, addr: Relocatable, size: usize) -> Result<Vec<u32>, MemoryError> {
self.segments.memory.get_u32_range(addr, size)
}

pub fn get_range_check_builtin(
&self,
) -> Result<&RangeCheckBuiltinRunner<RC_N_PARTS_STANDARD>, VirtualMachineError> {
Expand Down Expand Up @@ -4373,6 +4379,39 @@ mod tests {
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_ok() {
let mut vm = vm!();
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967295), ((0, 3), 3)];
let expected_vector = vec![1, 4294967295];
assert_eq!(vm.get_u32_range((0, 1).into(), 2), Ok(expected_vector));
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_relocatable() {
let mut vm = vm!();
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), (0, 0)), ((0, 3), 3)];
assert_matches!(vm.get_u32_range((0, 1).into(), 2), Err(MemoryError::ExpectedInteger(bx)) if *bx == (0, 2).into());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_over_32_bits() {
let mut vm = vm!();
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967296), ((0, 3), 3)];
assert_matches!(vm.get_u32_range((0, 1).into(), 2), Err(MemoryError::Math(MathError::Felt252ToU32Conversion(bx))) if *bx == Felt252::from(4294967296_u64));
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_memory_gap() {
let mut vm = vm!();
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 3), 3)];
assert_matches!(vm.get_u32_range((0, 1).into(), 3), Err(MemoryError::UnknownMemoryCell(bx)) if *bx == (0, 2).into());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_traceback_entries_bad_usort() {
Expand Down
66 changes: 66 additions & 0 deletions vm/src/vm/vm_memory/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,14 @@ impl Memory {
}
}

/// Gets a u32 value from memory address.
/// Returns an Error if the value at the memory address is missing or not a u32.
pub fn get_u32(&self, key: Relocatable) -> Result<u32, MemoryError> {
let felt = self.get_integer(key)?.into_owned();
felt.to_u32()
.ok_or_else(|| MemoryError::Math(MathError::Felt252ToU32Conversion(Box::new(felt))))
}

/// Gets the value from memory address as a usize.
/// Returns an Error if the value at the memory address is missing not a Felt252, or can't be converted to usize.
pub fn get_usize(&self, key: Relocatable) -> Result<usize, MemoryError> {
Expand Down Expand Up @@ -623,6 +631,18 @@ impl Memory {
Ok(values)
}

/// Gets a range of u32 memory values from addr to addr + size
/// Fails if any of the values inside the range is missing (memory gap) or is not a u32
pub fn get_u32_range(&self, addr: Relocatable, size: usize) -> Result<Vec<u32>, MemoryError> {
let mut values = Vec::new();

for i in 0..size {
values.push(self.get_u32((addr + i)?)?);
}

Ok(values)
}

pub fn mark_as_accessed(&mut self, addr: Relocatable) {
let (i, j) = from_relocatable_to_indexes(addr);
let data = if addr.segment_index < 0 {
Expand Down Expand Up @@ -1135,6 +1155,23 @@ mod memory_tests {
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_too_big() {
let mut segments = MemorySegmentManager::new();
segments.add();
segments
.memory
.insert(Relocatable::from((0, 0)), &Felt252::from(1_u64 << 32))
.unwrap();
assert_matches!(
segments.memory.get_u32(Relocatable::from((0, 0))),
Err(MemoryError::Math(MathError::Felt252ToU32Conversion(
bx
))) if *bx == Felt252::from(1_u64 << 32)
);
}

Comment on lines +1158 to +1174
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add more test cases:

  • Happy paths
  • Memory gap inside the range passed to get_u32_range

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn default_memory() {
Expand Down Expand Up @@ -1350,6 +1387,35 @@ mod memory_tests {
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_ok() {
let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967295), ((0, 3), 3)];
let expected_vector = vec![1, 4294967295];
assert_eq!(memory.get_u32_range((0, 1).into(), 2), Ok(expected_vector));
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_relocatable() {
let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), (0, 0)), ((0, 3), 3)];
assert_matches!(memory.get_u32_range((0, 1).into(), 2), Err(MemoryError::ExpectedInteger(bx)) if *bx == (0, 2).into());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_over_32_bits() {
let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967296), ((0, 3), 3)];
assert_matches!(memory.get_u32_range((0, 1).into(), 2), Err(MemoryError::Math(MathError::Felt252ToU32Conversion(bx))) if *bx == Felt252::from(4294967296_u64));
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn get_u32_range_memory_gap() {
let memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 3), 3)];
assert_matches!(memory.get_u32_range((0, 1).into(), 3), Err(MemoryError::UnknownMemoryCell(bx)) if *bx == (0, 2).into());
}

/// Test that relocate_memory() works when there are no relocation rules.
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
Expand Down
Loading