From 7b93fc90ec859b5cf6c0e043b796fbf81bcbf414 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 10 Jan 2017 19:42:57 +0100 Subject: [PATCH 1/5] Return 0 instead of error with out of gas on estimate_gas --- rpc/src/v1/impls/eth.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index fd5f3d4f3eb..22164998306 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -673,6 +673,7 @@ impl Eth for EthClient where let signed = self.sign_call(request)?; take_weak!(self.client).estimate_gas(&signed, num.0.into()) .map(Into::into) + .or_else(|_| Ok(0.into())) .map_err(errors::from_call_error) } From f11f8c2c1302821600664690ce9f0ac6cb21e907 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 11 Jan 2017 12:50:44 +0100 Subject: [PATCH 2/5] Fix stuff up. --- ethcore/src/client/client.rs | 4 ++-- rpc/src/v1/impls/eth.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index cd074a88c86..c612bb8faef 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -848,7 +848,7 @@ impl BlockChainClient for Client { difficulty: header.difficulty(), last_hashes: last_hashes, gas_used: U256::zero(), - gas_limit: header.gas_limit(), + gas_limit: U256::max_value(), }; // that's just a copy of the state. let mut state = self.state_at(block).ok_or(CallError::StatePruned)?; @@ -883,7 +883,7 @@ impl BlockChainClient for Client { difficulty: header.difficulty(), last_hashes: last_hashes, gas_used: U256::zero(), - gas_limit: header.gas_limit(), + gas_limit: U256::max_value(), }; // that's just a copy of the state. let mut original_state = self.state_at(block).ok_or(CallError::StatePruned)?; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 22164998306..fd5f3d4f3eb 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -673,7 +673,6 @@ impl Eth for EthClient where let signed = self.sign_call(request)?; take_weak!(self.client).estimate_gas(&signed, num.0.into()) .map(Into::into) - .or_else(|_| Ok(0.into())) .map_err(errors::from_call_error) } From 82e0775e067c4d27b7da4638d593b16cd00bcb91 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 11 Jan 2017 15:47:45 +0100 Subject: [PATCH 3/5] Another estimate gas fix. --- ethcore/src/client/client.rs | 7 ++++--- rpc/src/v1/impls/eth.rs | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index c612bb8faef..b23b9756dbc 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -874,6 +874,7 @@ impl BlockChainClient for Client { } fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result { + const UPPER_CEILING: u64 = 1_000_000_000_000u64; let header = self.block_header(block).ok_or(CallError::StatePruned)?; let last_hashes = self.build_last_hashes(header.parent_hash()); let env_info = EnvInfo { @@ -883,7 +884,7 @@ impl BlockChainClient for Client { difficulty: header.difficulty(), last_hashes: last_hashes, gas_used: U256::zero(), - gas_limit: U256::max_value(), + gas_limit: UPPER_CEILING.into(), }; // that's just a copy of the state. let mut original_state = self.state_at(block).ok_or(CallError::StatePruned)?; @@ -899,6 +900,7 @@ impl BlockChainClient for Client { } let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false }; let mut tx = t.clone(); + tx.gas_price = 0.into(); let mut cond = |gas| { let mut state = original_state.clone(); @@ -909,11 +911,10 @@ impl BlockChainClient for Client { .unwrap_or(false) }; - let mut upper = env_info.gas_limit; + let mut upper = header.gas_limit(); if !cond(upper) { // impossible at block gas limit - try `UPPER_CEILING` instead. // TODO: consider raising limit by powers of two. - const UPPER_CEILING: u64 = 1_000_000_000_000u64; upper = UPPER_CEILING.into(); if !cond(upper) { trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index fd5f3d4f3eb..75817838d67 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -660,7 +660,6 @@ impl Eth for EthClient where num => take_weak!(self.client).call(&signed, num.into(), Default::default()), }; - result .map(|b| b.output.into()) .map_err(errors::from_call_error) From 116386e98360469a7806267813f91b20f525cf88 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 11 Jan 2017 17:18:41 +0100 Subject: [PATCH 4/5] Alter balance to maximum possible rather than GP=0. --- ethcore/src/client/client.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 19b21bfe10f..c0eca8a6d89 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -893,14 +893,13 @@ impl BlockChainClient for Client { ExecutionError::TransactionMalformed(message) })?; let balance = original_state.balance(&sender); - let needed_balance = t.value + t.gas * t.gas_price; + let needed_balance = t.value + U256::from(UPPER_CEILING) * t.gas_price; if balance < needed_balance { // give the sender a sufficient balance original_state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty); } let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false }; let mut tx = t.clone(); - tx.gas_price = 0.into(); let mut cond = |gas| { let mut state = original_state.clone(); From c585cc113fe4f4240a0149d0866bed8706b55183 Mon Sep 17 00:00:00 2001 From: Gav Date: Wed, 11 Jan 2017 17:22:02 +0100 Subject: [PATCH 5/5] Only increase to amount strictly necessary. --- ethcore/src/client/client.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index c0eca8a6d89..abc4977179c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -887,23 +887,25 @@ impl BlockChainClient for Client { gas_limit: UPPER_CEILING.into(), }; // that's just a copy of the state. - let mut original_state = self.state_at(block).ok_or(CallError::StatePruned)?; + let original_state = self.state_at(block).ok_or(CallError::StatePruned)?; let sender = t.sender().map_err(|e| { let message = format!("Transaction malformed: {:?}", e); ExecutionError::TransactionMalformed(message) })?; let balance = original_state.balance(&sender); - let needed_balance = t.value + U256::from(UPPER_CEILING) * t.gas_price; - if balance < needed_balance { - // give the sender a sufficient balance - original_state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty); - } let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false }; let mut tx = t.clone(); let mut cond = |gas| { - let mut state = original_state.clone(); tx.gas = gas; + + let mut state = original_state.clone(); + let needed_balance = tx.value + tx.gas * tx.gas_price; + if balance < needed_balance { + // give the sender a sufficient balance + state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty); + } + Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm) .transact(&tx, options.clone()) .map(|r| r.trace[0].result.succeeded())