Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Tracedb interface && cli #997

Merged
merged 4 commits into from
May 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ use filter::Filter;
use log_entry::LocalizedLogEntry;
use block_queue::{BlockQueue, BlockQueueInfo};
use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
use client::{BlockId, TransactionId, UncleId, ClientConfig, BlockChainClient};
use client::{BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient, TraceFilter};
use env_info::EnvInfo;
use executive::{Executive, Executed, TransactOptions, contract_address};
use receipt::LocalizedReceipt;
pub use blockchain::CacheSize as BlockChainCacheSize;
use trace::{TraceDB, Database as TraceDatabase};
use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase, Filter as
TracedbFilter};
use trace;

/// General block status
#[derive(Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -309,13 +311,23 @@ impl<V> Client<V> where V: Verifier {
// Commit results
let closed_block = closed_block.unwrap();
let receipts = closed_block.block().receipts().clone();
let traces = From::from(closed_block.block().traces().clone().unwrap_or_else(Vec::new));

closed_block.drain()
.commit(header.number(), &header.hash(), ancient)
.expect("State DB commit failed.");

// And update the chain after commit to prevent race conditions
// (when something is in chain but you are not able to fetch details)
let route = self.chain.insert_block(&block.bytes, receipts);
self.tracedb.import(TraceImportRequest {
traces: traces,
block_hash: header.hash(),
block_number: header.number(),
enacted: route.enacted.clone(),
retracted: route.retracted.len()
});

import_results.push(route);

self.report.write().unwrap().accrue_block(&block);
Expand Down Expand Up @@ -707,6 +719,46 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
.collect()
}

fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
let start = self.block_number(filter.range.start);
let end = self.block_number(filter.range.end);

if start.is_some() && end.is_some() {
let filter = trace::Filter {
range: start.unwrap() as usize..end.unwrap() as usize,
from_address: From::from(filter.from_address),
to_address: From::from(filter.to_address),
};

let traces = self.tracedb.filter(&filter);
Some(traces)
} else {
None
}
}

fn trace(&self, trace: TraceId) -> Option<LocalizedTrace> {
let trace_address = trace.address;
self.transaction_address(trace.transaction)
.and_then(|tx_address| {
self.block_number(BlockId::Hash(tx_address.block_hash))
.and_then(|number| self.tracedb.trace(number, tx_address.index, trace_address))
})
}

fn transaction_traces(&self, transaction: TransactionId) -> Option<Vec<LocalizedTrace>> {
self.transaction_address(transaction)
.and_then(|tx_address| {
self.block_number(BlockId::Hash(tx_address.block_hash))
.and_then(|number| self.tracedb.transaction_traces(number, tx_address.index))
})
}

fn block_traces(&self, block: BlockId) -> Option<Vec<LocalizedTrace>> {
self.block_number(block)
.and_then(|number| self.tracedb.block_traces(number))
}

fn last_hashes(&self) -> LastHashes {
self.build_last_hashes(self.chain.best_block_hash())
}
Expand Down
8 changes: 8 additions & 0 deletions ethcore/src/client/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ pub enum TransactionId {
Location(BlockId, usize)
}

/// Uniquely identifies Trace.
pub struct TraceId {
/// Transaction
pub transaction: TransactionId,
/// Trace address within transaction.
pub address: Vec<usize>,
}

/// Uniquely identifies Uncle.
pub struct UncleId (
/// Block id.
Expand Down
18 changes: 16 additions & 2 deletions ethcore/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ mod test_client;
mod trace;

pub use self::client::*;
pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig};
pub use self::ids::{BlockId, TransactionId, UncleId};
pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig, Switch};
pub use self::ids::{BlockId, TransactionId, UncleId, TraceId};
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
pub use self::trace::Filter as TraceFilter;
pub use executive::{Executed, Executive, TransactOptions};
pub use env_info::{LastHashes, EnvInfo};

Expand All @@ -43,6 +44,7 @@ use filter::Filter;
use error::{ImportResult, Error};
use receipt::LocalizedReceipt;
use engine::{Engine};
use trace::LocalizedTrace;

/// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient : Sync + Send {
Expand Down Expand Up @@ -135,6 +137,18 @@ pub trait BlockChainClient : Sync + Send {
/// Executes a function providing it with a reference to an engine.
fn engine(&self) -> &Engine;

/// Returns traces matching given filter.
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>>;

/// Returns trace with given id.
fn trace(&self, trace: TraceId) -> Option<LocalizedTrace>;

/// Returns traces created by transaction.
fn transaction_traces(&self, trace: TransactionId) -> Option<Vec<LocalizedTrace>>;

/// Returns traces created by transaction from block.
fn block_traces(&self, trace: BlockId) -> Option<Vec<LocalizedTrace>>;

/// Get last hashes starting from best block.
fn last_hashes(&self) -> LastHashes;
}
Expand Down
19 changes: 18 additions & 1 deletion ethcore/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder};
use util::*;
use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action};
use blockchain::TreeRoute;
use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockId, TransactionId, UncleId, LastHashes};
use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockId, TransactionId, UncleId, TraceId, TraceFilter, LastHashes};
use header::{Header as BlockHeader, BlockNumber};
use filter::Filter;
use log_entry::LocalizedLogEntry;
Expand All @@ -33,6 +33,7 @@ use block::{SealedBlock, ClosedBlock, LockedBlock};
use executive::Executed;
use error::Error;
use engine::Engine;
use trace::LocalizedTrace;

/// Test client.
pub struct TestBlockChainClient {
Expand Down Expand Up @@ -432,4 +433,20 @@ impl BlockChainClient for TestBlockChainClient {
fn engine(&self) -> &Engine {
unimplemented!();
}

fn filter_traces(&self, _filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
unimplemented!();
}

fn trace(&self, _trace: TraceId) -> Option<LocalizedTrace> {
unimplemented!();
}

fn transaction_traces(&self, _trace: TransactionId) -> Option<Vec<LocalizedTrace>> {
unimplemented!();
}

fn block_traces(&self, _trace: BlockId) -> Option<Vec<LocalizedTrace>> {
unimplemented!();
}
}
8 changes: 7 additions & 1 deletion parity/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ API and Console Options:
--jsonrpc-apis APIS Specify the APIs available through the JSONRPC
interface. APIS is a comma-delimited list of API
name. Possible name are web3, eth and net.
[default: web3,eth,net,personal,ethcore].
[default: web3,eth,net,personal,ethcore,traces].
-w --webapp Enable the web applications server (e.g.
status page).
--webapp-port PORT Specify the port portion of the WebApps server
Expand Down Expand Up @@ -103,6 +103,11 @@ Sealing/Mining Options:
be included in next block) [default: 1024].

