Merge pull request #1098 from ethcore/trace_err

pretty print trace error
This commit is contained in:
Marek Kotewicz 2016-05-19 18:00:39 +02:00
commit 852155959d
15 changed files with 117 additions and 32 deletions

View File

@ -21,7 +21,7 @@ use std::path::PathBuf;
use util::*;
use util::panics::*;
use views::BlockView;
use error::*;
use error::{Error, ImportError, ExecutionError, BlockError, ImportResult};
use header::{BlockNumber, Header};
use state::State;
use spec::Spec;
@ -38,6 +38,7 @@ use log_entry::LocalizedLogEntry;
use block_queue::{BlockQueue, BlockQueueInfo};
use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, TraceFilter};
use client::Error as ClientError;
use env_info::EnvInfo;
use executive::{Executive, Executed, TransactOptions, contract_address};
use receipt::LocalizedReceipt;
@ -101,7 +102,7 @@ const CLIENT_DB_VER_STR: &'static str = "5.3";
impl Client<CanonVerifier> {
/// Create a new client with given spec and DB path.
pub fn new(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel<NetSyncMessage> ) -> Arc<Client> {
pub fn new(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel<NetSyncMessage> ) -> Result<Arc<Client>, ClientError> {
Client::<CanonVerifier>::new_with_verifier(config, spec, path, message_channel)
}
}
@ -125,11 +126,11 @@ pub fn append_path(path: &Path, item: &str) -> String {
impl<V> Client<V> where V: Verifier {
/// Create a new client with given spec and DB path and custom verifier.
pub fn new_with_verifier(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel<NetSyncMessage> ) -> Arc<Client<V>> {
pub fn new_with_verifier(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel<NetSyncMessage> ) -> Result<Arc<Client<V>>, ClientError> {
let path = get_db_path(path, config.pruning, spec.genesis_header().hash());
let gb = spec.genesis_block();
let chain = Arc::new(BlockChain::new(config.blockchain, &gb, &path));
let tracedb = Arc::new(TraceDB::new(config.tracing, &path, chain.clone()));
let tracedb = Arc::new(try!(TraceDB::new(config.tracing, &path, chain.clone())));
let mut state_db = journaldb::new(&append_path(&path, "state"), config.pruning);
@ -143,7 +144,7 @@ impl<V> Client<V> where V: Verifier {
let panic_handler = PanicHandler::new_in_arc();
panic_handler.forward_from(&block_queue);
Arc::new(Client {
let client = Client {
chain: chain,
tracedb: tracedb,
engine: engine,
@ -154,7 +155,9 @@ impl<V> Client<V> where V: Verifier {
panic_handler: panic_handler,
verifier: PhantomData,
vm_factory: Arc::new(EvmFactory::new(config.vm_type)),
})
};
Ok(Arc::new(client))
}
/// Flush the block import queue.

View File

@ -0,0 +1,23 @@
use trace::Error as TraceError;
use std::fmt::{Display, Formatter, Error as FmtError};
/// Client configuration errors.
#[derive(Debug)]
pub enum Error {
/// TraceDB configuration error.
Trace(TraceError),
}
impl From<TraceError> for Error {
fn from(err: TraceError) -> Self {
Error::Trace(err)
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match *self {
Error::Trace(ref err) => write!(f, "{}", err)
}
}
}

View File

@ -18,11 +18,13 @@
mod client;
mod config;
mod error;
mod test_client;
mod trace;
pub use self::client::*;
pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig, Switch, VMType};
pub use self::error::Error;
pub use types::ids::*;
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
pub use self::trace::Filter as TraceFilter;

View File

@ -19,6 +19,7 @@
use util::*;
use header::BlockNumber;
use basic_types::LogBloom;
use client::Error as ClientError;
pub use types::executed::ExecutionError;
@ -134,6 +135,8 @@ pub enum ImportError {
#[derive(Debug)]
/// General error type which should be capable of representing all errors in ethcore.
pub enum Error {
/// Client configuration error.
Client(ClientError),
/// Error concerning a utility.
Util(UtilError),
/// Error concerning block processing.
@ -155,6 +158,12 @@ pub enum Error {
/// Result of import block operation.
pub type ImportResult = Result<H256, Error>;
impl From<ClientError> for Error {
fn from(err: ClientError) -> Error {
Error::Client(err)
}
}
impl From<TransactionError> for Error {
fn from(err: TransactionError) -> Error {
Error::Transaction(err)

View File

@ -53,7 +53,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
let temp = RandomTempPath::new();
{
let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected());
let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap();
for b in &blockchain.blocks_rlp() {
if Block::is_good(&b) {
let _ = client.import_block(b.clone());

View File

@ -61,7 +61,7 @@ impl ClientService {
info!("Starting {}", net_service.host_info());
info!("Configured for {} using {:?} engine", spec.name, spec.engine.name());
let client = Client::new(config, spec, db_path, net_service.io().channel());
let client = try!(Client::new(config, spec, db_path, net_service.io().channel()));
panic_handler.forward_from(client.deref());
let client_io = Arc::new(ClientIoHandler {
client: client.clone()

View File

@ -23,7 +23,7 @@ use devtools::*;
#[test]
fn imports_from_empty() {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected());
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
client.import_verified_blocks(&IoChannel::disconnected());
client.flush_queue();
}
@ -41,7 +41,7 @@ fn returns_state_root_basic() {
#[test]
fn imports_good_block() {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected());
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
let good_block = get_good_dummy_block();
if let Err(_) = client.import_block(good_block) {
panic!("error importing block being good by definition");
@ -56,7 +56,7 @@ fn imports_good_block() {
#[test]
fn query_none_block() {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected());
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
let non_existant = client.block_header(BlockID::Number(188));
assert!(non_existant.is_none());

View File

@ -139,7 +139,7 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTrans
pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected());
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
let test_spec = get_test_spec();
let test_engine = &test_spec.engine;
let state_root = test_spec.genesis_header().state_root;
@ -205,7 +205,7 @@ pub fn push_blocks_to_client(client: &Arc<Client>, timestamp_salt: u64, starting
pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected());
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
for block in &blocks {
if let Err(_) = client.import_block(block.clone()) {
panic!("panic importing block which is well-formed");

View File

@ -16,6 +16,7 @@
//! Traces config.
use bloomchain::Config as BloomConfig;
use trace::Error;
/// 3-value enum.
#[derive(Debug, Clone, Copy, PartialEq)]
@ -30,10 +31,10 @@ pub enum Switch {
impl Switch {
/// Tries to turn old switch to new value.
pub fn turn_to(&self, to: Switch) -> Result<bool, &'static str> {
pub fn turn_to(&self, to: Switch) -> Result<bool, Error> {
match (*self, to) {
(Switch::On, Switch::On) | (Switch::On, Switch::Auto) | (Switch::Auto, Switch::On) => Ok(true),
(Switch::Off, Switch::On) => Err("Tracing can't be enabled"),
(Switch::Off, Switch::On) => Err(Error::ResyncRequired),
_ => Ok(false),
}
}

View File

@ -25,7 +25,7 @@ use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, Bloo
use util::{H256, H264, Database, DBTransaction};
use header::BlockNumber;
use trace::{BlockTraces, LocalizedTrace, Config, Switch, Filter, Database as TraceDatabase, ImportRequest,
DatabaseExtras};
DatabaseExtras, Error};
use db::{Key, Writable, Readable, CacheUpdatePolicy};
use super::bloom::{TraceGroupPosition, BlockTracesBloom, BlockTracesBloomGroup};
use super::flat::{FlatTrace, FlatBlockTraces, FlatTransactionTraces};
@ -103,7 +103,7 @@ impl<T> BloomGroupDatabase for TraceDB<T> where T: DatabaseExtras {
impl<T> TraceDB<T> where T: DatabaseExtras {
/// Creates new instance of `TraceDB`.
pub fn new(config: Config, path: &Path, extras: Arc<T>) -> Self {
pub fn new(config: Config, path: &Path, extras: Arc<T>) -> Result<Self, Error> {
let mut tracedb_path = path.to_path_buf();
tracedb_path.push("tracedb");
let tracesdb = Database::open_default(tracedb_path.to_str().unwrap()).unwrap();
@ -116,7 +116,7 @@ impl<T> TraceDB<T> where T: DatabaseExtras {
None => Switch::Auto,
};
let enabled = old_tracing.turn_to(config.enabled).expect("Tracing can't be enabled. Resync required.");
let enabled = try!(old_tracing.turn_to(config.enabled));
let encoded_tracing = match enabled {
true => [0x1],
@ -126,14 +126,16 @@ impl<T> TraceDB<T> where T: DatabaseExtras {
tracesdb.put(b"enabled", &encoded_tracing).unwrap();
tracesdb.put(b"version", TRACE_DB_VER).unwrap();
TraceDB {
let db = TraceDB {
traces: RwLock::new(HashMap::new()),
blooms: RwLock::new(HashMap::new()),
tracesdb: tracesdb,
bloom_config: config.blooms,
enabled: enabled,
extras: extras,
}
};
Ok(db)
}
/// Returns traces for block with hash.
@ -401,19 +403,19 @@ mod tests {
config.enabled = Switch::Auto;
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), false);
}
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), false);
}
config.enabled = Switch::Off;
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), false);
}
}
@ -427,26 +429,26 @@ mod tests {
config.enabled = Switch::On;
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), true);
}
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), true);
}
config.enabled = Switch::Auto;
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), true);
}
config.enabled = Switch::Off;
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), false);
}
}
@ -461,12 +463,12 @@ mod tests {
config.enabled = Switch::Off;
{
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras));
let tracedb = TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap();
assert_eq!(tracedb.tracing_enabled(), true);
}
config.enabled = Switch::On;
TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)); // should panic!
TraceDB::new(config.clone(), temp.as_path(), Arc::new(NoopExtras)).unwrap(); // should panic!
}
fn create_simple_import_request(block_number: BlockNumber, block_hash: H256) -> ImportRequest {
@ -526,7 +528,7 @@ mod tests {
extras.transaction_hashes.insert(0, vec![tx_0.clone()]);
extras.transaction_hashes.insert(1, vec![tx_1.clone()]);
let tracedb = TraceDB::new(config, temp.as_path(), Arc::new(extras));
let tracedb = TraceDB::new(config, temp.as_path(), Arc::new(extras)).unwrap();
// import block 0
let request = create_simple_import_request(0, block_0.clone());

View File

@ -0,0 +1,41 @@
// Copyright 2015, 2016 Ethcore (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)
}
}

