Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Improvements and optimisations to estimate_gas (#4142)
Browse files Browse the repository at this point in the history
* Return 0 instead of error with out of gas on estimate_gas

* Fix stuff up.

* Another estimate gas fix.

* Alter balance to maximum possible rather than GP=0.

* Only increase to amount strictly necessary.

* Improvements and optimisations to estimate_gas.

- Introduce proper error type
- Avoid building costly traces

* Fix tests.

* Actually fix testsActually fix tests
  • Loading branch information
gavofyork authored and arkpar committed Jan 12, 2017
1 parent 41da1a0 commit 311730e
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 3 deletions.
2 changes: 1 addition & 1 deletion ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ impl BlockChainClient for Client {

Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm)
.transact(&tx, options.clone())
.map(|r| r.trace[0].result.succeeded())
.map(|r| r.exception.is_some())
.unwrap_or(false)
};

Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/evm/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use action_params::ActionParams;
use evm::Ext;

/// Evm errors.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Error {
/// `OutOfGas` is returned when transaction execution runs out of gas.
/// The state should be reverted to the state from before the
Expand Down
4 changes: 3 additions & 1 deletion ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,9 @@ impl<'a> Executive<'a> {

match result {
Err(evm::Error::Internal) => Err(ExecutionError::Internal),
Err(_) => {
Err(exception) => {
Ok(Executed {
exception: Some(exception),
gas: t.gas,
gas_used: t.gas,
refunded: U256::zero(),
Expand All @@ -479,6 +480,7 @@ impl<'a> Executive<'a> {
},
_ => {
Ok(Executed {
exception: None,
gas: t.gas,
gas_used: gas_used,
refunded: refunded,
Expand Down
7 changes: 7 additions & 0 deletions ethcore/src/types/executed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use util::{Bytes, U256, Address, U512};
use rlp::*;
use evm;
use trace::{VMTrace, FlatTrace};
use types::log_entry::LogEntry;
use types::state_diff::StateDiff;
Expand Down Expand Up @@ -65,6 +66,9 @@ impl Decodable for CallType {
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Executed {
/// True if the outer call/create resulted in an exceptional exit.
pub exception: Option<evm::Error>,

/// Gas paid up front for execution of transaction.
pub gas: U256,

Expand Down Expand Up @@ -178,6 +182,8 @@ pub enum CallError {
TransactionNotFound,
/// Couldn't find requested block's state in the chain.
StatePruned,
/// Couldn't find an amount of gas that didn't result in an exception.
Exceptional,
/// Error executing.
Execution(ExecutionError),
}
Expand All @@ -195,6 +201,7 @@ impl fmt::Display for CallError {
let msg = match *self {
TransactionNotFound => "Transaction couldn't be found in the chain".into(),
StatePruned => "Couldn't find the transaction block's state in the chain".into(),
Exceptional => "An exception happened in the execution".into(),
Execution(ref e) => format!("{}", e),
};

Expand Down
10 changes: 10 additions & 0 deletions rpc/src/v1/helpers/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mod codes {
pub const UNKNOWN_ERROR: i64 = -32009;
pub const TRANSACTION_ERROR: i64 = -32010;
pub const EXECUTION_ERROR: i64 = -32015;
pub const EXCEPTION_ERROR: i64 = -32016;
pub const ACCOUNT_LOCKED: i64 = -32020;
pub const PASSWORD_INVALID: i64 = -32021;
pub const ACCOUNT_ERROR: i64 = -32023;
Expand Down Expand Up @@ -130,6 +131,14 @@ pub fn state_pruned() -> Error {
}
}

pub fn exceptional() -> Error {
Error {
code: ErrorCode::ServerError(codes::EXCEPTION_ERROR),
message: "The execution failed due to an exception.".into(),
data: None
}
}

pub fn no_work() -> Error {
Error {
code: ErrorCode::ServerError(codes::NO_WORK),
Expand Down Expand Up @@ -286,6 +295,7 @@ pub fn from_rlp_error(error: DecoderError) -> Error {
pub fn from_call_error(error: CallError) -> Error {
match error {
CallError::StatePruned => state_pruned(),
CallError::Exceptional => exceptional(),
CallError::Execution(e) => execution(e),
CallError::TransactionNotFound => internal("{}, this should not be the case with eth_call, most likely a bug.", CallError::TransactionNotFound),
}
Expand Down
5 changes: 5 additions & 0 deletions rpc/src/v1/tests/mocked/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ fn rpc_eth_code() {
fn rpc_eth_call_latest() {
let tester = EthTester::default();
tester.client.set_execution_result(Ok(Executed {
exception: None,
gas: U256::zero(),
gas_used: U256::from(0xff30),
refunded: U256::from(0x5),
Expand Down Expand Up @@ -599,6 +600,7 @@ fn rpc_eth_call_latest() {
fn rpc_eth_call() {
let tester = EthTester::default();
tester.client.set_execution_result(Ok(Executed {
exception: None,
gas: U256::zero(),
gas_used: U256::from(0xff30),
refunded: U256::from(0x5),
Expand Down Expand Up @@ -634,6 +636,7 @@ fn rpc_eth_call() {
fn rpc_eth_call_default_block() {
let tester = EthTester::default();
tester.client.set_execution_result(Ok(Executed {
exception: None,
gas: U256::zero(),
gas_used: U256::from(0xff30),
refunded: U256::from(0x5),
Expand Down Expand Up @@ -668,6 +671,7 @@ fn rpc_eth_call_default_block() {
fn rpc_eth_estimate_gas() {
let tester = EthTester::default();
tester.client.set_execution_result(Ok(Executed {
exception: None,
gas: U256::zero(),
gas_used: U256::from(0xff30),
refunded: U256::from(0x5),
Expand Down Expand Up @@ -703,6 +707,7 @@ fn rpc_eth_estimate_gas() {
fn rpc_eth_estimate_gas_default_block() {
let tester = EthTester::default();
tester.client.set_execution_result(Ok(Executed {
exception: None,
gas: U256::zero(),
gas_used: U256::from(0xff30),
refunded: U256::from(0x5),
Expand Down
1 change: 1 addition & 0 deletions rpc/src/v1/tests/mocked/traces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ fn io() -> Tester {
block_hash: 10.into(),
}]);
*client.execution_result.write() = Some(Ok(Executed {
exception: None,
gas: 20_000.into(),
gas_used: 10_000.into(),
refunded: 0.into(),
Expand Down

0 comments on commit 311730e

Please sign in to comment.