diff --git a/src/evm/ext.rs b/src/evm/ext.rs index 9365c40a0..ca06b5086 100644 --- a/src/evm/ext.rs +++ b/src/evm/ext.rs @@ -6,20 +6,6 @@ use util::bytes::*; use evm::{Schedule, Error}; use env_info::*; -pub struct CallResult { - pub gas_left: U256, - pub success: bool -} - -impl CallResult { - pub fn new(gas_left: U256, success: bool) -> Self { - CallResult { - gas_left: gas_left, - success: success - } - } -} - pub trait Ext { /// Returns a value for given key. fn sload(&self, key: &H256) -> H256; @@ -35,12 +21,12 @@ pub trait Ext { /// Creates new contract. /// - /// Return gas_left and contract address if contract creation was succesfull. + /// Returns gas_left and contract address if contract creation was succesfull. fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> (U256, Option
); /// Message call. /// - /// Returns None, if we run out of gas. + /// Returns Err, if we run out of gas. /// Otherwise returns call_result which contains gas left /// and true if subcall was successfull. fn call(&mut self, @@ -50,7 +36,7 @@ pub trait Ext { value: &U256, data: &[u8], code_address: &Address, - output: &mut [u8]) -> Option; + output: &mut [u8]) -> Result<(U256, bool), Error>; /// Returns code at given address fn extcode(&self, address: &Address) -> Vec; diff --git a/src/evm/jit.rs b/src/evm/jit.rs index 4cb2e763e..c997ac89b 100644 --- a/src/evm/jit.rs +++ b/src/evm/jit.rs @@ -229,21 +229,29 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> { out_size: u64, code_address: *const evmjit::H256) -> bool { unsafe { - let opt = self.ext.call(&U256::from(*io_gas), + let res = self.ext.call(&U256::from(*io_gas), &U256::from(call_gas), &Address::from_jit(&*receive_address), &U256::from_jit(&*value), slice::from_raw_parts(in_beg, in_size as usize), &Address::from_jit(&*code_address), slice::from_raw_parts_mut(out_beg, out_size as usize)); - match opt { - None => { + match res { + Ok((gas_left, ok)) => { + *io_gas = gas_left.low_u64(); + ok + } + Err(evm::Error::OutOfGas) => { + // hack to propagate out_of_gas to evmjit. + // must be negative *io_gas = -1i64 as u64; false }, - Some(res) => { - *io_gas = res.gas_left.low_u64(); - res.success + Err(err) => { + // internal error. + *self.err = Some(err); + *io_gas = -1i64 as u64; + false } } } diff --git a/src/evm/mod.rs b/src/evm/mod.rs index d0635a017..e84e133c5 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -11,6 +11,6 @@ mod jit; mod tests; pub use self::evm::{Evm, Error, Result}; -pub use self::ext::{Ext, CallResult}; +pub use self::ext::{Ext}; pub use self::factory::Factory; pub use self::schedule::Schedule; diff --git a/src/evm/tests.rs b/src/evm/tests.rs index f06d55943..648d35646 100644 --- a/src/evm/tests.rs +++ b/src/evm/tests.rs @@ -1,6 +1,6 @@ use common::*; use evm; -use evm::{Ext, Schedule, Factory, CallResult}; +use evm::{Ext, Schedule, Factory}; struct FakeLogEntry { topics: Vec, @@ -53,7 +53,7 @@ impl Ext for FakeExt { _value: &U256, _data: &[u8], _code_address: &Address, - _output: &mut [u8]) -> Option { + _output: &mut [u8]) -> result::Result<(U256, bool), evm::Error> { unimplemented!(); } diff --git a/src/executive.rs b/src/executive.rs index e0531fdae..c9a829f8a 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -2,7 +2,7 @@ use common::*; use state::*; use engine::*; -use evm::{self, Schedule, Factory, Ext, CallResult}; +use evm::{self, Schedule, Factory, Ext}; /// Returns new address created from address and given nonce. pub fn contract_address(address: &Address, nonce: &U256) -> Address { @@ -408,7 +408,7 @@ impl<'a> Ext for Externalities<'a> { value: &U256, data: &[u8], code_address: &Address, - output: &mut [u8]) -> Option { + output: &mut [u8]) -> Result<(U256, bool), evm::Error> { let mut gas_cost = *call_gas; let mut call_gas = *call_gas; @@ -425,7 +425,7 @@ impl<'a> Ext for Externalities<'a> { if gas_cost > *gas { self.substate.out_of_gas = true; - return None; + return Err(evm::Error::OutOfGas); //return (U256::from(-1i64 as u64), false); } @@ -433,8 +433,9 @@ impl<'a> Ext for Externalities<'a> { // if balance is insufficient or we are to deep, return if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.max_depth { - return Some(CallResult::new(gas + call_gas, true)); + //return Some(CallResult::new(gas + call_gas, true)); //return (gas + call_gas, true); + return Ok((gas + call_gas, true)); } let params = ActionParams { @@ -450,10 +451,11 @@ impl<'a> Ext for Externalities<'a> { let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth); match ex.call(¶ms, self.substate, BytesRef::Fixed(output)) { - Ok(gas_left) => Some(CallResult::new(gas + gas_left, true)), + Ok(gas_left) => Ok((gas + gas_left, true)), //Some(CallResult::new(gas + gas_left, true)), _ => { self.substate.out_of_gas = true; - Some(CallResult::new(gas, false)) + Ok((gas, false)) + //Some(CallResult::new(gas, false)) } } //ex.call(¶ms, self.substate, BytesRef::Fixed(output)).map(|gas_left| gas + gas_left) diff --git a/src/tests/executive.rs b/src/tests/executive.rs index 704ce8259..073751a72 100644 --- a/src/tests/executive.rs +++ b/src/tests/executive.rs @@ -4,7 +4,7 @@ use executive::*; use spec::*; use engine::*; use evm; -use evm::{Schedule, Ext, Factory, CallResult}; +use evm::{Schedule, Ext, Factory}; use ethereum; struct TestEngine { @@ -110,10 +110,10 @@ impl<'a> Ext for TestExt<'a> { value: &U256, data: &[u8], code_address: &Address, - output: &mut [u8]) -> Option { - let opt = self.ext.call(gas, call_gas, receive_address, value, data, code_address, output); + output: &mut [u8]) -> Result<(U256, bool), evm::Error> { + let res = self.ext.call(gas, call_gas, receive_address, value, data, code_address, output); let ext = &self.ext; - if let &Some(_) = &opt { + if let &Ok(_some) = &res { if ext.state.balance(&ext.params.address) >= *value { self.callcreates.push(CallCreate { data: data.to_vec(), @@ -123,7 +123,7 @@ impl<'a> Ext for TestExt<'a> { }); } } - opt + res } fn extcode(&self, address: &Address) -> Vec {