diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index f47ab2055..cf8bdbbe1 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -627,26 +627,28 @@ impl Eth for EthClient where self.send_raw_transaction(raw) } - fn call(&self, request: CallRequest, num: Trailing) -> Result { + fn call(&self, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); let signed = self.sign_call(request)?; let result = match num.0 { - BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()), - num => take_weak!(self.client).call(&signed, num.into(), Default::default()), + BlockNumber::Pending => take_weakf!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()), + num => take_weakf!(self.client).call(&signed, num.into(), Default::default()), }; - result + future::done(result .map(|b| b.output.into()) .map_err(errors::from_call_error) + ).boxed() } - fn estimate_gas(&self, request: CallRequest, num: Trailing) -> Result { + fn estimate_gas(&self, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); let signed = self.sign_call(request)?; - take_weak!(self.client).estimate_gas(&signed, num.0.into()) + future::done(take_weakf!(self.client).estimate_gas(&signed, num.0.into()) .map(Into::into) .map_err(errors::from_call_error) + ).boxed() } fn compile_lll(&self, _: String) -> Result { diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index 2e129d31e..fdd5e193b 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -38,7 +38,7 @@ use rlp::{UntrustedRlp, View}; use util::sha3::{SHA3_NULL_RLP, SHA3_EMPTY_LIST_RLP}; use util::{RwLock, U256}; -use futures::{future, Future, BoxFuture}; +use futures::{future, Future, BoxFuture, IntoFuture}; use futures::sync::oneshot; use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; @@ -153,6 +153,27 @@ impl EthClient { .unwrap_or_else(|| future::err(err_no_context()).boxed()) }).boxed() } + + // helper for getting proved execution. + fn proved_execution(&self, req: CallRequest, num: Trailing) -> Result, Error> { + let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone()); + let req: CRequest = req.into(); + let id = num.0.into(); + + let from = request.from.unwrap_or(Address::zero()); + let action = request.to.map_or(Action::Create, Action::Call); + let gas: request.gas.unwrap_or(U256::from(10_000_000)); + let value = request.value.unwrap_or_else(U256::zero); + let data = request.data.map_or_else(Vec::new, |d| d.to_vec()); + + sync.with_context(|ctx| { + let nonce_fut = req.nonce.map(Some).ok_or(err_no_context()) + .or_else(|_| self.account(from, id).map(|acc| acc.map(|a| a.nonce))); + + let gas_price_fut = req.gas_price.map(Some).ok_or(err_no_context()) + .or_else(|_| unimplemented!()) + }) + } } impl Eth for EthClient { @@ -328,12 +349,25 @@ impl Eth for EthClient { self.send_raw_transaction(raw) } - fn call(&self, req: CallRequest, num: Trailing) -> Result { - Err(errors::unimplemented(None)) + fn call(&self, req: CallRequest, num: Trailing) -> BoxFuture { + self.proved_execution().and_then(|res| { + match res { + Ok(Some(exec)) => Ok(exec.output.into()), + Ok(None) => Err(errors::unknown_block()), + Err(e) => Err(errors::execution(e)), + } + }).boxed() } - fn estimate_gas(&self, req: CallRequest, num: Trailing) -> Result { - Err(errors::unimplemented(None)) + fn estimate_gas(&self, req: CallRequest, num: Trailing) -> BoxFuture { + // TODO: binary chop for more accurate estimates. + self.proved_execution().and_then(|res| { + match res { + Ok(Some(exec)) => Ok((exec.refunded + exec.gas_used).into()), + Ok(None) => Err(errors::unknown_block()), + Err(e) => Err(errors::execution(e)), + } + }).boxed() } fn transaction_by_hash(&self, hash: RpcH256) -> Result, Error> { @@ -361,19 +395,20 @@ impl Eth for EthClient { } fn compilers(&self) -> Result, Error> { - Err(errors::unimplemented(None)) + Err(errors::deprecated("Compilation functionality is deprecated.".to_string())) + } - fn compile_lll(&self, _code: String) -> Result { - Err(errors::unimplemented(None)) + fn compile_lll(&self, _: String) -> Result { + Err(errors::deprecated("Compilation of LLL via RPC is deprecated".to_string())) } - fn compile_solidity(&self, _code: String) -> Result { - Err(errors::unimplemented(None)) + fn compile_serpent(&self, _: String) -> Result { + Err(errors::deprecated("Compilation of Serpent via RPC is deprecated".to_string())) } - fn compile_serpent(&self, _code: String) -> Result { - Err(errors::unimplemented(None)) + fn compile_solidity(&self, _: String) -> Result { + Err(errors::deprecated("Compilation of Solidity via RPC is deprecated".to_string())) } fn logs(&self, _filter: Filter) -> Result, Error> { diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index eaf608c60..365ad9320 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -110,12 +110,12 @@ build_rpc_trait! { fn submit_transaction(&self, Bytes) -> Result; /// Call contract, returning the output data. - #[rpc(name = "eth_call")] - fn call(&self, CallRequest, Trailing) -> Result; + #[rpc(async, name = "eth_call")] + fn call(&self, CallRequest, Trailing) -> BoxFuture; /// Estimate gas needed for execution of given contract. - #[rpc(name = "eth_estimateGas")] - fn estimate_gas(&self, CallRequest, Trailing) -> Result; + #[rpc(async, name = "eth_estimateGas")] + fn estimate_gas(&self, CallRequest, Trailing) -> BoxFuture; /// Get transaction by its hash. #[rpc(name = "eth_getTransactionByHash")]