Merge pull request #133 from gavofyork/evm_stack_fix

Single array for logs output.
This commit is contained in:
Arkadiy Paronyan 2016-01-16 17:29:01 +01:00
commit 1d53d806b2
2 changed files with 33 additions and 16 deletions

View File

@ -516,6 +516,8 @@ pub const LOG2: Instruction = 0xa2;
pub const LOG3: Instruction = 0xa3; pub const LOG3: Instruction = 0xa3;
/// Makes a log entry; 4 topics. /// Makes a log entry; 4 topics.
pub const LOG4: Instruction = 0xa4; pub const LOG4: Instruction = 0xa4;
/// Maximal number of topics for log instructions
pub const MAX_NO_OF_TOPICS : usize = 4;
/// create a new account with associated code /// create a new account with associated code
pub const CREATE: Instruction = 0xf0; pub const CREATE: Instruction = 0xf0;

View File

@ -5,6 +5,7 @@ use evm;
use super::instructions as instructions; use super::instructions as instructions;
use super::instructions::Instruction; use super::instructions::Instruction;
use std::num::wrapping::OverflowingOps; use std::num::wrapping::OverflowingOps;
use std::marker::Copy;
#[cfg(feature = "evm_debug")] #[cfg(feature = "evm_debug")]
macro_rules! evm_debug { macro_rules! evm_debug {
@ -39,30 +40,44 @@ trait Stack<T> {
fn has(&self, no_of_elems: usize) -> bool; fn has(&self, no_of_elems: usize) -> bool;
/// Get element from top and remove it from Stack. Panics if stack is empty. /// Get element from top and remove it from Stack. Panics if stack is empty.
fn pop_back(&mut self) -> T; fn pop_back(&mut self) -> T;
/// Get elements from top and remove them from Stack. Panics if stack is empty. /// Get (up to `instructions::MAX_NO_OF_TOPICS`) elements from top and remove them from Stack. Panics if stack is empty.
fn pop_n(&mut self, no_of_elems: usize) -> Vec<T>; fn pop_n(&mut self, no_of_elems: usize) -> &[T];
/// Add element on top of the Stack /// Add element on top of the Stack
fn push(&mut self, elem: T); fn push(&mut self, elem: T);
/// Get number of elements on Stack /// Get number of elements on Stack
fn size(&self) -> usize; fn size(&self) -> usize;
} }
impl<S : fmt::Display> Stack<S> for Vec<S> { struct VecStack<S> {
stack: Vec<S>,
logs: [S; instructions::MAX_NO_OF_TOPICS]
}
impl<S : Copy> VecStack<S> {
fn with_capacity(capacity: usize, zero: S) -> Self {
VecStack {
stack: Vec::with_capacity(capacity),
logs: [zero; instructions::MAX_NO_OF_TOPICS]
}
}
}
impl<S : fmt::Display> Stack<S> for VecStack<S> {
fn peek(&self, no_from_top: usize) -> &S { fn peek(&self, no_from_top: usize) -> &S {
return &self[self.len() - no_from_top - 1]; return &self.stack[self.stack.len() - no_from_top - 1];
} }
fn swap_with_top(&mut self, no_from_top: usize) { fn swap_with_top(&mut self, no_from_top: usize) {
let len = self.len(); let len = self.stack.len();
self.swap(len - no_from_top - 1, len - 1); self.stack.swap(len - no_from_top - 1, len - 1);
} }
fn has(&self, no_of_elems: usize) -> bool { fn has(&self, no_of_elems: usize) -> bool {
self.len() >= no_of_elems self.stack.len() >= no_of_elems
} }
fn pop_back(&mut self) -> S { fn pop_back(&mut self) -> S {
let val = self.pop(); let val = self.stack.pop();
match val { match val {
Some(x) => { Some(x) => {
evm_debug!({ evm_debug!({
@ -74,24 +89,24 @@ impl<S : fmt::Display> Stack<S> for Vec<S> {
} }
} }
fn pop_n(&mut self, no_of_elems: usize) -> Vec<S> { fn pop_n(&mut self, no_of_elems: usize) -> &[S] {
let mut vec = Vec::new(); assert!(no_of_elems <= instructions::MAX_NO_OF_TOPICS);
for _i in 1..no_of_elems+1 { for i in 0..no_of_elems {
vec.push(self.pop_back()); self.logs[i] = self.pop_back();
} }
vec &self.logs[0..no_of_elems]
} }
fn push(&mut self, elem: S) { fn push(&mut self, elem: S) {
evm_debug!({ evm_debug!({
format!(" PUSH: {}", elem) format!(" PUSH: {}", elem)
}); });
self.push(elem); self.stack.push(elem);
} }
fn size(&self) -> usize { fn size(&self) -> usize {
self.len() self.stack.len()
} }
} }
@ -246,7 +261,7 @@ impl evm::Evm for Interpreter {
let valid_jump_destinations = self.find_jump_destinations(&code); let valid_jump_destinations = self.find_jump_destinations(&code);
let mut current_gas = params.gas.clone(); let mut current_gas = params.gas.clone();
let mut stack = Vec::with_capacity(ext.schedule().stack_limit); let mut stack = VecStack::with_capacity(ext.schedule().stack_limit, U256::zero());
let mut mem = vec![]; let mut mem = vec![];
let mut reader = CodeReader { let mut reader = CodeReader {
position: 0, position: 0,