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

Commit

Permalink
Execute read_only can't run out-of-gas
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasad1 committed Oct 29, 2018
1 parent f8f8bf0 commit 452a20d
Showing 1 changed file with 20 additions and 16 deletions.
36 changes: 20 additions & 16 deletions rpc/src/v1/helpers/light_fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
use std::cmp;
use std::sync::Arc;

use light::on_demand::error::Error as OnDemandError;
use ethcore::basic_account::BasicAccount;
use ethcore::encoded;
use ethcore::filter::Filter as EthcoreFilter;
use ethcore::ids::BlockId;
use ethcore::receipt::Receipt;
use ethcore::executed::ExecutionError;

use jsonrpc_core::{Result, Error};
use jsonrpc_core::futures::{future, Future};
Expand All @@ -38,6 +38,7 @@ use light::on_demand::{
request, OnDemand, HeaderRef, Request as OnDemandRequest,
Response as OnDemandResponse, ExecutionResult,
};
use light::on_demand::error::Error as OnDemandError;
use light::request::Field;

use sync::LightSync;
Expand Down Expand Up @@ -202,8 +203,8 @@ impl LightFetch {
/// Helper for getting proved execution.
pub fn proved_read_only_execution(&self, req: CallRequest, num: Trailing<BlockNumber>) -> impl Future<Item = ExecutionResult, Error = Error> + Send {
const DEFAULT_GAS_PRICE: u64 = 21_000;
// starting gas when gas not provided.
const START_GAS: u64 = 50_000;
// (21000 G_transaction + 32000 G_create)
const START_GAS: u64 = 53_000;

let (sync, on_demand, client) = (self.sync.clone(), self.on_demand.clone(), self.client.clone());
let req: CallRequestHelper = req.into();
Expand Down Expand Up @@ -615,28 +616,31 @@ struct ExecuteParams {
sync: Arc<LightSync>,
}

// has a peer execute the transaction with given params. If `gas_known` is false,
// this will double the gas on each `OutOfGas` error.
// Has a peer execute the transaction with given params. If `gas_known` is false, this will set the `gas value` to the
// `required gas value` unless it exceeds the block gas limit
fn execute_read_only_tx(gas_known: bool, params: ExecuteParams) -> impl Future<Item = ExecutionResult, Error = Error> + Send {
if !gas_known {
Box::new(future::loop_fn(params, |mut params| {
execute_read_only_tx(true, params.clone()).and_then(move |res| {
match res {
Ok(executed) => {
// TODO: how to distinguish between actual OOG and
// exception?
if executed.exception.is_some() {
let old_gas = params.tx.gas;
params.tx.gas = params.tx.gas * 2u32;
if params.tx.gas > params.hdr.gas_limit() {
params.tx.gas = old_gas;
} else {
return Ok(future::Loop::Continue(params))
}
// `OutOfGas` exception can't occur here because of virtual execution context
if let Some(ref exception) = executed.exception {
trace!(target: "light_fetch", "Execution exception: {}", exception);
}

Ok(future::Loop::Break(Ok(executed)))
}
Err(ExecutionError::NotEnoughBaseGas { required, got }) => {
trace!(target: "light_fetch", "Not enough start gas provided required: {}, got: {}", required, got);
if required <= params.hdr.gas_limit() {
params.tx.gas = required;
return Ok(future::Loop::Continue(params))
} else {
warn!(target: "light_fetch", "Required gas is bigger than block header's gas dropping the request");
Ok(future::Loop::Break(Err(ExecutionError::NotEnoughBaseGas { required, got })))
}
}
// Non-recoverable execution error
failed => Ok(future::Loop::Break(failed)),
}
})
Expand Down

0 comments on commit 452a20d

Please sign in to comment.