Skip to content

Commit

Permalink
implements STOP opcode
Browse files Browse the repository at this point in the history
  • Loading branch information
0xys committed Mar 27, 2022
1 parent e29e5e0 commit 5513d55
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 49 deletions.
79 changes: 38 additions & 41 deletions src/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::host::Host;
use crate::executor::callstack::{
CallStack, CallScope, ExecutionContext
};
use crate::interpreter::{CallParams, CallKind};
use crate::interpreter::{CallParams, CallKind, ExitKind};
use crate::interpreter::stack::{Calldata};
use crate::interpreter::{
Interrupt,
Expand Down Expand Up @@ -38,6 +38,7 @@ const MAX_CODE_SIZE: usize = 0x6000;
const SUCCESS: bool = true;
const FAILED: bool = false;


impl Executor {
pub fn new(host: Rc<RefCell<dyn Host>>) -> Self {
Self {
Expand Down Expand Up @@ -198,49 +199,17 @@ impl Executor {
},
Ok(interrupt) => {
match interrupt {
Interrupt::Return(gas_left, data) => {
let child = match self.callstack.pop() {
None => panic!("pop from empty callstack is not allowed."),
Some(c) => c,
};
let child = child.borrow_mut();
if self.callstack.is_empty() {
Interrupt::Exit(gas_left, data, exit_kind) => {
if let Some(r) = self.exit_scope(&data, exit_kind) {
resume = r;
continue;
}else{
if exit_kind == ExitKind::Revert {
return Output::new_revert(gas_left, data);
}
let effective_refund = calc_effective_refund(scope.gas_limit, gas_left, exec_context.refund_counter, exec_context.num_of_selfdestruct, self.revision);
return Output::new_success(gas_left, exec_context.refund_counter, effective_refund, data);
}
let parent = self.callstack.peek();
let mut parent = parent.borrow_mut();

parent.memory.set_range(child.ret_offset, &data[..child.ret_size]);
parent.gas_left = parent.gas_left.saturating_add(child.gas_left); // refund unused gas

resume = Resume::Returned(SUCCESS);
continue;
},
Interrupt::Revert(gas_left, data) => {
let child = match self.callstack.pop() {
None => panic!("pop from empty callstack is not allowed."),
Some(c) => c,
};
let child = child.borrow_mut();
(*self.host).borrow_mut().rollback(child.snapshot); // revert the state to previous snapshot

if self.callstack.is_empty() {
return Output::new_revert(gas_left, data);
}
let parent = self.callstack.peek();
let mut parent = parent.borrow_mut();

parent.memory.set_range(child.ret_offset, &data[..child.ret_size]);
parent.gas_left = parent.gas_left.saturating_add(child.gas_left); // refund unused gas


resume = Resume::Returned(FAILED);
continue;
},
Interrupt::Stop(gas_left) => {
let effective_refund = calc_effective_refund(scope.gas_limit, gas_left, exec_context.refund_counter, exec_context.num_of_selfdestruct, self.revision);
return Output::new_success(gas_left, exec_context.refund_counter, effective_refund, Bytes::default());
},
Interrupt::Call(params) => {
match self.push_child_scope(&params) {
Expand All @@ -263,6 +232,34 @@ impl Executor {

}

fn exit_scope(&mut self, data: &Bytes, exit_kind: ExitKind) -> Option<Resume> {
let child = match self.callstack.pop() {
None => panic!("pop from empty callstack is not allowed."),
Some(c) => c,
};
let child = child.borrow_mut();

if exit_kind == ExitKind::Revert {
(*self.host).borrow_mut().rollback(child.snapshot); // revert the state to previous snapshot
}

if self.callstack.is_empty() {
return None;
}
let parent = self.callstack.peek();
let mut parent = parent.borrow_mut();

if exit_kind != ExitKind::Stop {
parent.memory.set_range(child.ret_offset, &data[..child.ret_size]);
}
parent.gas_left = parent.gas_left.saturating_add(child.gas_left); // refund unused gas

if exit_kind == ExitKind::Revert {
return Some(Resume::Returned(FAILED));
}
Some(Resume::Returned(SUCCESS))
}

pub fn execute_raw(&mut self, code: &Code) -> Output {
let mut scope = CallScope::default();
scope.code = code.clone();
Expand Down
11 changes: 6 additions & 5 deletions src/interpreter/interpreter.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use bytes::Bytes;
use ethereum_types::{
U256, U512
};
Expand Down Expand Up @@ -33,7 +34,7 @@ use crate::utils::{
address_to_u256, u256_to_address,
};

use super::{CallParams, CallKind};
use super::{CallParams, CallKind, ExitKind};

#[derive(Clone, Debug)]
pub struct Interpreter {
Expand Down Expand Up @@ -82,7 +83,7 @@ impl Interpreter {

let op_byte = match scope.code.0.get(scope.pc) {
Some(num) => *num,
None => return Ok(Interrupt::Stop(scope.gas_left))
None => return Ok(Interrupt::Exit(scope.gas_left, Bytes::default(), ExitKind::Stop))
};

if let Some(opcode) = OpCode::from_u8(op_byte) {
Expand Down Expand Up @@ -156,7 +157,7 @@ impl Interpreter {

match opcode {
OpCode::STOP => {
Ok(Some(Interrupt::Stop(scope.gas_left)))
Ok(Some(Interrupt::Exit(scope.gas_left, Bytes::default(), ExitKind::Stop)))
},
OpCode::ADD => {
Self::consume_constant_gas(&mut scope.gas_left, 3)?;
Expand Down Expand Up @@ -1078,7 +1079,7 @@ impl Interpreter {
let (gas_consumed, data) = ret(offset, size, memory, scope.gas_left)?;
scope.gas_left -= gas_consumed;
exec_context.return_data_buffer = data.clone();
Ok(Some(Interrupt::Return(scope.gas_left, data)))
Ok(Some(Interrupt::Exit(scope.gas_left, data, ExitKind::Return)))
},

OpCode::DELEGATECALL => {
Expand Down Expand Up @@ -1141,7 +1142,7 @@ impl Interpreter {
let (gas_consumed, data) = ret(offset, size, memory, scope.gas_left)?;
scope.gas_left -= gas_consumed;
exec_context.return_data_buffer = data.clone();
Ok(Some(Interrupt::Revert(scope.gas_left, data)))
Ok(Some(Interrupt::Exit(scope.gas_left, data, ExitKind::Revert)))
},

// OpCode::INVALID => {
Expand Down
14 changes: 11 additions & 3 deletions src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,17 @@ pub enum Interrupt {

Call(CallParams),

Return(i64, Bytes),
Stop(i64),
Revert(i64, Bytes),
Exit(i64, Bytes, ExitKind),
// Return(i64, Bytes),
// Stop(i64),
// Revert(i64, Bytes),
}

#[derive(Clone, Debug, PartialEq, Copy)]
pub enum ExitKind {
Stop,
Return,
Revert,
}

pub enum Resume {
Expand Down

0 comments on commit 5513d55

Please sign in to comment.