diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 9e25b6671..af95af20b 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -155,7 +155,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { pub fn transact_virtual(&'a mut self, t: &SignedTransaction, options: TransactOptions) -> Result { let sender = t.sender(); let balance = self.state.balance(&sender)?; - let needed_balance = t.value + t.gas * t.gas_price; + let needed_balance = t.value.saturating_add(t.gas.saturating_mul(t.gas_price)); if balance < needed_balance { // give the sender a sufficient balance self.state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty)?; diff --git a/rpc/src/v1/helpers/fake_sign.rs b/rpc/src/v1/helpers/fake_sign.rs index 21cb0cfe1..c5b95f6a4 100644 --- a/rpc/src/v1/helpers/fake_sign.rs +++ b/rpc/src/v1/helpers/fake_sign.rs @@ -18,6 +18,7 @@ use std::sync::Arc; use ethcore::client::MiningBlockChainClient; use ethcore::miner::MinerService; use ethcore::transaction::{Transaction, SignedTransaction, Action}; +use util::U256; use jsonrpc_core::Error; use v1::helpers::CallRequest; @@ -27,13 +28,22 @@ pub fn sign_call( client: &Arc, miner: &Arc, request: CallRequest, + gas_cap: bool, ) -> Result { let from = request.from.unwrap_or(0.into()); + let mut gas = request.gas.unwrap_or(U256::max_value()); + if gas_cap { + let max_gas = 50_000_000.into(); + if gas > max_gas { + warn!("Gas limit capped to {} (from {})", max_gas, gas); + gas = max_gas + } + } Ok(Transaction { nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or(50_000_000.into()), + gas, gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&**client, &**miner)), value: request.value.unwrap_or(0.into()), data: request.data.unwrap_or_default(), diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 6ae614db1..2e9a5b43d 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -641,9 +641,9 @@ impl Eth for EthClient where self.send_raw_transaction(raw) } - fn call(&self, request: CallRequest, num: Trailing) -> BoxFuture { + fn call(&self, meta: Self::Metadata, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); - let signed = match fake_sign::sign_call(&self.client, &self.miner, request) { + let signed = match fake_sign::sign_call(&self.client, &self.miner, request, meta.is_dapp()) { Ok(signed) => signed, Err(e) => return future::err(e).boxed(), }; @@ -659,9 +659,9 @@ impl Eth for EthClient where ).boxed() } - fn estimate_gas(&self, request: CallRequest, num: Trailing) -> BoxFuture { + fn estimate_gas(&self, meta: Self::Metadata, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); - let signed = match fake_sign::sign_call(&self.client, &self.miner, request) { + let signed = match fake_sign::sign_call(&self.client, &self.miner, request, meta.is_dapp()) { Ok(signed) => signed, Err(e) => return future::err(e).boxed(), }; diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index fd03f1226..d33b5a06f 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -383,7 +383,7 @@ impl Eth for EthClient { self.send_raw_transaction(raw) } - fn call(&self, req: CallRequest, num: Trailing) -> BoxFuture { + fn call(&self, _meta: Self::Metadata, req: CallRequest, num: Trailing) -> BoxFuture { self.fetcher().proved_execution(req, num).and_then(|res| { match res { Ok(exec) => Ok(exec.output.into()), @@ -392,7 +392,7 @@ impl Eth for EthClient { }).boxed() } - fn estimate_gas(&self, req: CallRequest, num: Trailing) -> BoxFuture { + fn estimate_gas(&self, _meta: Self::Metadata, req: CallRequest, num: Trailing) -> BoxFuture { // TODO: binary chop for more accurate estimates. self.fetcher().proved_execution(req, num).and_then(|res| { match res { diff --git a/rpc/src/v1/impls/light/trace.rs b/rpc/src/v1/impls/light/trace.rs index 00d19dc24..e8abac74c 100644 --- a/rpc/src/v1/impls/light/trace.rs +++ b/rpc/src/v1/impls/light/trace.rs @@ -17,7 +17,9 @@ //! Traces api implementation. use jsonrpc_core::Error; +use jsonrpc_core::futures::{future, Future, BoxFuture}; use jsonrpc_macros::Trailing; +use v1::Metadata; use v1::traits::Traces; use v1::helpers::errors; use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256}; @@ -27,6 +29,8 @@ use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, By pub struct TracesClient; impl Traces for TracesClient { + type Metadata = Metadata; + fn filter(&self, _filter: TraceFilter) -> Result>, Error> { Err(errors::light_unimplemented(None)) } @@ -43,8 +47,8 @@ impl Traces for TracesClient { Err(errors::light_unimplemented(None)) } - fn call(&self, _request: CallRequest, _flags: Vec, _block: Trailing) -> Result { - Err(errors::light_unimplemented(None)) + fn call(&self, _meta: Self::Metadata, _request: CallRequest, _flags: Vec, _block: Trailing) -> BoxFuture { + future::err(errors::light_unimplemented(None)).boxed() } fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec, _block: Trailing) -> Result { diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 2c65f4403..58be1a974 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -18,13 +18,15 @@ use std::sync::Arc; -use rlp::UntrustedRlp; use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId}; use ethcore::miner::MinerService; use ethcore::transaction::SignedTransaction; +use rlp::UntrustedRlp; use jsonrpc_core::Error; +use jsonrpc_core::futures::{self, Future, BoxFuture}; use jsonrpc_macros::Trailing; +use v1::Metadata; use v1::traits::Traces; use v1::helpers::{errors, fake_sign}; use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256}; @@ -54,6 +56,8 @@ impl TracesClient { } impl Traces for TracesClient where C: MiningBlockChainClient + 'static, M: MinerService + 'static { + type Metadata = Metadata; + fn filter(&self, filter: TraceFilter) -> Result>, Error> { Ok(self.client.filter_traces(filter.into()) .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) @@ -79,15 +83,17 @@ impl Traces for TracesClient where C: MiningBlockChainClient + 'stat .map(LocalizedTrace::from)) } - fn call(&self, request: CallRequest, flags: Vec, block: Trailing) -> Result { + fn call(&self, meta: Self::Metadata, request: CallRequest, flags: Vec, block: Trailing) -> BoxFuture { let block = block.unwrap_or_default(); let request = CallRequest::into(request); - let signed = fake_sign::sign_call(&self.client, &self.miner, request)?; + let signed = try_bf!(fake_sign::sign_call(&self.client, &self.miner, request, meta.is_dapp())); - self.client.call(&signed, block.into(), to_call_analytics(flags)) + let res = self.client.call(&signed, block.into(), to_call_analytics(flags)) .map(TraceResults::from) - .map_err(errors::call) + .map_err(errors::call); + + futures::done(res).boxed() } fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec, block: Trailing) -> Result { diff --git a/rpc/src/v1/metadata.rs b/rpc/src/v1/metadata.rs index b65003ad8..f0644d455 100644 --- a/rpc/src/v1/metadata.rs +++ b/rpc/src/v1/metadata.rs @@ -42,6 +42,15 @@ impl Metadata { _ => DappId::default(), } } + + /// Returns true if the request originates from a Dapp. + pub fn is_dapp(&self) -> bool { + if let Origin::Dapps(_) = self.origin { + true + } else { + false + } + } } impl jsonrpc_core::Metadata for Metadata {} diff --git a/rpc/src/v1/tests/mocked/traces.rs b/rpc/src/v1/tests/mocked/traces.rs index b1b297eb1..127ebd624 100644 --- a/rpc/src/v1/tests/mocked/traces.rs +++ b/rpc/src/v1/tests/mocked/traces.rs @@ -25,12 +25,12 @@ use evm::CallType; use jsonrpc_core::IoHandler; use v1::tests::helpers::{TestMinerService}; -use v1::{Traces, TracesClient}; +use v1::{Metadata, Traces, TracesClient}; struct Tester { client: Arc, _miner: Arc, - io: IoHandler, + io: IoHandler, } fn io() -> Tester { @@ -67,7 +67,7 @@ fn io() -> Tester { })); let miner = Arc::new(TestMinerService::default()); let traces = TracesClient::new(&client, &miner); - let mut io = IoHandler::new(); + let mut io = IoHandler::default(); io.extend_with(traces.to_delegate()); Tester { diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 941263335..9e7ed9715 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(async, name = "eth_call")] - fn call(&self, CallRequest, Trailing) -> BoxFuture; + #[rpc(meta, name = "eth_call")] + fn call(&self, Self::Metadata, CallRequest, Trailing) -> BoxFuture; /// Estimate gas needed for execution of given contract. - #[rpc(async, name = "eth_estimateGas")] - fn estimate_gas(&self, CallRequest, Trailing) -> BoxFuture; + #[rpc(meta, name = "eth_estimateGas")] + fn estimate_gas(&self, Self::Metadata, CallRequest, Trailing) -> BoxFuture; /// Get transaction by its hash. #[rpc(name = "eth_getTransactionByHash")] diff --git a/rpc/src/v1/traits/traces.rs b/rpc/src/v1/traits/traces.rs index 64b37ac1d..c187b6a7a 100644 --- a/rpc/src/v1/traits/traces.rs +++ b/rpc/src/v1/traits/traces.rs @@ -17,12 +17,15 @@ //! Traces specific rpc interface. use jsonrpc_core::Error; +use jsonrpc_core::futures::BoxFuture; use jsonrpc_macros::Trailing; use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256}; build_rpc_trait! { /// Traces specific rpc interface. pub trait Traces { + type Metadata; + /// Returns traces matching given filter. #[rpc(name = "trace_filter")] fn filter(&self, TraceFilter) -> Result>, Error>; @@ -40,8 +43,8 @@ build_rpc_trait! { fn block_traces(&self, BlockNumber) -> Result>, Error>; /// Executes the given call and returns a number of possible traces for it. - #[rpc(name = "trace_call")] - fn call(&self, CallRequest, Vec, Trailing) -> Result; + #[rpc(meta, name = "trace_call")] + fn call(&self, Self::Metadata, CallRequest, Vec, Trailing) -> BoxFuture; /// Executes the given raw transaction and returns a number of possible traces for it. #[rpc(name = "trace_rawTransaction")]