View File

@ -20,6 +20,7 @@ mod block;
mod bloom;
mod config;
mod db;
mod error;
mod executive_tracer;
pub mod flat;
mod import;
@ -29,6 +30,7 @@ pub use types::trace_types::*;
pub use self::block::BlockTraces;
pub use self::config::{Config, Switch};
pub use self::db::TraceDB;
pub use self::error::Error;
pub use types::trace_types::trace::Trace;
pub use self::noop_tracer::NoopTracer;
pub use self::executive_tracer::ExecutiveTracer;

View File

@ -16,6 +16,7 @@
use std;
use ethcore;
use ethcore::client::Error as ClientError;
use util::UtilError;
use std::process::exit;
@ -29,6 +30,7 @@ pub fn die_with_error(module: &'static str, e: ethcore::error::Error) -> ! {
match e {
Error::Util(UtilError::StdIo(e)) => die_with_io_error(module, e),
Error::Client(ClientError::Trace(e)) => die_with_message(&format!("{}", e)),
_ => die!("{}: {:?}", module, e),
}
}

View File

@ -28,7 +28,7 @@ use util::numbers::*;
use util::sha3::*;
use util::bytes::{ToPretty};
use util::rlp::{encode, decode, UntrustedRlp, View};
use ethcore::client::*;
use ethcore::client::{BlockChainClient, BlockID, TransactionID, UncleID};
use ethcore::block::IsBlock;
use ethcore::views::*;
use ethcore::ethereum::Ethash;

View File

@ -44,7 +44,7 @@
//! fn main() {
//! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap();
//! let dir = env::temp_dir();
//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel());
//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel()).unwrap();
//! let miner = Miner::new(false, ethereum::new_frontier());
//! EthSync::register(&mut service, SyncConfig::default(), client, miner);
//! }