From 6eb3253b307ec3818ca4a9f2cccfae6b820cfd36 Mon Sep 17 00:00:00 2001 From: Niklas Adofsson Date: Wed, 19 Sep 2018 08:39:25 +0200 Subject: [PATCH] `ExecutionsRequest` from light-clients as read-only This changes so all `ExecutionRequests` from light-clients are executed as read-only which the `virtual``flag == true ensures. This boost up the current transaction to always succeed Note, this only affects `eth_estimateGas` and `eth_call` AFAIK. --- ethcore/light/src/on_demand/request.rs | 10 +++++----- ethcore/res/wasm-tests | 2 +- ethcore/src/client/client.rs | 3 ++- rpc/src/v1/helpers/light_fetch.rs | 22 +++++++++++----------- rpc/src/v1/impls/light/eth.rs | 4 ++-- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index 76ecf879d00..6053146e16b 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -61,7 +61,7 @@ pub enum Request { /// A request for a contract's code. Code(Code), /// A request for proof of execution. - Execution(TransactionProof), + Execution(ReadOnlyTransactionProof), /// A request for epoch change signal. Signal(Signal), } @@ -145,7 +145,7 @@ impl_single!(Receipts, BlockReceipts, Vec); impl_single!(Body, Body, encoded::Block); impl_single!(Account, Account, Option); impl_single!(Code, Code, Bytes); -impl_single!(Execution, TransactionProof, super::ExecutionResult); +impl_single!(Execution, ReadOnlyTransactionProof, super::ExecutionResult); impl_single!(Signal, Signal, Vec); macro_rules! impl_args { @@ -256,7 +256,7 @@ pub enum CheckedRequest { Body(Body, net_request::IncompleteBodyRequest), Account(Account, net_request::IncompleteAccountRequest), Code(Code, net_request::IncompleteCodeRequest), - Execution(TransactionProof, net_request::IncompleteExecutionRequest), + Execution(ReadOnlyTransactionProof, net_request::IncompleteExecutionRequest), Signal(Signal, net_request::IncompleteSignalRequest) } @@ -1030,7 +1030,7 @@ impl Code { /// Request for transaction execution, along with the parts necessary to verify the proof. #[derive(Clone)] -pub struct TransactionProof { +pub struct ReadOnlyTransactionProof { /// The transaction to request proof of. pub tx: SignedTransaction, /// Block header. @@ -1042,7 +1042,7 @@ pub struct TransactionProof { pub engine: Arc, } -impl TransactionProof { +impl ReadOnlyTransactionProof { /// Check the proof, returning the proved execution or indicate that the proof was bad. pub fn check_response(&self, _: &Mutex<::cache::Cache>, state_items: &[DBValue]) -> Result { let root = self.header.as_ref()?.state_root(); diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 0edbf860ff7..d17bfb69620 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 0edbf860ff7ed4b6b6336097ba44836e8c6482dd +Subproject commit d17bfb6962041c4ac7f82eb79f72eef8d42f9447 diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d9c2a578113..b3b0ebd2990 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -2342,6 +2342,7 @@ impl ProvingBlockChainClient for Client { } fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec)> { + trace!(target: "pip_provider", "prove_transaction: {:?}", transaction); let (header, mut env_info) = match (self.block_header(id), self.env_info(id)) { (Some(s), Some(e)) => (s, e), _ => return None, @@ -2357,7 +2358,7 @@ impl ProvingBlockChainClient for Client { self.engine.machine(), &env_info, self.factories.clone(), - false, + true, ) } diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index 88821c572f0..683c9366451 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -191,7 +191,7 @@ impl LightFetch { } /// Helper for getting proved execution. - pub fn proved_execution(&self, req: CallRequest, num: Trailing) -> impl Future + Send { + pub fn proved_read_only_execution(&self, req: CallRequest, num: Trailing) -> impl Future + Send { const DEFAULT_GAS_PRICE: u64 = 21_000; // starting gas when gas not provided. const START_GAS: u64 = 50_000; @@ -255,14 +255,14 @@ impl LightFetch { _ => return Either::A(future::err(errors::unknown_block())), }; - Either::B(execute_tx(gas_known, ExecuteParams { - from: from, - tx: tx, - hdr: hdr, - env_info: env_info, + Either::B(execute_read_only_tx(gas_known, ExecuteParams { + from, + tx, + hdr, + env_info, engine: client.engine().clone(), - on_demand: on_demand, - sync: sync, + on_demand, + sync, })) })) } @@ -607,10 +607,10 @@ struct ExecuteParams { // has a peer execute the transaction with given params. If `gas_known` is false, // this will double the gas on each `OutOfGas` error. -fn execute_tx(gas_known: bool, params: ExecuteParams) -> impl Future + Send { +fn execute_read_only_tx(gas_known: bool, params: ExecuteParams) -> impl Future + Send { if !gas_known { Box::new(future::loop_fn(params, |mut params| { - execute_tx(true, params.clone()).and_then(move |res| { + execute_read_only_tx(true, params.clone()).and_then(move |res| { match res { Ok(executed) => { // TODO: how to distinguish between actual OOG and @@ -635,7 +635,7 @@ fn execute_tx(gas_known: bool, params: ExecuteParams) -> impl Future Eth for EthClient { } fn call(&self, req: CallRequest, num: Trailing) -> BoxFuture { - Box::new(self.fetcher().proved_execution(req, num).and_then(|res| { + Box::new(self.fetcher().proved_read_only_execution(req, num).and_then(|res| { match res { Ok(exec) => Ok(exec.output.into()), Err(e) => Err(errors::execution(e)), @@ -408,7 +408,7 @@ impl Eth for EthClient { fn estimate_gas(&self, req: CallRequest, num: Trailing) -> BoxFuture { // TODO: binary chop for more accurate estimates. - Box::new(self.fetcher().proved_execution(req, num).and_then(|res| { + Box::new(self.fetcher().proved_read_only_execution(req, num).and_then(|res| { match res { Ok(exec) => Ok((exec.refunded + exec.gas_used).into()), Err(e) => Err(errors::execution(e)),