Skip to content

Commit 9c699c9

Browse files
add get_u32_range to impl VirtualMachine add get_u32 and get_u32_range to impl Memory
1 parent aa3ec83 commit 9c699c9

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#### Upcoming Changes
44

5+
* 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)
6+
57
* feat: add the field `opcode_extension` to the structure of `Instruction` [#1933](https://github.com/lambdaclass/cairo-vm/pull/1933)
68

79
* fix(BREAKING): Fix no trace padding flow in proof mode [#1909](https://github.com/lambdaclass/cairo-vm/pull/1909)

vm/src/vm/decoding/decoder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub fn decode_instruction(encoded_instr: u64) -> Result<Instruction, VirtualMach
3131

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

4445
// Grab flags
45-
let flags = encoded_instr >> FLAGS_OFFSET;
46+
let flags = (encoded_instr >> FLAGS_OFFSET) & FLAGS_MASK;
4647
// Grab individual flags
4748
let dst_reg_num = (flags & DST_REG_MASK) >> DST_REG_OFF;
4849
let op0_reg_num = (flags & OP0_REG_MASK) >> OP0_REG_OFF;

vm/src/vm/vm_core.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,12 @@ impl VirtualMachine {
929929
self.segments.memory.get_integer_range(addr, size)
930930
}
931931

932+
/// Gets n u32 values from memory starting from addr (n being size).
933+
/// Returns an error if any of the values inside the range is missing (memory gap) or is not a u32.
934+
pub fn get_u32_range(&self, addr: Relocatable, size: usize) -> Result<Vec<u32>, MemoryError> {
935+
self.segments.memory.get_u32_range(addr, size)
936+
}
937+
932938
pub fn get_range_check_builtin(
933939
&self,
934940
) -> Result<&RangeCheckBuiltinRunner<RC_N_PARTS_STANDARD>, VirtualMachineError> {
@@ -4373,6 +4379,39 @@ mod tests {
43734379
);
43744380
}
43754381

4382+
#[test]
4383+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4384+
fn get_u32_range_ok() {
4385+
let mut vm = vm!();
4386+
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967295), ((0, 3), 3)];
4387+
let expected_vector = vec![1, 4294967295];
4388+
assert_eq!(vm.get_u32_range((0, 1).into(), 2), Ok(expected_vector));
4389+
}
4390+
4391+
#[test]
4392+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4393+
fn get_u32_range_relocatable() {
4394+
let mut vm = vm!();
4395+
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), (0, 0)), ((0, 3), 3)];
4396+
assert_matches!(vm.get_u32_range((0, 1).into(), 2), Err(MemoryError::ExpectedInteger(bx)) if *bx == (0, 2).into());
4397+
}
4398+
4399+
#[test]
4400+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4401+
fn get_u32_range_over_32_bits() {
4402+
let mut vm = vm!();
4403+
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 2), 4294967296), ((0, 3), 3)];
4404+
assert_matches!(vm.get_u32_range((0, 1).into(), 2), Err(MemoryError::Math(MathError::Felt252ToU32Conversion(bx))) if *bx == Felt252::from(4294967296_u64));
4405+
}
4406+
4407+
#[test]
4408+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
4409+
fn get_u32_range_memory_gap() {
4410+
let mut vm = vm!();
4411+
vm.segments.memory = memory![((0, 0), 0), ((0, 1), 1), ((0, 3), 3)];
4412+
assert_matches!(vm.get_u32_range((0, 1).into(), 3), Err(MemoryError::UnknownMemoryCell(bx)) if *bx == (0, 2).into());
4413+
}
4414+
43764415
#[test]
43774416
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
43784417
fn get_traceback_entries_bad_usort() {

vm/src/vm/vm_memory/memory.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,14 @@ impl Memory {
414414
}
415415
}
416416

417+
/// Gets a u32 value from memory address.
418+
/// Returns an Error if the value at the memory address is missing or not a u32.
419+
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+
417425
/// Gets the value from memory address as a usize.
418426
/// Returns an Error if the value at the memory address is missing not a Felt252, or can't be converted to usize.
419427
pub fn get_usize(&self, key: Relocatable) -> Result<usize, MemoryError> {
@@ -623,6 +631,18 @@ impl Memory {
623631
Ok(values)
624632
}
625633

634+
/// Gets a range of u32 memory values from addr to addr + size
635+
/// Fails if any of the values inside the range is missing (memory gap) or is not a u32
636+
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+
626646
pub fn mark_as_accessed(&mut self, addr: Relocatable) {
627647
let (i, j) = from_relocatable_to_indexes(addr);
628648
let data = if addr.segment_index < 0 {
@@ -1135,6 +1155,23 @@ mod memory_tests {
11351155
);
11361156
}
11371157

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+
11381175
#[test]
11391176
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
11401177
fn default_memory() {
@@ -1350,6 +1387,35 @@ mod memory_tests {
13501387
);
13511388
}
13521389

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+
13531419
/// Test that relocate_memory() works when there are no relocation rules.
13541420
#[test]
13551421
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]

0 commit comments

Comments
 (0)