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

fix: increment pc post-opcode execution #955

Merged
merged 6 commits into from
Sep 18, 2024
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
28 changes: 10 additions & 18 deletions crates/evm/src/instructions/memory_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -188,21 +188,17 @@ pub impl MemoryOperation of MemoryOperationTrait {
/// The new pc target has to be a JUMPDEST opcode.
/// # Specification: https://www.evm.codes/#57?fork=shanghai
fn exec_jumpi(ref self: VM) -> Result<(), EVMError> {
self.charge_gas(gas::HIGH)?;
let index = self.stack.pop_usize()?;
let b = self.stack.pop()?;

// Peek the value so we don't need to push it back again in case we want to call `exec_jump`
let b = self.stack.peek_at(1)?;
self.charge_gas(gas::HIGH)?;

if b != 0x0 {
let index = self.stack.pop_usize()?;
jump(ref self, index)?;
// counter would have been already popped by `exec_jump`
// so we just remove `b`
self.stack.pop()?;
} else {
// remove both `value` and `b`
self.stack.pop()?;
self.stack.pop()?;
// Return with a PC incremented by one - as JUMP and JUMPi increments
// are skipped in the main `execute_code` loop
self.set_pc(self.pc() + 1);
obatirou marked this conversation as resolved.
Show resolved Hide resolved
}

Result::Ok(())
Expand Down Expand Up @@ -709,10 +705,8 @@ mod tests {

// Then
let pc = vm.pc();
// ideally we should assert that it incremented, but incrementing is done by
// `decode_and_execute`
// so we can assume that will be done
assert(pc == old_pc, 'PC should be same');
// If the jump is not taken, the PC should be incremented by 1
assert_eq!(pc, old_pc + 1);
}

#[test]
Expand Down Expand Up @@ -754,10 +748,8 @@ mod tests {

// Then
let pc = vm.pc();
// ideally we should assert that it incremented, but incrementing is done by
// `decode_and_execute`
// so we can assume that will be done
assert(pc == old_pc, 'PC should be same');
// If the jump is not taken, the PC should be incremented by 1
assert_eq!(pc, old_pc + 1);
}

#[test]
Expand Down
6 changes: 5 additions & 1 deletion crates/evm/src/instructions/push_operations.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use utils::helpers::U8SpanExTrait;
fn exec_push_i(ref self: VM, i: u8) -> Result<(), EVMError> {
self.charge_gas(gas::VERYLOW)?;
let i = i.into();
let data = self.read_code(i);
let args_pc = self.pc() + 1; // PUSH_N Arguments begin at pc + 1
let data = self.read_code(args_pc, i);

self.set_pc(self.pc() + i);

Expand Down Expand Up @@ -328,8 +329,11 @@ mod tests {
}
}

/// Get a span of 0xFF bytes of length n preceded by a 0x00 byte
/// to account for the argument offset in push operations
fn get_n_0xFF(mut n: u8) -> Span<u8> {
let mut array: Array<u8> = ArrayTrait::new();
array.append(0x00);
while n != 0 {
array.append(0xFF);
n -= 1;
Expand Down
7 changes: 5 additions & 2 deletions crates/evm/src/interpreter.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -334,11 +334,14 @@ pub impl EVMImpl of EVMTrait {
}

let opcode: u8 = *bytecode.at(pc);
// Increment pc
vm.set_pc(pc + 1);

match Self::execute_opcode(ref vm, opcode) {
Result::Ok(_) => {
if opcode != 0x56 && opcode != 0x57 {
// Increment pc if not a JUMP family opcode
vm.set_pc(vm.pc() + 1);
}
obatirou marked this conversation as resolved.
Show resolved Hide resolved

if vm.is_running() {
return Self::execute_code(ref vm);
}
Expand Down
12 changes: 6 additions & 6 deletions crates/evm/src/model/vm.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -130,20 +130,20 @@ pub impl VMImpl of VMTrait {
self.accessed_storage_keys.spanset()
}

/// Reads and returns data from bytecode starting at the current program counter.
/// Reads and returns data from bytecode starting at the provided pc.
///
/// # Arguments
///
/// * `self` - The `VM` instance to read the data from.
/// * `pc` - The starting position in the bytecode to read from.
/// * `len` - The length of the data to read from the bytecode.
///
/// # Returns
///
/// * A `Span<u8>` containing the requested bytecode slice.
/// * If the requested slice extends beyond the code length, returns remaining bytes.
#[inline(always)]
fn read_code(self: @VM, len: usize) -> Span<u8> {
let pc = self.pc();
fn read_code(self: @VM, pc: usize, len: usize) -> Span<u8> {
let code_len = self.message().code.len();

// If pc is out of bounds, return an empty span
Expand Down Expand Up @@ -239,7 +239,7 @@ mod tests {
let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build();
vm.set_pc(1);

let read_code = vm.read_code(3);
let read_code = vm.read_code(vm.pc(), 3);

assert_eq!(read_code, [0x02, 0x03, 0x04].span());
assert_eq!(vm.pc(), 1);
Expand All @@ -251,7 +251,7 @@ mod tests {
let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build();
vm.set_pc(2);

let read_code = vm.read_code(2);
let read_code = vm.read_code(vm.pc(), 3);

assert_eq!(read_code, [0x03].span());
assert_eq!(vm.pc(), 2);
Expand All @@ -263,7 +263,7 @@ mod tests {
let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build();
vm.set_pc(3);

let read_code = vm.read_code(2);
let read_code = vm.read_code(vm.pc(), 3);

assert_eq!(read_code, [0x04, 0x05].span());
assert_eq!(vm.pc(), 3);
Expand Down
Loading