diff --git a/src/evm/instructions.rs b/src/evm/instructions.rs index 4325ae0fc..78b111342 100644 --- a/src/evm/instructions.rs +++ b/src/evm/instructions.rs @@ -380,6 +380,7 @@ pub const LOG1: Instruction = 0xa1; //< Makes a log entry; 1 topic. pub const LOG2: Instruction = 0xa2; //< Makes a log entry; 2 topics. pub const LOG3: Instruction = 0xa3; //< Makes a log entry; 3 topics. pub const LOG4: Instruction = 0xa4; //< Makes a log entry; 4 topics. +pub const NO_OF_LOG_INSTRUCTIONS : usize = 5; pub const CREATE: Instruction = 0xf0; //< create a new account with associated code pub const CALL: Instruction = 0xf1; //< message-call into an account diff --git a/src/evm/interpreter.rs b/src/evm/interpreter.rs index 02fbdc06d..fe4f039ef 100644 --- a/src/evm/interpreter.rs +++ b/src/evm/interpreter.rs @@ -5,6 +5,7 @@ use evm; use super::instructions as instructions; use super::instructions::Instruction; use std::num::wrapping::OverflowingOps; +use std::marker::Copy; #[cfg(feature = "evm_debug")] macro_rules! evm_debug { @@ -39,29 +40,45 @@ trait Stack { fn has(&self, no_of_elems: usize) -> bool; /// Get element from top and remove it from Stack. Panics if stack is empty. fn pop_back(&mut self) -> T; - /// Get elements from top and remove them from Stack. Panics if stack is empty. - fn pop_n(&mut self, no_of_elems: usize) -> Vec; + /// Get (up to 5) elements from top and remove them from Stack. Panics if stack is empty. + fn pop_n(&mut self, no_of_elems: usize) -> &[T]; /// Add element on top of the Stack fn push(&mut self, elem: T); /// Get number of elements on Stack fn size(&self) -> usize; } -impl Stack for Vec { + +struct VecStack { + stack: Vec, + logs: [S; instructions::NO_OF_LOG_INSTRUCTIONS] +} + +impl VecStack { + fn with_capacity(capacity: usize, zero: S) -> Self { + VecStack { + stack: Vec::with_capacity(capacity), + logs: [zero; instructions::NO_OF_LOG_INSTRUCTIONS] + } + } +} + +impl Stack for VecStack { + 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) { - let len = self.len(); - self.swap(len - no_from_top - 1, len - 1); + let len = self.stack.len(); + self.stack.swap(len - no_from_top - 1, len - 1); } 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 { - let val = self.pop(); + let val = self.stack.pop(); match val { Some(x) => { evm_debug!({ @@ -73,24 +90,24 @@ impl Stack for Vec { } } - fn pop_n(&mut self, no_of_elems: usize) -> Vec { - let mut vec = Vec::new(); + fn pop_n(&mut self, no_of_elems: usize) -> &[S] { + assert!(no_of_elems < instructions::NO_OF_LOG_INSTRUCTIONS); - for _i in 1..no_of_elems+1 { - vec.push(self.pop_back()); + for i in 0..no_of_elems { + self.logs[i] = self.pop_back(); } - vec + &self.logs[0..no_of_elems] } fn push(&mut self, elem: S) { evm_debug!({ format!(" PUSH: {}", elem) }); - self.push(elem); + self.stack.push(elem); } fn size(&self) -> usize { - self.len() + self.stack.len() } } @@ -244,7 +261,7 @@ impl evm::Evm for Interpreter { let valid_jump_destinations = self.find_jump_destinations(&code); 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 reader = CodeReader { position: 0,