diff --git a/src/evm/evm.rs b/src/evm/evm.rs index 45b48a206..2beb80e45 100644 --- a/src/evm/evm.rs +++ b/src/evm/evm.rs @@ -1,7 +1,6 @@ //! Evm interface. use util::uint::U256; -use util::bytes::Bytes; use evm::{EvmParams, Ext}; /// Evm errors. diff --git a/src/evm/executive.rs b/src/evm/executive.rs index a983aff9c..603c8f34e 100644 --- a/src/evm/executive.rs +++ b/src/evm/executive.rs @@ -1,3 +1,4 @@ +//! Transaction Execution environment. use std::collections::HashSet; use std::cmp; use std::ptr; @@ -139,11 +140,11 @@ impl<'a> Executive<'a> { } /// This funtion should be used to execute transaction. - pub fn transact(e: &mut Executive<'a>, t: &Transaction) -> ExecutionResult { + pub fn transact(&mut self, t: &Transaction) -> ExecutionResult { // TODO: validate transaction signature ?/ sender let sender = t.sender(); - let nonce = e.state.nonce(&sender); + let nonce = self.state.nonce(&sender); // validate transaction nonce if t.nonce != nonce { @@ -151,16 +152,16 @@ impl<'a> Executive<'a> { } // validate if transaction fits into given block - if e.info.gas_used + t.gas > e.info.gas_limit { + if self.info.gas_used + t.gas > self.info.gas_limit { return Err(ExecutionError::BlockGasLimitReached { - gas_limit: e.info.gas_limit, - gas_used: e.info.gas_used, + gas_limit: self.info.gas_limit, + gas_used: self.info.gas_used, gas: t.gas }); } // TODO: we might need bigints here, or at least check overflows. - let balance = e.state.balance(&sender); + let balance = self.state.balance(&sender); let gas_cost = t.gas * t.gas_price; let total_cost = t.value + gas_cost; @@ -170,7 +171,7 @@ impl<'a> Executive<'a> { } // NOTE: there can be no invalid transactions from this point. - e.state.inc_nonce(&sender); + self.state.inc_nonce(&sender); let mut substate = Substate::new(); let res = match t.kind() { @@ -185,7 +186,7 @@ impl<'a> Executive<'a> { code: t.data.clone(), data: vec![], }; - Executive::call(e, ¶ms, &mut substate, &mut []) + self.call(¶ms, &mut substate, &mut []) }, TransactionKind::MessageCall => { let params = EvmParams { @@ -195,15 +196,15 @@ impl<'a> Executive<'a> { gas: t.gas, gas_price: t.gas_price, value: t.value, - code: e.state.code(&t.to.clone().unwrap()).unwrap_or(vec![]), + code: self.state.code(&t.to.clone().unwrap()).unwrap_or(vec![]), data: t.data.clone(), }; - Executive::create(e, ¶ms, &mut substate) + self.create(¶ms, &mut substate) } }; // finalize here! - e.finalize(substate, &sender, U256::zero(), U256::zero(), t.gas_price); + self.finalize(substate, &sender, U256::zero(), U256::zero(), t.gas_price); //res Ok(Executed::new()) } @@ -212,23 +213,23 @@ impl<'a> Executive<'a> { /// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides). /// Modifies the substate and the output. /// Returns either gas_left or `EvmError`. - fn call(e: &mut Executive<'a>, params: &EvmParams, substate: &mut Substate, output: &mut [u8]) -> EvmResult { + fn call(&mut self, params: &EvmParams, substate: &mut Substate, output: &mut [u8]) -> EvmResult { // at first, transfer value to destination - e.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value); + self.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value); - if e.engine.is_builtin(¶ms.address) { + if self.engine.is_builtin(¶ms.address) { // if destination is builtin, try to execute it - let cost = e.engine.cost_of_builtin(¶ms.address, ¶ms.data); + let cost = self.engine.cost_of_builtin(¶ms.address, ¶ms.data); match cost <= params.gas { true => { - e.engine.execute_builtin(¶ms.address, ¶ms.data, output); + self.engine.execute_builtin(¶ms.address, ¶ms.data, output); Ok(params.gas - cost) }, false => Err(EvmError::OutOfGas) } } else if params.code.len() > 0 { // if destination is a contract, do normal message call - let mut ext = Externalities::new(e.state, e.info, e.engine, e.depth, params, substate, OutputPolicy::Return(output)); + let mut ext = Externalities::new(self.state, self.info, self.engine, self.depth, params, substate, OutputPolicy::Return(output)); let evm = VmFactory::create(); evm.exec(¶ms, &mut ext) } else { @@ -240,13 +241,13 @@ impl<'a> Executive<'a> { /// Creates contract with given contract params. /// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides). /// Modifies the substate. - fn create(e: &mut Executive<'a>, params: &EvmParams, substate: &mut Substate) -> EvmResult { + fn create(&mut self, params: &EvmParams, substate: &mut Substate) -> EvmResult { // at first create new contract - e.state.new_contract(¶ms.address); + self.state.new_contract(¶ms.address); // then transfer value to it - e.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value); + self.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value); - let mut ext = Externalities::new(e.state, e.info, e.engine, e.depth, params, substate, OutputPolicy::InitContract); + let mut ext = Externalities::new(self.state, self.info, self.engine, self.depth, params, substate, OutputPolicy::InitContract); let evm = VmFactory::create(); evm.exec(¶ms, &mut ext) } @@ -351,7 +352,7 @@ impl<'a> Ext for Externalities<'a> { } } - fn create(&mut self, gas: u64, endowment: &U256, code: &[u8]) -> Option<(Address, u64)> { + fn create(&mut self, gas: u64, endowment: &U256, code: &[u8]) -> Option<(u64, Address)> { // if balance is insufficient or we are to deep, return if self.state.balance(&self.params.address) < *endowment && self.depth >= 1024 { return None @@ -376,14 +377,14 @@ impl<'a> Ext for Externalities<'a> { { let mut ex = Executive::from_parent(self); ex.state.inc_nonce(&address); - let res = Executive::create(&mut ex, ¶ms, &mut substate); + let res = ex.create(¶ms, &mut substate); } self.substate.accrue(substate); - Some((address, gas)) + Some((gas, address)) } - fn call(&mut self, gas: u64, call_gas: u64, receive_address: &Address, value: &U256, data: &[u8], code_address: &Address) -> Option<(Vec, u64)> { + fn call(&mut self, gas: u64, call_gas: u64, receive_address: &Address, value: &U256, data: &[u8], code_address: &Address, output: &mut [u8]) -> Option { // TODO: validation of the call println!("gas: {:?}", gas); @@ -431,12 +432,12 @@ impl<'a> Ext for Externalities<'a> { { let mut ex = Executive::from_parent(self); // TODO: take output into account - Executive::call(&mut ex, ¶ms, &mut substate, &mut []); + ex.call(¶ms, &mut substate, output); } self.substate.accrue(substate); // TODO: replace call_gas with what's actually left - Some((vec![], gas - gas_cost + call_gas)) + Some(gas - gas_cost + call_gas) } fn extcode(&self, address: &Address) -> Vec { diff --git a/src/evm/ext.rs b/src/evm/ext.rs index d9fb0b659..ac9780737 100644 --- a/src/evm/ext.rs +++ b/src/evm/ext.rs @@ -20,14 +20,14 @@ pub trait Ext { /// Creates new contract. /// If contract creation is successfull, - /// returns new contract address and gas left, + /// return gas_left and contract address, /// otherwise `None`. - fn create(&mut self, gas: u64, endowment: &U256, code: &[u8]) -> Option<(Address, u64)>; + fn create(&mut self, gas: u64, endowment: &U256, code: &[u8]) -> Option<(u64, Address)>; /// Message call. - /// If call is successfull, returns call output and gas left. + /// If call is successfull, returns gas left. /// otherwise `None`. - fn call(&mut self, gas: u64, call_gas: u64, receive_address: &Address, value: &U256, data: &[u8], code_address: &Address) -> Option<(Vec, u64)>; + fn call(&mut self, gas: u64, call_gas: u64, receive_address: &Address, value: &U256, data: &[u8], code_address: &Address, output: &mut [u8]) -> Option; /// Returns code at given address fn extcode(&self, address: &Address) -> Vec; diff --git a/src/evm/jit.rs b/src/evm/jit.rs index 2ac756ddc..f1e1b1bc3 100644 --- a/src/evm/jit.rs +++ b/src/evm/jit.rs @@ -1,3 +1,4 @@ +//! Just in time compiler execution environment. use std::mem; use std::ptr; use std::slice; @@ -240,6 +241,7 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> { return false; } + // TODO: fix this! let (mut output, gas) = opt.unwrap(); out_beg = output.as_mut_ptr(); mem::forget(output); diff --git a/src/evm/logentry.rs b/src/evm/logentry.rs index 7307dadf4..265e8885a 100644 --- a/src/evm/logentry.rs +++ b/src/evm/logentry.rs @@ -1,3 +1,4 @@ +//! Transaction log entry. use util::hash::*; use util::bytes::*; use util::sha3::*; diff --git a/src/evm/params.rs b/src/evm/params.rs index 143709f56..5edbe128a 100644 --- a/src/evm/params.rs +++ b/src/evm/params.rs @@ -1,16 +1,26 @@ +//! Evm input params. use util::hash::*; use util::uint::*; use util::bytes::*; +/// Evm input params. Everything else should be specified in Externalities. #[derive(Clone, Debug)] pub struct EvmParams { + /// Address of currently executed code. pub address: Address, + /// Sender of current part of the transaction. pub sender: Address, + /// Transaction initiator. pub origin: Address, + /// Gas paid up front for transaction execution pub gas: U256, + /// Gas price. pub gas_price: U256, + /// Transaction value. pub value: U256, + /// Code being executed. pub code: Bytes, + /// Input data. pub data: Bytes } diff --git a/src/evm/vmfactory.rs b/src/evm/vmfactory.rs index 306ec4e0f..13a908cc7 100644 --- a/src/evm/vmfactory.rs +++ b/src/evm/vmfactory.rs @@ -2,8 +2,7 @@ use evm::Evm; -/// Vm factory. Creates appropriate Evm. -/// TODO: SmartVm +/// Evm factory. Creates appropriate Evm. pub struct VmFactory; impl VmFactory {