Skip to content

Commit

Permalink
add get_u32_range to impl VirtualMachine add get_u32 and get_u32_rang…
Browse files Browse the repository at this point in the history
…e to impl Memory
  • Loading branch information
ohad-nir-starkware committed Feb 11, 2025
1 parent dfd3f66 commit e5c96eb
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 1 deletion.
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
3 changes: 2 additions & 1 deletion vm/src/vm/decoding/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub fn decode_instruction(encoded_instr: u64) -> Result<Instruction, VirtualMach

// Flags start on the 48th bit.
const FLAGS_OFFSET: u64 = 48;
const FLAGS_MASK: u64 = 0x7FFF;
const OFF0_OFF: u64 = 0;
const OFF1_OFF: u64 = 16;
const OFF2_OFF: u64 = 32;
Expand All @@ -42,7 +43,7 @@ pub fn decode_instruction(encoded_instr: u64) -> Result<Instruction, VirtualMach
let off2 = decode_offset(encoded_instr >> OFF2_OFF & OFFX_MASK);

// Grab flags
let flags = encoded_instr >> FLAGS_OFFSET;
let flags = (encoded_instr >> FLAGS_OFFSET) & FLAGS_MASK;
// Grab individual flags
let dst_reg_num = (flags & DST_REG_MASK) >> DST_REG_OFF;
let op0_reg_num = (flags & OP0_REG_MASK) >> OP0_REG_OFF;
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)
);
}

#[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

0 comments on commit e5c96eb

Please sign in to comment.