Another minor estimation fix (#4133)

* 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.
This commit is contained in:
Gav Wood 2017-01-11 17:51:48 +01:00 committed by Arkadiy Paronyan
parent 8d3d76c107
commit 56c546f465
2 changed files with 12 additions and 11 deletions

View File

@ -874,6 +874,7 @@ impl BlockChainClient for Client {
} }
fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError> { fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError> {
const UPPER_CEILING: u64 = 1_000_000_000_000u64;
let header = self.block_header(block).ok_or(CallError::StatePruned)?; let header = self.block_header(block).ok_or(CallError::StatePruned)?;
let last_hashes = self.build_last_hashes(header.parent_hash()); let last_hashes = self.build_last_hashes(header.parent_hash());
let env_info = EnvInfo { let env_info = EnvInfo {
@ -883,37 +884,38 @@ impl BlockChainClient for Client {
difficulty: header.difficulty(), difficulty: header.difficulty(),
last_hashes: last_hashes, last_hashes: last_hashes,
gas_used: U256::zero(), gas_used: U256::zero(),
gas_limit: U256::max_value(), gas_limit: UPPER_CEILING.into(),
}; };
// that's just a copy of the state. // 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 sender = t.sender().map_err(|e| {
let message = format!("Transaction malformed: {:?}", e); let message = format!("Transaction malformed: {:?}", e);
ExecutionError::TransactionMalformed(message) ExecutionError::TransactionMalformed(message)
})?; })?;
let balance = original_state.balance(&sender); let balance = original_state.balance(&sender);
let needed_balance = t.value + t.gas * 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 options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false };
let mut tx = t.clone(); let mut tx = t.clone();
let mut cond = |gas| { let mut cond = |gas| {
let mut state = original_state.clone();
tx.gas = gas; 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) Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm)
.transact(&tx, options.clone()) .transact(&tx, options.clone())
.map(|r| r.trace[0].result.succeeded()) .map(|r| r.trace[0].result.succeeded())
.unwrap_or(false) .unwrap_or(false)
}; };
let mut upper = env_info.gas_limit; let mut upper = header.gas_limit();
if !cond(upper) { if !cond(upper) {
// impossible at block gas limit - try `UPPER_CEILING` instead. // impossible at block gas limit - try `UPPER_CEILING` instead.
// TODO: consider raising limit by powers of two. // TODO: consider raising limit by powers of two.
const UPPER_CEILING: u64 = 1_000_000_000_000u64;
upper = UPPER_CEILING.into(); upper = UPPER_CEILING.into();
if !cond(upper) { if !cond(upper) {
trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); trace!(target: "estimate_gas", "estimate_gas failed with {}", upper);

View File

@ -660,7 +660,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
num => take_weak!(self.client).call(&signed, num.into(), Default::default()), num => take_weak!(self.client).call(&signed, num.into(), Default::default()),
}; };
result result
.map(|b| b.output.into()) .map(|b| b.output.into())
.map_err(errors::from_call_error) .map_err(errors::from_call_error)