diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 368851b7b..e8a318020 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -109,8 +109,6 @@ enum InstructionResult { Trap(TrapKind), } -enum Never {} - /// ActionParams without code, so that it can be feed into CodeReader. #[derive(Debug)] struct InterpreterParams { @@ -171,12 +169,6 @@ pub enum InterpreterResult { Trap(TrapKind), } -impl From for InterpreterResult { - fn from(error: vm::Error) -> InterpreterResult { - InterpreterResult::Done(Err(error)) - } -} - /// Intepreter EVM implementation pub struct Interpreter { mem: Vec, @@ -309,7 +301,7 @@ impl Interpreter { } else if self.reader.len() == 0 { InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_ref().expect("Gasometer None case is checked above; qed").current_gas.as_u256()))) } else { - self.step_inner(ext).err().expect("step_inner never returns Ok(()); qed") + self.step_inner(ext) }; if let &InterpreterResult::Done(_) = &result { @@ -321,7 +313,7 @@ impl Interpreter { /// Inner helper function for step. #[inline(always)] - fn step_inner(&mut self, ext: &mut dyn vm::Ext) -> Result { + fn step_inner(&mut self, ext: &mut dyn vm::Ext) -> InterpreterResult { let result = match self.resume_result.take() { Some(result) => result, None => { @@ -336,22 +328,28 @@ impl Interpreter { let instruction = match instruction { Some(i) => i, - None => return Err(InterpreterResult::Done(Err(vm::Error::BadInstruction { + None => return InterpreterResult::Done(Err(vm::Error::BadInstruction { instruction: opcode - }))), + })), }; let info = instruction.info(); self.last_stack_ret_len = info.ret; - self.verify_instruction(ext, instruction, info)?; + if let Err(e) = self.verify_instruction(ext, instruction, info) { + return InterpreterResult::Done(Err(e)); + }; // Calculate gas cost - let requirements = self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size())?; + let requirements = match self.gasometer.as_mut().expect(GASOMETER_PROOF).requirements(ext, instruction, info, &self.stack, self.mem.size()) { + Ok(t) => t, + Err(e) => return InterpreterResult::Done(Err(e)), + }; if self.do_trace { ext.trace_prepare_execute(self.reader.position - 1, opcode, requirements.gas_cost.as_u256(), Self::mem_written(instruction, &self.stack), Self::store_written(instruction, &self.stack)); } - - self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost)?; + if let Err(e) = self.gasometer.as_mut().expect(GASOMETER_PROOF).verify_gas(&requirements.gas_cost) { + return InterpreterResult::Done(Err(e)); + } self.mem.expand(requirements.memory_required_size); self.gasometer.as_mut().expect(GASOMETER_PROOF).current_mem_gas = requirements.memory_total_gas; self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas - requirements.gas_cost; @@ -360,18 +358,19 @@ impl Interpreter { // Execute instruction let current_gas = self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas; - let result = self.exec_instruction( + let result = match self.exec_instruction( current_gas, ext, instruction, requirements.provide_gas - )?; - + ) { + Err(x) => return InterpreterResult::Done(Err(x)), + Ok(x) => x, + }; evm_debug!({ self.informant.after_instruction(instruction) }); - result }, }; if let InstructionResult::Trap(trap) = result { - return Err(InterpreterResult::Trap(trap)); + return InterpreterResult::Trap(trap); } if let InstructionResult::UnusedGas(ref gas) = result { @@ -393,28 +392,31 @@ impl Interpreter { self.valid_jump_destinations = Some(self.cache.jump_destinations(&self.params.code_hash, &self.reader.code)); } let jump_destinations = self.valid_jump_destinations.as_ref().expect("jump_destinations are initialized on first jump; qed"); - let pos = self.verify_jump(position, jump_destinations)?; + let pos = match self.verify_jump(position, jump_destinations) { + Ok(x) => x, + Err(e) => return InterpreterResult::Done(Err(e)) + }; self.reader.position = pos; }, InstructionResult::StopExecutionNeedsReturn {gas, init_off, init_size, apply} => { let mem = mem::replace(&mut self.mem, Vec::new()); - return Err(InterpreterResult::Done(Ok(GasLeft::NeedsReturn { + return InterpreterResult::Done(Ok(GasLeft::NeedsReturn { gas_left: gas.as_u256(), data: mem.into_return_data(init_off, init_size), apply_state: apply - }))); + })); }, InstructionResult::StopExecution => { - return Err(InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256())))); + return InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256()))); }, _ => {}, } if self.reader.position >= self.reader.len() { - return Err(InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256())))); + return InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_mut().expect(GASOMETER_PROOF).current_gas.as_u256()))); } - Err(InterpreterResult::Continue) + InterpreterResult::Continue } fn verify_instruction(&self, ext: &dyn vm::Ext, instruction: Instruction, info: &InstructionInfo) -> vm::Result<()> {