Traces error handling (#4849)
This commit is contained in:
parent
7c45178076
commit
2dca24cc28
@ -14,7 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<TraceError> for Error {
|
||||
fn from(err: TraceError) -> Self {
|
||||
Error::Trace(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TrieError> for Error {
|
||||
fn from(err: TrieError) -> Self {
|
||||
Error::Trie(err)
|
||||
@ -60,7 +51,6 @@ impl<E> From<Box<E>> for Error where Error: From<E> {
|
||||
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),
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! `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)
|
||||
}
|
||||
}
|
@ -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};
|
||||
|
@ -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,
|
||||
}
|
||||
|
43
rpc/src/v1/helpers/fake_sign.rs
Normal file
43
rpc/src/v1/helpers/fake_sign.rs
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<B: MiningBlockChainClient, M: MinerService>(
|
||||
client: &Weak<B>,
|
||||
miner: &Weak<M>,
|
||||
request: CallRequest,
|
||||
) -> Result<SignedTransaction, Error> {
|
||||
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))
|
||||
}
|
@ -19,6 +19,7 @@ pub mod errors;
|
||||
|
||||
pub mod block_import;
|
||||
pub mod dispatch;
|
||||
pub mod fake_sign;
|
||||
pub mod informant;
|
||||
|
||||
mod network_settings;
|
||||
|
@ -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<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
|
||||
Ok(Some(block))
|
||||
}
|
||||
|
||||
fn sign_call(&self, request: CRequest) -> Result<SignedTransaction, Error> {
|
||||
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<Vec<H160>, Error> {
|
||||
let store = take_weak!(self.accounts);
|
||||
store
|
||||
@ -654,7 +641,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
|
||||
fn call(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes, Error> {
|
||||
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<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
||||
|
||||
fn estimate_gas(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256, Error> {
|
||||
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(),
|
||||
};
|
||||
|
@ -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<Vec<LocalizedTrace>, Error> {
|
||||
fn filter(&self, _filter: TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn block_traces(&self, _block_number: BlockNumber) -> Result<Vec<LocalizedTrace>, Error> {
|
||||
fn block_traces(&self, _block_number: BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn transaction_traces(&self, _transaction_hash: H256) -> Result<Vec<LocalizedTrace>, Error> {
|
||||
fn transaction_traces(&self, _transaction_hash: H256) -> Result<Option<Vec<LocalizedTrace>>, 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<String>, _block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
|
||||
fn call(&self, _request: CallRequest, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
|
||||
fn raw_transaction(&self, _raw_transaction: Bytes, _flags: Vec<String>, _block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
|
||||
fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec<String>) -> Result<Option<TraceResults>, Error> {
|
||||
fn replay_transaction(&self, _transaction_hash: H256, _flags: Vec<String>) -> Result<TraceResults, Error> {
|
||||
Err(errors::light_unimplemented(None))
|
||||
}
|
||||
}
|
||||
|
@ -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<String>) -> CallAnalytics {
|
||||
@ -38,12 +38,12 @@ fn to_call_analytics(flags: Vec<String>) -> CallAnalytics {
|
||||
}
|
||||
|
||||
/// Traces api implementation.
|
||||
pub struct TracesClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||
pub struct TracesClient<C, M> {
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
}
|
||||
|
||||
impl<C, M> TracesClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||
impl<C, M> TracesClient<C, M> {
|
||||
/// Creates new Traces client.
|
||||
pub fn new(client: &Arc<C>, miner: &Arc<M>) -> Self {
|
||||
TracesClient {
|
||||
@ -51,86 +51,59 @@ impl<C, M> TracesClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||
miner: Arc::downgrade(miner),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: share with eth.rs
|
||||
fn sign_call(&self, request: CRequest) -> Result<SignedTransaction, Error> {
|
||||
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<C, M> Traces for TracesClient<C, M> where C: BlockChainClient + 'static, M: MinerService + 'static {
|
||||
fn filter(&self, filter: TraceFilter) -> Result<Vec<LocalizedTrace>, 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<C, M> Traces for TracesClient<C, M> where C: MiningBlockChainClient + 'static, M: MinerService + 'static {
|
||||
fn filter(&self, filter: TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, 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<Vec<LocalizedTrace>, 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<Option<Vec<LocalizedTrace>>, 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<Vec<LocalizedTrace>, 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<Option<Vec<LocalizedTrace>>, 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<Index>) -> Result<Option<LocalizedTrace>, 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<String>, block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
|
||||
fn call(&self, request: CallRequest, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
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<String>, block: Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error> {
|
||||
fn raw_transaction(&self, raw_transaction: Bytes, flags: Vec<String>, block: Trailing<BlockNumber>) -> Result<TraceResults, Error> {
|
||||
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<String>) -> Result<Option<TraceResults>, 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<String>) -> Result<TraceResults, Error> {
|
||||
take_weak!(self.client).replay(TransactionId::Hash(transaction_hash.into()), to_call_analytics(flags))
|
||||
.map(TraceResults::from)
|
||||
.map_err(errors::from_call_error)
|
||||
}
|
||||
}
|
||||
|
@ -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()));
|
||||
|
@ -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<TestBlockChainClient>,
|
||||
client: Arc<TestBlockChainClient>,
|
||||
_miner: Arc<TestMinerService>,
|
||||
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()));
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ build_rpc_trait! {
|
||||
pub trait Traces {
|
||||
/// Returns traces matching given filter.
|
||||
#[rpc(name = "trace_filter")]
|
||||
fn filter(&self, TraceFilter) -> Result<Vec<LocalizedTrace>, Error>;
|
||||
fn filter(&self, TraceFilter) -> Result<Option<Vec<LocalizedTrace>>, 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<Vec<LocalizedTrace>, Error>;
|
||||
fn transaction_traces(&self, H256) -> Result<Option<Vec<LocalizedTrace>>, Error>;
|
||||
|
||||
/// Returns all traces produced at given block.
|
||||
#[rpc(name = "trace_block")]
|
||||
fn block_traces(&self, BlockNumber) -> Result<Vec<LocalizedTrace>, Error>;
|
||||
fn block_traces(&self, BlockNumber) -> Result<Option<Vec<LocalizedTrace>>, Error>;
|
||||
|
||||
/// Executes the given call and returns a number of possible traces for it.
|
||||
#[rpc(name = "trace_call")]
|
||||
fn call(&self, CallRequest, Vec<String>, Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error>;
|
||||
fn call(&self, CallRequest, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
|
||||
|
||||
/// Executes the given raw transaction and returns a number of possible traces for it.
|
||||
#[rpc(name = "trace_rawTransaction")]
|
||||
fn raw_transaction(&self, Bytes, Vec<String>, Trailing<BlockNumber>) -> Result<Option<TraceResults>, Error>;
|
||||
fn raw_transaction(&self, Bytes, Vec<String>, Trailing<BlockNumber>) -> Result<TraceResults, Error>;
|
||||
|
||||
/// 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<String>) -> Result<Option<TraceResults>, Error>;
|
||||
fn replay_transaction(&self, H256, Vec<String>) -> Result<TraceResults, Error>;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user