From 2dca24cc28ab06fdab3a4b183ca59913022d0ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 14 Mar 2017 13:04:32 +0100 Subject: [PATCH] Traces error handling (#4849) --- ethcore/src/client/error.rs | 10 ---- ethcore/src/trace/error.rs | 41 ------------- ethcore/src/trace/mod.rs | 2 - rpc/src/v1/helpers/errors.rs | 22 +++---- rpc/src/v1/helpers/fake_sign.rs | 43 ++++++++++++++ rpc/src/v1/helpers/mod.rs | 1 + rpc/src/v1/impls/eth.rs | 23 ++------ rpc/src/v1/impls/light/trace.rs | 12 ++-- rpc/src/v1/impls/traces.rs | 95 +++++++++++-------------------- rpc/src/v1/tests/mocked/parity.rs | 8 +-- rpc/src/v1/tests/mocked/traces.rs | 84 +++++++++++++++++++++++++-- rpc/src/v1/traits/traces.rs | 12 ++-- 12 files changed, 188 insertions(+), 165 deletions(-) delete mode 100644 ethcore/src/trace/error.rs create mode 100644 rpc/src/v1/helpers/fake_sign.rs diff --git a/ethcore/src/client/error.rs b/ethcore/src/client/error.rs index 9f22673b7..ff8b6d2ce 100644 --- a/ethcore/src/client/error.rs +++ b/ethcore/src/client/error.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use trace::Error as TraceError; use util::UtilError; use std::fmt::{Display, Formatter, Error as FmtError}; @@ -23,8 +22,6 @@ use util::trie::TrieError; /// Client configuration errors. #[derive(Debug)] pub enum Error { - /// TraceDB configuration error. - Trace(TraceError), /// TrieDB-related error. Trie(TrieError), /// Database error @@ -33,12 +30,6 @@ pub enum Error { Util(UtilError), } -impl From for Error { - fn from(err: TraceError) -> Self { - Error::Trace(err) - } -} - impl From for Error { fn from(err: TrieError) -> Self { Error::Trie(err) @@ -60,7 +51,6 @@ impl From> for Error where Error: From { impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Error::Trace(ref err) => write!(f, "{}", err), Error::Trie(ref err) => write!(f, "{}", err), Error::Util(ref err) => write!(f, "{}", err), Error::Database(ref s) => write!(f, "Database error: {}", s), diff --git a/ethcore/src/trace/error.rs b/ethcore/src/trace/error.rs deleted file mode 100644 index 081045d85..000000000 --- a/ethcore/src/trace/error.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! `TraceDB` errors. - -use std::fmt::{Display, Formatter, Error as FmtError}; - -const RESYNC_ERR: &'static str = -"Your current parity installation has synced without transaction tracing. -To use Parity with transaction tracing, you'll need to resync with tracing. -To do this, remove or move away your current database and restart parity. e.g.: - -> mv ~/.parity/906a34e69aec8c0d /tmp -> parity"; - -/// `TraceDB` errors. -#[derive(Debug)] -pub enum Error { - /// Returned when tracing is enabled, - /// but database does not contain traces of old transactions. - ResyncRequired, -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - write!(f, "{}", RESYNC_ERR) - } -} diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index c63890ae9..2d13e3260 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -19,7 +19,6 @@ mod bloom; mod config; mod db; -mod error; mod executive_tracer; mod import; mod noop_tracer; @@ -28,7 +27,6 @@ pub use types::trace_types::{filter, flat, localized, trace}; pub use types::trace_types::error::Error as TraceError; pub use self::config::Config; pub use self::db::TraceDB; -pub use self::error::Error; pub use types::trace_types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff}; pub use types::trace_types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces}; pub use self::noop_tracer::{NoopTracer, NoopVMTracer}; diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 1f98b922d..e8fcee303 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -32,7 +32,6 @@ mod codes { pub const NO_WORK: i64 = -32001; pub const NO_AUTHOR: i64 = -32002; pub const NO_NEW_WORK: i64 = -32003; - pub const NOT_ENOUGH_DATA: i64 = -32006; pub const UNKNOWN_ERROR: i64 = -32009; pub const TRANSACTION_ERROR: i64 = -32010; pub const EXECUTION_ERROR: i64 = -32015; @@ -41,9 +40,6 @@ mod codes { pub const ACCOUNT_LOCKED: i64 = -32020; pub const PASSWORD_INVALID: i64 = -32021; pub const ACCOUNT_ERROR: i64 = -32023; - pub const SIGNER_DISABLED: i64 = -32030; - pub const DAPPS_DISABLED: i64 = -32031; - pub const NETWORK_DISABLED: i64 = -32035; pub const REQUEST_REJECTED: i64 = -32040; pub const REQUEST_REJECTED_LIMIT: i64 = -32041; pub const REQUEST_NOT_FOUND: i64 = -32042; @@ -174,9 +170,9 @@ pub fn no_author() -> Error { pub fn not_enough_data() -> Error { Error { - code: ErrorCode::ServerError(codes::NOT_ENOUGH_DATA), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "The node does not have enough data to compute the given statistic.".into(), - data: None + data: None, } } @@ -190,25 +186,25 @@ pub fn token(e: String) -> Error { pub fn signer_disabled() -> Error { Error { - code: ErrorCode::ServerError(codes::SIGNER_DISABLED), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "Trusted Signer is disabled. This API is not available.".into(), - data: None + data: None, } } pub fn dapps_disabled() -> Error { Error { - code: ErrorCode::ServerError(codes::DAPPS_DISABLED), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "Dapps Server is disabled. This API is not available.".into(), - data: None + data: None, } } pub fn network_disabled() -> Error { Error { - code: ErrorCode::ServerError(codes::NETWORK_DISABLED), + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), message: "Network is disabled or not yet up.".into(), - data: None + data: None, } } @@ -321,7 +317,7 @@ pub fn from_call_error(error: CallError) -> Error { pub fn unknown_block() -> Error { Error { - code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), + code: ErrorCode::InvalidParams, message: "Unknown block number".into(), data: None, } diff --git a/rpc/src/v1/helpers/fake_sign.rs b/rpc/src/v1/helpers/fake_sign.rs new file mode 100644 index 000000000..c8e835bb3 --- /dev/null +++ b/rpc/src/v1/helpers/fake_sign.rs @@ -0,0 +1,43 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::Weak; +use ethcore::client::MiningBlockChainClient; +use ethcore::miner::MinerService; +use ethcore::transaction::{Transaction, SignedTransaction, Action}; + +use jsonrpc_core::Error; +use v1::helpers::CallRequest; +use v1::helpers::dispatch::default_gas_price; + +pub fn sign_call( + client: &Weak, + miner: &Weak, + request: CallRequest, +) -> Result { + let client = take_weak!(client); + let miner = take_weak!(miner); + let from = request.from.unwrap_or(0.into()); + + 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_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)), + value: request.value.unwrap_or(0.into()), + data: request.data.map_or_else(Vec::new, |d| d.to_vec()) + }.fake_sign(from)) +} diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index 1d6bd14f3..ae8990cdc 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -19,6 +19,7 @@ pub mod errors; pub mod block_import; pub mod dispatch; +pub mod fake_sign; pub mod informant; mod network_settings; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 341ab13d8..52bc2de71 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -23,7 +23,7 @@ use std::sync::{Arc, Weak}; use futures::{self, future, BoxFuture, Future}; use rlp::{self, UntrustedRlp, View}; use time::get_time; -use util::{H160, H256, Address, U256, H64, Uint}; +use util::{H160, H256, Address, U256, H64}; use util::sha3::Hashable; use util::Mutex; @@ -36,14 +36,14 @@ use ethcore::filter::Filter as EthcoreFilter; use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; use ethcore::log_entry::LogEntry; use ethcore::miner::{MinerService, ExternalMinerService}; -use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; +use ethcore::transaction::SignedTransaction; use ethcore::snapshot::SnapshotService; use ethsync::{SyncProvider}; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; -use v1::helpers::{CallRequest as CRequest, errors, limit_logs}; +use v1::helpers::{errors, limit_logs, fake_sign}; use v1::helpers::dispatch::{Dispatcher, FullDispatcher, default_gas_price}; use v1::helpers::block_import::is_major_importing; use v1::traits::Eth; @@ -222,19 +222,6 @@ impl EthClient where Ok(Some(block)) } - fn sign_call(&self, request: CRequest) -> Result { - let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); - let from = request.from.unwrap_or(Address::zero()); - Ok(EthTransaction { - nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), - action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or(U256::from(50_000_000)), - gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)), - value: request.value.unwrap_or_else(U256::zero), - data: request.data.map_or_else(Vec::new, |d| d.to_vec()) - }.fake_sign(from)) - } - fn dapp_accounts(&self, dapp: DappId) -> Result, Error> { let store = take_weak!(self.accounts); store @@ -654,7 +641,7 @@ impl Eth for EthClient where fn call(&self, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); - let signed = match self.sign_call(request) { + let signed = match fake_sign::sign_call(&self.client, &self.miner, request) { Ok(signed) => signed, Err(e) => return future::err(e).boxed(), }; @@ -672,7 +659,7 @@ impl Eth for EthClient where fn estimate_gas(&self, request: CallRequest, num: Trailing) -> BoxFuture { let request = CallRequest::into(request); - let signed = match self.sign_call(request) { + let signed = match fake_sign::sign_call(&self.client, &self.miner, request) { Ok(signed) => signed, Err(e) => return future::err(e).boxed(), }; diff --git a/rpc/src/v1/impls/light/trace.rs b/rpc/src/v1/impls/light/trace.rs index 5f785ed1b..00d19dc24 100644 --- a/rpc/src/v1/impls/light/trace.rs +++ b/rpc/src/v1/impls/light/trace.rs @@ -27,15 +27,15 @@ use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, By pub struct TracesClient; impl Traces for TracesClient { - fn filter(&self, _filter: TraceFilter) -> Result, Error> { + fn filter(&self, _filter: TraceFilter) -> Result>, Error> { Err(errors::light_unimplemented(None)) } - fn block_traces(&self, _block_number: BlockNumber) -> Result, Error> { + fn block_traces(&self, _block_number: BlockNumber) -> Result>, Error> { Err(errors::light_unimplemented(None)) } - fn transaction_traces(&self, _transaction_hash: H256) -> Result, Error> { + fn transaction_traces(&self, _transaction_hash: H256) -> Result>, Error> { Err(errors::light_unimplemented(None)) } @@ -43,15 +43,15 @@ impl Traces for TracesClient { Err(errors::light_unimplemented(None)) } - fn call(&self, _request: CallRequest, _flags: Vec, _block: Trailing) -> Result, Error> { + fn call(&self, _request: CallRequest, _flags: Vec, _block: Trailing) -> Result { Err(errors::light_unimplemented(None)) } - fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec, _block: Trailing) -> Result, Error> { + fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec, _block: Trailing) -> Result { Err(errors::light_unimplemented(None)) } - fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec) -> Result, Error> { + fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec) -> Result { Err(errors::light_unimplemented(None)) } } diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 9fe92518b..b4be40a56 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -19,14 +19,14 @@ use std::sync::{Weak, Arc}; use rlp::{UntrustedRlp, View}; -use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId}; +use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId}; use ethcore::miner::MinerService; -use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; +use ethcore::transaction::SignedTransaction; use jsonrpc_core::Error; use jsonrpc_macros::Trailing; use v1::traits::Traces; -use v1::helpers::{errors, CallRequest as CRequest}; +use v1::helpers::{errors, fake_sign}; use v1::types::{TraceFilter, LocalizedTrace, BlockNumber, Index, CallRequest, Bytes, TraceResults, H256}; fn to_call_analytics(flags: Vec) -> CallAnalytics { @@ -38,12 +38,12 @@ fn to_call_analytics(flags: Vec) -> CallAnalytics { } /// Traces api implementation. -pub struct TracesClient where C: BlockChainClient, M: MinerService { +pub struct TracesClient { client: Weak, miner: Weak, } -impl TracesClient where C: BlockChainClient, M: MinerService { +impl TracesClient { /// Creates new Traces client. pub fn new(client: &Arc, miner: &Arc) -> Self { TracesClient { @@ -51,86 +51,59 @@ impl TracesClient where C: BlockChainClient, M: MinerService { miner: Arc::downgrade(miner), } } - - // TODO: share with eth.rs - fn sign_call(&self, request: CRequest) -> Result { - let client = take_weak!(self.client); - let miner = take_weak!(self.miner); - let from = request.from.unwrap_or(0.into()); - Ok(EthTransaction { - 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_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), - value: request.value.unwrap_or(0.into()), - data: request.data.map_or_else(Vec::new, |d| d.to_vec()) - }.fake_sign(from)) - } } -impl Traces for TracesClient where C: BlockChainClient + 'static, M: MinerService + 'static { - fn filter(&self, filter: TraceFilter) -> Result, Error> { - let client = take_weak!(self.client); - let traces = client.filter_traces(filter.into()); - let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - Ok(traces) +impl Traces for TracesClient where C: MiningBlockChainClient + 'static, M: MinerService + 'static { + fn filter(&self, filter: TraceFilter) -> Result>, Error> { + Ok(take_weak!(self.client).filter_traces(filter.into()) + .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } - fn block_traces(&self, block_number: BlockNumber) -> Result, Error> { - let client = take_weak!(self.client); - let traces = client.block_traces(block_number.into()); - let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - Ok(traces) + fn block_traces(&self, block_number: BlockNumber) -> Result>, Error> { + Ok(take_weak!(self.client).block_traces(block_number.into()) + .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } - fn transaction_traces(&self, transaction_hash: H256) -> Result, Error> { - let client = take_weak!(self.client); - let traces = client.transaction_traces(TransactionId::Hash(transaction_hash.into())); - let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(LocalizedTrace::from).collect()); - Ok(traces) + fn transaction_traces(&self, transaction_hash: H256) -> Result>, Error> { + Ok(take_weak!(self.client).transaction_traces(TransactionId::Hash(transaction_hash.into())) + .map(|traces| traces.into_iter().map(LocalizedTrace::from).collect())) } fn trace(&self, transaction_hash: H256, address: Vec) -> Result, Error> { - let client = take_weak!(self.client); let id = TraceId { transaction: TransactionId::Hash(transaction_hash.into()), address: address.into_iter().map(|i| i.value()).collect() }; - let trace = client.trace(id); - let trace = trace.map(LocalizedTrace::from); - Ok(trace) + Ok(take_weak!(self.client).trace(id) + .map(LocalizedTrace::from)) } - fn call(&self, request: CallRequest, flags: Vec, block: Trailing) -> Result, Error> { + fn call(&self, request: CallRequest, flags: Vec, block: Trailing) -> Result { let block = block.0; let request = CallRequest::into(request); - let signed = self.sign_call(request)?; - Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) { - Ok(e) => Some(TraceResults::from(e)), - _ => None, - }) + let signed = fake_sign::sign_call(&self.client, &self.miner, request)?; + + take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) + .map(TraceResults::from) + .map_err(errors::from_call_error) } - fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec, block: Trailing) -> Result, Error> { + fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec, block: Trailing) -> Result { let block = block.0; - UntrustedRlp::new(&raw_transaction.into_vec()).as_val() - .map_err(|e| errors::invalid_params("Transaction is not valid RLP", e)) - .and_then(|tx| SignedTransaction::new(tx).map_err(errors::from_transaction_error)) - .and_then(|signed| { - Ok(match take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) { - Ok(e) => Some(TraceResults::from(e)), - _ => None, - }) - }) + let tx = UntrustedRlp::new(&raw_transaction.into_vec()).as_val().map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?; + let signed = SignedTransaction::new(tx).map_err(errors::from_transaction_error)?; + + take_weak!(self.client).call(&signed, block.into(), to_call_analytics(flags)) + .map(TraceResults::from) + .map_err(errors::from_call_error) } - fn replay_transaction(&self, transaction_hash: H256, flags: Vec) -> Result, Error> { - Ok(match take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) { - Ok(e) => Some(TraceResults::from(e)), - _ => None, - }) + fn replay_transaction(&self, transaction_hash: H256, flags: Vec) -> Result { + take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags)) + .map(TraceResults::from) + .map_err(errors::from_call_error) } } diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index a53a86447..59cde8594 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -357,7 +357,7 @@ fn rpc_parity_unsigned_transactions_count_when_signer_disabled() { let io = deps.default_client(); let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } @@ -393,7 +393,7 @@ fn rpc_parity_signer_port() { // when let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#; - let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; + let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; // then assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); @@ -411,7 +411,7 @@ fn rpc_parity_dapps_port() { // when let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#; let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#; - let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; + let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; // then assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); @@ -429,7 +429,7 @@ fn rpc_parity_dapps_interface() { // when let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsInterface", "params": [], "id": 1}"#; let response1 = r#"{"jsonrpc":"2.0","result":"127.0.0.1","id":1}"#; - let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; + let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#; // then assert_eq!(io1.handle_request_sync(request), Some(response1.to_owned())); diff --git a/rpc/src/v1/tests/mocked/traces.rs b/rpc/src/v1/tests/mocked/traces.rs index 1d7c36a2b..83a266d2f 100644 --- a/rpc/src/v1/tests/mocked/traces.rs +++ b/rpc/src/v1/tests/mocked/traces.rs @@ -16,17 +16,17 @@ use std::sync::Arc; -use ethcore::executed::{CallType, Executed}; +use ethcore::executed::{CallType, Executed, CallError}; use ethcore::trace::trace::{Action, Res, Call}; use ethcore::trace::LocalizedTrace; -use ethcore::client::{TestBlockChainClient}; +use ethcore::client::TestBlockChainClient; use jsonrpc_core::IoHandler; use v1::tests::helpers::{TestMinerService}; use v1::{Traces, TracesClient}; struct Tester { - _client: Arc, + client: Arc, _miner: Arc, io: IoHandler, } @@ -69,7 +69,7 @@ fn io() -> Tester { io.extend_with(traces.to_delegate()); Tester { - _client: client, + client: client, _miner: miner, io: io, } @@ -85,6 +85,17 @@ fn rpc_trace_filter() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_filter_missing_trace() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_filter","params": [{}],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_block() { let tester = io(); @@ -95,6 +106,17 @@ fn rpc_trace_block() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_block_missing_traces() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_block","params": ["0x10"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_transaction() { let tester = io(); @@ -105,6 +127,17 @@ fn rpc_trace_transaction() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_transaction_missing_trace() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_transaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_get() { let tester = io(); @@ -115,6 +148,16 @@ fn rpc_trace_get() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_get_missing_trace() { + let tester = io(); + *tester.client.traces.write() = None; + + let request = r#"{"jsonrpc":"2.0","method":"trace_get","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["0","0","0"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_call() { let tester = io(); @@ -125,6 +168,17 @@ fn rpc_trace_call() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_call_state_pruned() { + let tester = io(); + *tester.client.execution_result.write() = Some(Err(CallError::StatePruned)); + + let request = r#"{"jsonrpc":"2.0","method":"trace_call","params":[{}, ["stateDiff", "vmTrace", "trace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive.","data":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_raw_transaction() { let tester = io(); @@ -135,6 +189,17 @@ fn rpc_trace_raw_transaction() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } +#[test] +fn rpc_trace_raw_transaction_state_pruned() { + let tester = io(); + *tester.client.execution_result.write() = Some(Err(CallError::StatePruned)); + + let request = r#"{"jsonrpc":"2.0","method":"trace_rawTransaction","params":["0xf869018609184e72a0008276c094d46e8dd67c5d32be8058bb8eb970870f07244567849184e72a801ba0617f39c1a107b63302449c476d96a6cb17a5842fc98ff0c5bcf4d5c4d8166b95a009fdb6097c6196b9bbafc3a59f02f38d91baeef23d0c60a8e4f23c7714cea3a9", ["stateDiff", "vmTrace", "trace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive.","data":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} + #[test] fn rpc_trace_replay_transaction() { let tester = io(); @@ -144,3 +209,14 @@ fn rpc_trace_replay_transaction() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); } + +#[test] +fn rpc_trace_replay_transaction_state_pruned() { + let tester = io(); + *tester.client.execution_result.write() = Some(Err(CallError::StatePruned)); + + let request = r#"{"jsonrpc":"2.0","method":"trace_replayTransaction","params":["0x0000000000000000000000000000000000000000000000000000000000000005", ["trace", "stateDiff", "vmTrace"]],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive.","data":null},"id":1}"#; + + assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/traits/traces.rs b/rpc/src/v1/traits/traces.rs index fa2b14cf3..64b37ac1d 100644 --- a/rpc/src/v1/traits/traces.rs +++ b/rpc/src/v1/traits/traces.rs @@ -25,7 +25,7 @@ build_rpc_trait! { pub trait Traces { /// Returns traces matching given filter. #[rpc(name = "trace_filter")] - fn filter(&self, TraceFilter) -> Result, Error>; + fn filter(&self, TraceFilter) -> Result>, Error>; /// Returns transaction trace at given index. #[rpc(name = "trace_get")] @@ -33,22 +33,22 @@ build_rpc_trait! { /// Returns all traces of given transaction. #[rpc(name = "trace_transaction")] - fn transaction_traces(&self, H256) -> Result, Error>; + fn transaction_traces(&self, H256) -> Result>, Error>; /// Returns all traces produced at given block. #[rpc(name = "trace_block")] - fn block_traces(&self, BlockNumber) -> Result, Error>; + 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, Error>; + fn call(&self, CallRequest, Vec, Trailing) -> Result; /// Executes the given raw transaction and returns a number of possible traces for it. #[rpc(name = "trace_rawTransaction")] - fn raw_transaction(&self, Bytes, Vec, Trailing) -> Result, Error>; + fn raw_transaction(&self, Bytes, Vec, Trailing) -> Result; /// Executes the transaction with the given hash and returns a number of possible traces for it. #[rpc(name = "trace_replayTransaction")] - fn replay_transaction(&self, H256, Vec) -> Result, Error>; + fn replay_transaction(&self, H256, Vec) -> Result; } }