Footprint Options:
--tracing BOOL Indicates if full transaction tracing should be
enabled. Works only if client had been fully synced with
tracing enabled. BOOL may be one of auto, on, off.
auto uses last used value of this option (off if it does
not exist) [default: auto].
--pruning METHOD Configure pruning of the state/storage trie. METHOD
may be one of auto, archive, basic, fast, light:
archive - keep all state trie data. No pruning.
Expand Down Expand Up @@ -164,6 +169,7 @@ pub struct Args {
pub flag_bootnodes: Option<String>,
pub flag_network_id: Option<String>,
pub flag_pruning: String,
pub flag_tracing: String,
pub flag_port: u16,
pub flag_peers: usize,
pub flag_no_discovery: bool,
Expand Down
8 changes: 7 additions & 1 deletion parity/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use die::*;
use util::*;
use util::keys::store::AccountService;
use util::network_settings::NetworkSettings;
use ethcore::client::{append_path, get_db_path, ClientConfig};
use ethcore::client::{append_path, get_db_path, ClientConfig, Switch};
use ethcore::ethereum;
use ethcore::spec::Spec;
use ethsync::SyncConfig;
Expand Down Expand Up @@ -207,6 +207,12 @@ impl Configuration {
client_config.blockchain.max_cache_size = self.args.flag_cache_max_size;
}
}
client_config.tracing.enabled = match self.args.flag_tracing.as_str() {
"auto" => Switch::Auto,
"on" => Switch::On,
"off" => Switch::Off,
_ => { die!("Invalid tracing method given!") }
};
client_config.pruning = match self.args.flag_pruning.as_str() {
"archive" => journaldb::Algorithm::Archive,
"light" => journaldb::Algorithm::EarlyMerge,
Expand Down
6 changes: 5 additions & 1 deletion parity/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub fn setup_rpc_server(
server.add_delegate(Web3Client::new().to_delegate());
},
"net" => {
modules.insert("web3".to_owned(), "1.0".to_owned());
modules.insert("net".to_owned(), "1.0".to_owned());
server.add_delegate(NetClient::new(&deps.sync).to_delegate());
},
"eth" => {
Expand All @@ -115,6 +115,10 @@ pub fn setup_rpc_server(
// not adding to modules, since `ethcore` is not supported in geth
server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate())
},
"traces" => {
modules.insert("traces".to_owned(), "1.0".to_owned());
server.add_delegate(TracesClient::new(&deps.client).to_delegate())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be also included in parity/webapps.rs?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea... It's not a part of 'standard' rpc, but it would be useful

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be added just for consistency.

},
_ => {
die!("{}: Invalid API name to be enabled.", api);
},
Expand Down
2 changes: 2 additions & 0 deletions rpc/src/v1/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ mod eth;
mod net;
mod personal;
mod ethcore;
mod traces;
mod rpc;

pub use self::web3::Web3Client;
pub use self::eth::{EthClient, EthFilterClient};
pub use self::net::NetClient;
pub use self::personal::PersonalClient;
pub use self::ethcore::EthcoreClient;
pub use self::traces::TracesClient;
pub use self::rpc::RpcClient;

84 changes: 84 additions & 0 deletions rpc/src/v1/impls/traces.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// 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/>.

//! Traces api implementation.

use std::sync::{Weak, Arc};
use jsonrpc_core::*;
use util::H256;
use ethcore::client::{BlockChainClient, TransactionId, TraceId};
use v1::traits::Traces;
use v1::types::{TraceFilter, Trace, BlockNumber, Index};

/// Traces api implementation.
pub struct TracesClient<C> where C: BlockChainClient {
client: Weak<C>,
}

impl<C> TracesClient<C> where C: BlockChainClient {
/// Creates new Traces client.
pub fn new(client: &Arc<C>) -> Self {
TracesClient {
client: Arc::downgrade(client),
}
}
}

impl<C> Traces for TracesClient<C> where C: BlockChainClient + 'static {
fn filter(&self, params: Params) -> Result<Value, Error> {
from_params::<(TraceFilter,)>(params)
.and_then(|(filter, )| {
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(Trace::from).collect());
to_value(&traces)
})
}

fn block_traces(&self, params: Params) -> Result<Value, Error> {
from_params::<(BlockNumber,)>(params)
.and_then(|(block_number,)| {
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(Trace::from).collect());
to_value(&traces)
})
}

fn transaction_traces(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256,)>(params)
.and_then(|(transaction_hash,)| {
let client = take_weak!(self.client);
let traces = client.transaction_traces(TransactionId::Hash(transaction_hash));
let traces = traces.map_or_else(Vec::new, |traces| traces.into_iter().map(Trace::from).collect());
to_value(&traces)
})
}

fn trace(&self, params: Params) -> Result<Value, Error> {
from_params::<(H256, Vec<Index>)>(params)
.and_then(|(transaction_hash, address)| {
let client = take_weak!(self.client);
let id = TraceId {
transaction: TransactionId::Hash(transaction_hash),
address: address.into_iter().map(|i| i.value()).collect()
};
let trace = client.trace(id);
let trace = trace.map(Trace::from);
to_value(&trace)
})
}
}
2 changes: 1 addition & 1 deletion rpc/src/v1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ mod helpers;

pub mod tests;

pub use self::traits::{Web3, Eth, EthFilter, Personal, Net, Ethcore, Rpc};
pub use self::traits::{Web3, Eth, EthFilter, Personal, Net, Ethcore, Traces, Rpc};
pub use self::impls::*;
2 changes: 2 additions & 0 deletions rpc/src/v1/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ pub mod eth;
pub mod net;
pub mod personal;
pub mod ethcore;
pub mod traces;
pub mod rpc;

pub use self::web3::Web3;
pub use self::eth::{Eth, EthFilter};
pub use self::net::Net;
pub use self::personal::Personal;
pub use self::ethcore::Ethcore;
pub use self::traces::Traces;
pub use self::rpc::Rpc;
Loading