From 9b7c48110af586eec8e6ddc00615823338f2252a Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 6 Apr 2016 13:05:58 +0200 Subject: [PATCH] Fixed eth_call nonce and gas handling --- ethcore/src/client/client.rs | 5 +++-- ethcore/src/executive.rs | 33 ++++++++++++++++++++++++--------- ethcore/src/state.rs | 5 +++-- rpc/src/v1/impls/eth.rs | 6 +++++- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index dfdad70a9..554a839e1 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -38,7 +38,7 @@ use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; use client::{BlockId, TransactionId, UncleId, ClientConfig, BlockChainClient}; use env_info::EnvInfo; -use executive::{Executive, Executed, contract_address}; +use executive::{Executive, Executed, TransactOptions, contract_address}; use receipt::LocalizedReceipt; pub use blockchain::CacheSize as BlockChainCacheSize; @@ -418,7 +418,8 @@ impl BlockChainClient for Client where V: Verifier { // give the sender max balance state.sub_balance(&sender, &balance); state.add_balance(&sender, &U256::max_value()); - Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t, false) + let options = TransactOptions { tracing: false, check_nonce: false }; + Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t, options) } // TODO [todr] Should be moved to miner crate eventually. diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index fe26846c7..3e74895bd 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -36,6 +36,14 @@ pub fn contract_address(address: &Address, nonce: &U256) -> Address { From::from(stream.out().sha3()) } +/// Transaction execution options. +pub struct TransactOptions { + /// Enable call tracing. + pub tracing: bool, + /// Check transaction nonce before execution. + pub check_nonce: bool, +} + /// Transaction execution receipt. #[derive(Debug, PartialEq, Clone)] pub struct Executed { @@ -110,7 +118,7 @@ impl<'a> Executive<'a> { } /// This funtion should be used to execute transaction. - pub fn transact(&'a mut self, t: &SignedTransaction, tracing: bool) -> Result { + pub fn transact(&'a mut self, t: &SignedTransaction, options: TransactOptions) -> Result { let sender = try!(t.sender()); let nonce = self.state.nonce(&sender); @@ -124,8 +132,10 @@ impl<'a> Executive<'a> { let init_gas = t.gas - base_gas_required; // validate transaction nonce - if t.nonce != nonce { - return Err(From::from(ExecutionError::InvalidNonce { expected: nonce, got: t.nonce })); + if options.check_nonce { + if t.nonce != nonce { + return Err(From::from(ExecutionError::InvalidNonce { expected: nonce, got: t.nonce })); + } } // validate if transaction fits into given block @@ -151,7 +161,7 @@ impl<'a> Executive<'a> { self.state.inc_nonce(&sender); self.state.sub_balance(&sender, &U256::from(gas_cost)); - let mut substate = Substate::new(tracing); + let mut substate = Substate::new(options.tracing); let (gas_left, output) = match t.action { Action::Create => { @@ -881,7 +891,8 @@ mod tests { let executed = { let mut ex = Executive::new(&mut state, &info, &engine); - ex.transact(&t, false).unwrap() + let opts = TransactOptions { check_nonce: true, tracing: false }; + ex.transact(&t, opts).unwrap() }; assert_eq!(executed.gas, U256::from(100_000)); @@ -914,7 +925,8 @@ mod tests { let res = { let mut ex = Executive::new(&mut state, &info, &engine); - ex.transact(&t, false) + let opts = TransactOptions { check_nonce: true, tracing: false }; + ex.transact(&t, opts) }; match res { @@ -945,7 +957,8 @@ mod tests { let res = { let mut ex = Executive::new(&mut state, &info, &engine); - ex.transact(&t, false) + let opts = TransactOptions { check_nonce: true, tracing: false }; + ex.transact(&t, opts) }; match res { @@ -978,7 +991,8 @@ mod tests { let res = { let mut ex = Executive::new(&mut state, &info, &engine); - ex.transact(&t, false) + let opts = TransactOptions { check_nonce: true, tracing: false }; + ex.transact(&t, opts) }; match res { @@ -1011,7 +1025,8 @@ mod tests { let res = { let mut ex = Executive::new(&mut state, &info, &engine); - ex.transact(&t, false) + let opts = TransactOptions { check_nonce: true, tracing: false }; + ex.transact(&t, opts) }; match res { diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index c0a676a7d..fca578a09 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -16,7 +16,7 @@ use common::*; use engine::Engine; -use executive::Executive; +use executive::{Executive, TransactOptions}; use account_db::*; #[cfg(test)] #[cfg(feature = "json-tests")] @@ -220,7 +220,8 @@ impl State { pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult { // let old = self.to_pod(); - let e = try!(Executive::new(self, env_info, engine).transact(t, tracing)); + let options = TransactOptions { tracing: tracing, check_nonce: true }; + let e = try!(Executive::new(self, env_info, engine).transact(t, options)); // TODO uncomment once to_pod() works correctly. // trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod())); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index dd241c9ec..b26ce8ac9 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -43,6 +43,10 @@ fn default_gas() -> U256 { U256::from(21_000) } +fn default_call_gas() -> U256 { + U256::from(50_000_000) +} + /// Eth rpc implementation. pub struct EthClient where C: BlockChainClient, @@ -175,7 +179,7 @@ impl EthClient Ok(EthTransaction { nonce: request.nonce.unwrap_or_else(|| client.nonce(&from)), action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or_else(default_gas), + gas: request.gas.unwrap_or_else(default_call_gas), gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), value: request.value.unwrap_or_else(U256::zero), data: request.data.map_or_else(Vec::new, |d| d.to_vec())