diff --git a/Cargo.lock b/Cargo.lock index a17bc4413..e3dc752f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,6 +245,7 @@ dependencies = [ "ethcore-devtools 1.3.0", "ethcore-ipc 1.3.0", "ethcore-ipc-codegen 1.3.0", + "ethcore-ipc-nano 1.3.0", "ethcore-util 1.3.0", "ethjson 0.1.0", "ethstore 0.1.0", @@ -256,6 +257,7 @@ dependencies = [ "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -330,6 +332,7 @@ dependencies = [ "ethash 1.3.0", "ethcore 1.3.0", "ethcore-devtools 1.3.0", + "ethcore-ipc 1.3.0", "ethcore-util 1.3.0", "ethjson 0.1.0", "ethsync 1.3.0", diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index acdcd667a..810fd6c51 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -31,6 +31,8 @@ bloomchain = "0.1" "ethcore-ipc" = { path = "../ipc/rpc" } rayon = "0.3.1" ethstore = { path = "../ethstore" } +semver = "0.2" +ethcore-ipc-nano = { path = "../ipc/nano" } [dependencies.hyper] git = "https://github.com/ethcore/hyper" diff --git a/ethcore/build.rs b/ethcore/build.rs index dadcce13a..9f61851d4 100644 --- a/ethcore/build.rs +++ b/ethcore/build.rs @@ -30,4 +30,18 @@ fn main() { codegen::register(&mut registry); registry.expand("", &src, &dst).unwrap(); } + + // client interface + { + let src = Path::new("src/client/client.rs"); + let intermediate = Path::new(&out_dir).join("client.intermediate.rs.in"); + let mut registry = syntex::Registry::new(); + codegen::register(&mut registry); + registry.expand("", &src, &intermediate).unwrap(); + + let dst = Path::new(&out_dir).join("client.ipc.rs"); + let mut registry = syntex::Registry::new(); + codegen::register(&mut registry); + registry.expand("", &intermediate, &dst).unwrap(); + } } diff --git a/ethcore/src/block_queue.rs b/ethcore/src/block_queue.rs index ce99dcccd..2288c1509 100644 --- a/ethcore/src/block_queue.rs +++ b/ethcore/src/block_queue.rs @@ -28,6 +28,8 @@ use service::*; use client::BlockStatus; use util::panics::*; +pub use types::block_queue_info::BlockQueueInfo; + known_heap_size!(0, UnverifiedBlock, VerifyingBlock, PreverifiedBlock); const MIN_MEM_LIMIT: usize = 16384; @@ -53,22 +55,6 @@ impl Default for BlockQueueConfig { } } -/// Block queue status -#[derive(Debug)] -pub struct BlockQueueInfo { - /// Number of queued blocks pending verification - pub unverified_queue_size: usize, - /// Number of verified queued blocks pending import - pub verified_queue_size: usize, - /// Number of blocks being verified - pub verifying_queue_size: usize, - /// Configured maximum number of blocks in the queue - pub max_queue_size: usize, - /// Configured maximum number of bytes to use - pub max_mem_use: usize, - /// Heap memory used in bytes - pub mem_used: usize, -} impl BlockQueueInfo { /// The total size of the queues. diff --git a/ethcore/src/blockchain/block_info.rs b/ethcore/src/blockchain/block_info.rs index eb3677c25..42f1bd439 100644 --- a/ethcore/src/blockchain/block_info.rs +++ b/ethcore/src/blockchain/block_info.rs @@ -17,8 +17,6 @@ use util::numbers::{U256,H256}; use header::BlockNumber; -use util::bytes::{FromRawBytesVariable, FromBytesError, ToBytesWithMap}; - /// Brief info about inserted block. #[derive(Clone)] pub struct BlockInfo { @@ -54,43 +52,3 @@ pub struct BranchBecomingCanonChainData { /// Hashes of the blocks which were invalidated. pub retracted: Vec, } - -impl FromRawBytesVariable for BranchBecomingCanonChainData { - fn from_bytes_variable(bytes: &[u8]) -> Result { - type Tuple = (Vec, Vec, H256); - let (enacted, retracted, ancestor) = try!(Tuple::from_bytes_variable(bytes)); - Ok(BranchBecomingCanonChainData { ancestor: ancestor, enacted: enacted, retracted: retracted }) - } -} - -impl FromRawBytesVariable for BlockLocation { - fn from_bytes_variable(bytes: &[u8]) -> Result { - match bytes[0] { - 0 => Ok(BlockLocation::CanonChain), - 1 => Ok(BlockLocation::Branch), - 2 => Ok(BlockLocation::BranchBecomingCanonChain( - try!(BranchBecomingCanonChainData::from_bytes_variable(&bytes[1..bytes.len()])))), - _ => Err(FromBytesError::UnknownMarker) - } - } -} - -impl ToBytesWithMap for BranchBecomingCanonChainData { - fn to_bytes_map(&self) -> Vec { - (&self.enacted, &self.retracted, &self.ancestor).to_bytes_map() - } -} - -impl ToBytesWithMap for BlockLocation { - fn to_bytes_map(&self) -> Vec { - match *self { - BlockLocation::CanonChain => vec![0u8], - BlockLocation::Branch => vec![1u8], - BlockLocation::BranchBecomingCanonChain(ref data) => { - let mut bytes = (&data.enacted, &data.retracted, &data.ancestor).to_bytes_map(); - bytes.insert(0, 2u8); - bytes - } - } - } -} diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index fffef2bb2..a23e47929 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -14,16 +14,35 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Blockchain database client. - use std::path::PathBuf; +use std::collections::{HashSet, HashMap}; +use std::ops::Deref; +use std::mem; +use std::collections::VecDeque; +use std::sync::*; +use std::path::Path; +use std::fmt; +use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::time::Instant; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering}; -use util::*; + +// util +use util::numbers::*; use util::panics::*; +use util::network::*; +use util::io::*; +use util::rlp; +use util::sha3::*; +use util::{Bytes}; +use util::rlp::{RlpStream, Rlp, UntrustedRlp}; +use util::journaldb; +use util::journaldb::JournalDB; +use util::kvdb::*; +use util::{Applyable, Stream, View, PerfTimer, Itertools, Colour}; + +// other use views::BlockView; use error::{ImportError, ExecutionError, BlockError, ImportResult}; -use header::{BlockNumber}; +use header::BlockNumber; use state::State; use spec::Spec; use engine::Engine; @@ -35,24 +54,29 @@ use verification::{PreverifiedBlock, Verifier}; use block::*; use transaction::{LocalizedTransaction, SignedTransaction, Action}; use blockchain::extras::TransactionAddress; -use filter::Filter; +use types::filter::Filter; use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use client::{BlockID, TransactionID, UncleID, TraceId, Mode, ClientConfig, DatabaseCompactionProfile, - BlockChainClient, MiningBlockChainClient, TraceFilter, CallAnalytics, - BlockImportError}; +use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, + DatabaseCompactionProfile, BlockChainClient, MiningBlockChainClient, + TraceFilter, CallAnalytics, BlockImportError, Mode}; use client::Error as ClientError; use env_info::EnvInfo; use executive::{Executive, Executed, TransactOptions, contract_address}; use receipt::LocalizedReceipt; -pub use blockchain::CacheSize as BlockChainCacheSize; use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase}; use trace; -pub use types::blockchain_info::BlockChainInfo; -pub use types::block_status::BlockStatus; use evm::Factory as EvmFactory; use miner::{Miner, MinerService}; +use util::TrieFactory; +use ipc::IpcConfig; +use ipc::binary::{BinaryConvertError}; + +// re-export +pub use types::blockchain_info::BlockChainInfo; +pub use types::block_status::BlockStatus; +pub use blockchain::CacheSize as BlockChainCacheSize; const MAX_TX_QUEUE_SIZE: usize = 4096; const MAX_QUEUE_SIZE_TO_SLEEP_ON: usize = 2; @@ -452,7 +476,7 @@ impl Client { HeaderView::new(&self.best_block_header()).state_root(), self.engine.account_start_nonce(), self.trie_factory.clone()) - .expect("State root of best block header always valid.") + .expect("State root of best block header always valid.") } /// Get info on the cache. @@ -472,12 +496,12 @@ impl Client { pub fn tick(&self) { self.chain.collect_garbage(); self.block_queue.collect_garbage(); - + match self.mode { Mode::Dark(timeout) => { let mut ss = self.sleep_state.lock().unwrap(); if let Some(t) = ss.last_activity { - if Instant::now() > t + timeout { + if Instant::now() > t + timeout { self.sleep(); ss.last_activity = None; } @@ -487,14 +511,14 @@ impl Client { let mut ss = self.sleep_state.lock().unwrap(); let now = Instant::now(); if let Some(t) = ss.last_activity { - if now > t + timeout { + if now > t + timeout { self.sleep(); ss.last_activity = None; ss.last_autosleep = Some(now); } } - if let Some(t) = ss.last_autosleep { - if now > t + wakeup_after { + if let Some(t) = ss.last_autosleep { + if now > t + wakeup_after { self.wake_up(); ss.last_activity = Some(now); ss.last_autosleep = None; @@ -575,6 +599,8 @@ impl Client { } } +#[derive(Ipc)] +#[ipc(client_ident="RemoteClient")] impl BlockChainClient for Client { fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result { let header = self.block_header(BlockID::Latest).unwrap(); @@ -811,8 +837,8 @@ impl BlockChainClient for Client { receipt.logs.into_iter() .enumerate() .filter(|tuple| filter.matches(&tuple.1)) - .map(|(i, log)| LocalizedLogEntry { - entry: log, + .map(|(i, log)| LocalizedLogEntry { + entry: log, block_hash: hash.clone(), block_number: number, transaction_hash: hashes.get(index).cloned().unwrap_or_else(H256::new), @@ -822,7 +848,6 @@ impl BlockChainClient for Client { .collect::>() }) .collect::>() - }) .collect() } @@ -966,3 +991,5 @@ impl MayPanic for Client { self.panic_handler.on_panic(closure); } } + +impl IpcConfig for Client { } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 0e7298b74..7a24dc94b 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -16,7 +16,6 @@ //! Blockchain database client. -mod client; mod config; mod error; mod test_client; @@ -27,7 +26,7 @@ pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockQueue pub use self::error::Error; pub use types::ids::*; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; -pub use self::trace::Filter as TraceFilter; +pub use types::trace_filter::Filter as TraceFilter; pub use executive::{Executed, Executive, TransactOptions}; pub use env_info::{LastHashes, EnvInfo}; @@ -47,23 +46,21 @@ use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; use evm::Factory as EvmFactory; +pub use types::call_analytics::CallAnalytics; pub use block_import_error::BlockImportError; pub use transaction_import::TransactionImportResult; +pub use transaction_import::TransactionImportError; -/// Options concerning what analytics we run on the call. -#[derive(Eq, PartialEq, Default, Clone, Copy, Debug)] -pub struct CallAnalytics { - /// Make a transaction trace. - pub transaction_tracing: bool, - /// Make a VM trace. - pub vm_tracing: bool, - /// Make a diff. - pub state_diffing: bool, +pub mod client { + //! Blockchain database client. + + #![allow(dead_code, unused_assignments, unused_variables, missing_docs)] // codegen issues + include!(concat!(env!("OUT_DIR"), "/client.ipc.rs")); } /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { - + /// Should be called by any external-facing interface when actively using the client. /// To minimise chatter, there's no need to call more than once every 30s. fn keep_alive(&self) {} diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 16adfe7c3..0f615832e 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -36,7 +36,7 @@ use spec::Spec; use block_queue::BlockQueueInfo; use block::{OpenBlock, SealedBlock}; use executive::Executed; -use error::{ExecutionError}; +use error::ExecutionError; use trace::LocalizedTrace; /// Test client. diff --git a/ethcore/src/client/trace.rs b/ethcore/src/client/trace.rs index 15920dea9..3ab01757e 100644 --- a/ethcore/src/client/trace.rs +++ b/ethcore/src/client/trace.rs @@ -1,13 +1,12 @@ //! Bridge between Tracedb and Blockchain. -use std::ops::Range; -use util::{Address, H256}; +use util::{H256}; use header::BlockNumber; use trace::DatabaseExtras as TraceDatabaseExtras; use blockchain::{BlockChain, BlockProvider}; use blockchain::extras::TransactionAddress; -use super::BlockID; +pub use types::trace_filter::Filter; impl TraceDatabaseExtras for BlockChain { fn block_hash(&self, block_number: BlockNumber) -> Option { @@ -26,13 +25,3 @@ impl TraceDatabaseExtras for BlockChain { .map(|tx| tx.hash()) } } - -/// Easy to use trace filter. -pub struct Filter { - /// Range of filtering. - pub range: Range, - /// From address. - pub from_address: Vec
, - /// To address. - pub to_address: Vec
, -} diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 8c37e98ef..10786cf91 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -20,9 +20,9 @@ use util::*; use header::BlockNumber; use basic_types::LogBloom; use client::Error as ClientError; -pub use types::executed::ExecutionError; use ipc::binary::{BinaryConvertError, BinaryConvertable}; use types::block_import_error::BlockImportError; +pub use types::executed::ExecutionError; #[derive(Debug, PartialEq, Clone)] /// Errors concerning transaction processing. @@ -327,7 +327,6 @@ binary_fixed_size!(BlockError); binary_fixed_size!(ImportError); binary_fixed_size!(TransactionError); - // TODO: uncomment below once https://github.com/rust-lang/rust/issues/27336 sorted. /*#![feature(concat_idents)] macro_rules! assimilate { diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 183a3c251..f2269501c 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -95,6 +95,8 @@ extern crate rayon; extern crate hyper; extern crate ethash; pub extern crate ethstore; +extern crate semver; +extern crate ethcore_ipc_nano as nanoipc; #[cfg(test)] extern crate ethcore_devtools as devtools; #[cfg(feature = "jit" )] extern crate evmjit; @@ -106,7 +108,6 @@ pub mod block_queue; pub mod client; pub mod error; pub mod ethereum; -pub mod filter; pub mod header; pub mod service; pub mod trace; diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index bdce9f504..f86bf3564 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -198,6 +198,7 @@ struct VerifiedTransaction { /// transaction origin origin: TransactionOrigin, } + impl VerifiedTransaction { fn new(transaction: SignedTransaction, origin: TransactionOrigin) -> Result { try!(transaction.sender()); diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs index 76dac214b..9a11fb33f 100644 --- a/ethcore/src/pod_state.rs +++ b/ethcore/src/pod_state.rs @@ -72,7 +72,7 @@ impl fmt::Display for PodState { /// Calculate and return diff between `pre` state and `post` state. pub fn diff_pod(pre: &PodState, post: &PodState) -> StateDiff { - StateDiff(pre.get().keys().merge(post.get().keys()).filter_map(|acc| pod_account::diff_pod(pre.get().get(acc), post.get().get(acc)).map(|d|(acc.clone(), d))).collect()) + StateDiff { raw: pre.get().keys().merge(post.get().keys()).filter_map(|acc| pod_account::diff_pod(pre.get().get(acc), post.get().get(acc)).map(|d|(acc.clone(), d))).collect() } } #[cfg(test)] @@ -86,22 +86,22 @@ mod test { #[test] fn create_delete() { let a = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); - assert_eq!(super::diff_pod(&a, &PodState::new()), StateDiff(map![ + assert_eq!(super::diff_pod(&a, &PodState::new()), StateDiff { raw: map![ 1.into() => AccountDiff{ balance: Diff::Died(69.into()), nonce: Diff::Died(0.into()), code: Diff::Died(vec![]), storage: map![], } - ])); - assert_eq!(super::diff_pod(&PodState::new(), &a), StateDiff(map![ + ]}); + assert_eq!(super::diff_pod(&PodState::new(), &a), StateDiff{ raw: map![ 1.into() => AccountDiff{ balance: Diff::Born(69.into()), nonce: Diff::Born(0.into()), code: Diff::Born(vec![]), storage: map![], } - ])); + ]}); } #[test] @@ -111,22 +111,22 @@ mod test { 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]), 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); - assert_eq!(super::diff_pod(&a, &b), StateDiff(map![ + assert_eq!(super::diff_pod(&a, &b), StateDiff { raw: map![ 2.into() => AccountDiff{ balance: Diff::Born(69.into()), nonce: Diff::Born(0.into()), code: Diff::Born(vec![]), storage: map![], } - ])); - assert_eq!(super::diff_pod(&b, &a), StateDiff(map![ + ]}); + assert_eq!(super::diff_pod(&b, &a), StateDiff { raw: map![ 2.into() => AccountDiff{ balance: Diff::Died(69.into()), nonce: Diff::Died(0.into()), code: Diff::Died(vec![]), storage: map![], } - ])); + ]}); } #[test] @@ -139,14 +139,14 @@ mod test { 1.into() => PodAccount::new(69.into(), 1.into(), vec![], map![]), 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); - assert_eq!(super::diff_pod(&a, &b), StateDiff(map![ + assert_eq!(super::diff_pod(&a, &b), StateDiff { raw: map![ 1.into() => AccountDiff{ balance: Diff::Same, nonce: Diff::Changed(0.into(), 1.into()), code: Diff::Same, storage: map![], } - ])); + ]}); } } diff --git a/ethcore/src/tests/mod.rs b/ethcore/src/tests/mod.rs index 28c1b3b5b..db36a3762 100644 --- a/ethcore/src/tests/mod.rs +++ b/ethcore/src/tests/mod.rs @@ -15,4 +15,5 @@ // along with Parity. If not, see . pub mod helpers; -mod client; \ No newline at end of file +mod client; +mod rpc; diff --git a/ethcore/src/tests/rpc.rs b/ethcore/src/tests/rpc.rs new file mode 100644 index 000000000..a25928cf8 --- /dev/null +++ b/ethcore/src/tests/rpc.rs @@ -0,0 +1,57 @@ +// 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 . + +//! Client RPC tests + +use nanoipc; +use std::sync::Arc; +use std::sync::atomic::{Ordering, AtomicBool}; +use client::{Client, ClientConfig, RemoteClient}; +use tests::helpers::*; +use devtools::*; +use miner::Miner; +use crossbeam; +use common::IoChannel; + +pub fn run_test_worker(scope: &crossbeam::Scope, stop: Arc, socket_path: &str) { + let socket_path = socket_path.to_owned(); + scope.spawn(move || { + let temp = RandomTempPath::create_dir(); + let client = Client::new( + ClientConfig::default(), + get_test_spec(), + temp.as_path(), + Arc::new(Miner::with_spec(get_test_spec())), + IoChannel::disconnected()).unwrap(); + let mut worker = nanoipc::Worker::new(&client); + worker.add_reqrep(&socket_path).unwrap(); + while !stop.load(Ordering::Relaxed) { + worker.poll(); + } + }); +} + +#[test] +fn can_handshake() { + crossbeam::scope(|scope| { + let stop_guard = StopGuard::new(); + let socket_path = "ipc:///tmp/parity-client-rpc-10.ipc"; + run_test_worker(scope, stop_guard.share(), socket_path); + let remote_client = nanoipc::init_client::>(socket_path).unwrap(); + + assert!(remote_client.handshake().is_ok()); + }) +} diff --git a/ethcore/src/types/account_diff.rs b/ethcore/src/types/account_diff.rs index 49fc51110..5071c2f7e 100644 --- a/ethcore/src/types/account_diff.rs +++ b/ethcore/src/types/account_diff.rs @@ -16,11 +16,17 @@ //! Diff between two accounts. -use util::*; +use util::numbers::*; +use std::cmp::*; +use std::fmt; +use ipc::binary::{BinaryConvertError, BinaryConvertable}; +use util::Bytes; +use std::collections::{VecDeque, BTreeMap}; +use std::mem; -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Binary)] /// Diff type for specifying a change (or not). -pub enum Diff where T: Eq { +pub enum Diff where T: Eq + BinaryConvertable { /// Both sides are the same. Same, /// Left (pre, source) side doesn't include value, right side (post, destination) does. @@ -31,7 +37,7 @@ pub enum Diff where T: Eq { Died(T), } -impl Diff where T: Eq { +impl Diff where T: Eq + BinaryConvertable { /// Construct new object with given `pre` and `post`. pub fn new(pre: T, post: T) -> Self { if pre == post { Diff::Same } else { Diff::Changed(pre, post) } } @@ -45,7 +51,7 @@ impl Diff where T: Eq { pub fn is_same(&self) -> bool { match *self { Diff::Same => true, _ => false }} } -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Binary)] /// Account diff. pub struct AccountDiff { /// Change in balance, allowed to be `Diff::Same`. @@ -58,8 +64,8 @@ pub struct AccountDiff { pub storage: BTreeMap>, } -#[derive(Debug, PartialEq, Eq, Clone)] -/// Change in existance type. +#[derive(Debug, PartialEq, Eq, Clone, Binary)] +/// Change in existance type. // TODO: include other types of change. pub enum Existance { /// Item came into existance. @@ -94,6 +100,8 @@ impl AccountDiff { // TODO: refactor into something nicer. fn interpreted_hash(u: &H256) -> String { + use util::bytes::*; + if u <= &H256::from(0xffffffff) { format!("{} = 0x{:x}", U256::from(u.as_slice()).low_u32(), U256::from(u.as_slice()).low_u32()) } else if u <= &H256::from(u64::max_value()) { @@ -107,6 +115,8 @@ fn interpreted_hash(u: &H256) -> String { impl fmt::Display for AccountDiff { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use util::bytes::*; + match self.nonce { Diff::Born(ref x) => try!(write!(f, " non {}", x)), Diff::Changed(ref pre, ref post) => try!(write!(f, "#{} ({} {} {})", post, pre, if pre > post {"-"} else {"+"}, *max(pre, post) - * min(pre, post))), diff --git a/ethcore/src/types/block_queue_info.rs b/ethcore/src/types/block_queue_info.rs new file mode 100644 index 000000000..714f84ece --- /dev/null +++ b/ethcore/src/types/block_queue_info.rs @@ -0,0 +1,38 @@ +// 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 . + +//! Block queue info types + +use std::mem; +use ipc::binary::BinaryConvertError; +use std::collections::VecDeque; + +/// Block queue status +#[derive(Debug, Binary)] +pub struct BlockQueueInfo { + /// Number of queued blocks pending verification + pub unverified_queue_size: usize, + /// Number of verified queued blocks pending import + pub verified_queue_size: usize, + /// Number of blocks being verified + pub verifying_queue_size: usize, + /// Configured maximum number of blocks in the queue + pub max_queue_size: usize, + /// Configured maximum number of bytes to use + pub max_mem_use: usize, + /// Heap memory used in bytes + pub mem_used: usize, +} diff --git a/ethcore/src/types/call_analytics.rs b/ethcore/src/types/call_analytics.rs new file mode 100644 index 000000000..c738c15bd --- /dev/null +++ b/ethcore/src/types/call_analytics.rs @@ -0,0 +1,32 @@ +// 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 . + +//! Call analytics related types + +use std::mem; +use ipc::binary::{BinaryConvertError}; +use std::collections::VecDeque; + +/// Options concerning what analytics we run on the call. +#[derive(Eq, PartialEq, Default, Clone, Copy, Debug, Binary)] +pub struct CallAnalytics { + /// Make a transaction trace. + pub transaction_tracing: bool, + /// Make a VM trace. + pub vm_tracing: bool, + /// Make a diff. + pub state_diffing: bool, +} diff --git a/ethcore/src/types/executed.rs b/ethcore/src/types/executed.rs index 4d31b9fe5..293a427f7 100644 --- a/ethcore/src/types/executed.rs +++ b/ethcore/src/types/executed.rs @@ -27,7 +27,7 @@ use std::mem; use std::collections::VecDeque; /// Transaction execution receipt. -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Binary)] pub struct Executed { /// Gas paid up front for execution of transaction. pub gas: U256, diff --git a/ethcore/src/filter.rs b/ethcore/src/types/filter.rs similarity index 93% rename from ethcore/src/filter.rs rename to ethcore/src/types/filter.rs index d99f80050..d8d5d03bd 100644 --- a/ethcore/src/filter.rs +++ b/ethcore/src/types/filter.rs @@ -20,8 +20,12 @@ use util::hash::*; use util::sha3::*; use client::BlockID; use log_entry::LogEntry; +use ipc::binary::BinaryConvertError; +use std::mem; +use std::collections::VecDeque; /// Blockchain Filter. +#[derive(Binary)] pub struct Filter { /// Blockchain will be searched from this block. pub from_block: BlockID, @@ -29,22 +33,27 @@ pub struct Filter { /// Till this block. pub to_block: BlockID, - /// Search addresses. - /// + /// Search addresses. + /// /// If None, match all. /// If specified, log must be produced by one of these addresses. pub address: Option>, /// Search topics. - /// + /// /// If None, match all. /// If specified, log must contain one of these topics. - pub topics: [Option>; 4], + pub topics: Vec>>, } impl Clone for Filter { fn clone(&self) -> Self { - let mut topics = [None, None, None, None]; + let mut topics = [ + None, + None, + None, + None, + ]; for i in 0..4 { topics[i] = self.topics[i].clone(); } @@ -53,13 +62,13 @@ impl Clone for Filter { from_block: self.from_block.clone(), to_block: self.to_block.clone(), address: self.address.clone(), - topics: topics + topics: topics[..].to_vec() } } } impl Filter { - /// Returns combinations of each address and topic. + /// Returns combinations of each address and topic. pub fn bloom_possibilities(&self) -> Vec { let blooms = match self.address { Some(ref addresses) if !addresses.is_empty() => @@ -71,7 +80,7 @@ impl Filter { _ => vec![H2048::new()] }; - self.topics.iter().fold(blooms, | bs, topic | match *topic { + self.topics.iter().fold(blooms, |bs, topic| match *topic { None => bs, Some(ref topics) => bs.into_iter().flat_map(|bloom| { topics.into_iter().map(|topic| { @@ -111,7 +120,7 @@ mod tests { from_block: BlockID::Earliest, to_block: BlockID::Latest, address: None, - topics: [None, None, None, None] + topics: vec![None, None, None, None], }; let possibilities = none_filter.bloom_possibilities(); @@ -126,9 +135,11 @@ mod tests { from_block: BlockID::Earliest, to_block: BlockID::Latest, address: Some(vec![Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap()]), - topics: [ + topics: vec![ Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()]), - None, None, None + None, + None, + None, ] }; @@ -142,10 +153,11 @@ mod tests { from_block: BlockID::Earliest, to_block: BlockID::Latest, address: Some(vec![Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap()]), - topics: [ + topics: vec![ Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()]), Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()]), - None, None + None, + None, ] }; @@ -162,7 +174,7 @@ mod tests { Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(), Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(), ]), - topics: [ + topics: vec![ Some(vec![ H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap(), H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap() @@ -188,10 +200,11 @@ mod tests { from_block: BlockID::Earliest, to_block: BlockID::Latest, address: Some(vec![Address::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap()]), - topics: [ + topics: vec![ Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9").unwrap()]), Some(vec![H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa").unwrap()]), - None, None + None, + None, ] }; diff --git a/ethcore/src/types/ids.rs b/ethcore/src/types/ids.rs index 99dadc4ea..c08ab4116 100644 --- a/ethcore/src/types/ids.rs +++ b/ethcore/src/types/ids.rs @@ -47,6 +47,7 @@ pub enum TransactionID { } /// Uniquely identifies Trace. +#[derive(Binary)] pub struct TraceId { /// Transaction pub transaction: TransactionID, diff --git a/ethcore/src/types/mod.rs.in b/ethcore/src/types/mod.rs.in index 97579da8a..e7731d1cc 100644 --- a/ethcore/src/types/mod.rs.in +++ b/ethcore/src/types/mod.rs.in @@ -25,5 +25,9 @@ pub mod executed; pub mod block_status; pub mod account_diff; pub mod state_diff; +pub mod block_queue_info; +pub mod filter; +pub mod trace_filter; +pub mod call_analytics; pub mod transaction_import; pub mod block_import_error; diff --git a/ethcore/src/types/state_diff.rs b/ethcore/src/types/state_diff.rs index 4257d5b07..e341b8436 100644 --- a/ethcore/src/types/state_diff.rs +++ b/ethcore/src/types/state_diff.rs @@ -16,24 +16,32 @@ //! State diff module. -use util::*; +use util::numbers::*; use account_diff::*; +use ipc::binary::BinaryConvertError; +use std::mem; +use std::fmt; +use std::ops::*; +use std::collections::{VecDeque, BTreeMap}; -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Binary)] /// Expression for the delta between two system states. Encoded the /// delta of every altered account. -pub struct StateDiff (pub BTreeMap); +pub struct StateDiff { + /// Raw diff key-value + pub raw: BTreeMap +} impl StateDiff { /// Get the actual data. pub fn get(&self) -> &BTreeMap { - &self.0 + &self.raw } } impl fmt::Display for StateDiff { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for (add, acc) in &self.0 { + for (add, acc) in &self.raw { try!(write!(f, "{} {}: {}", acc.existance(), add, acc)); } Ok(()) @@ -44,6 +52,6 @@ impl Deref for StateDiff { type Target = BTreeMap; fn deref(&self) -> &Self::Target { - &self.0 + &self.raw } } diff --git a/ethcore/src/types/trace_filter.rs b/ethcore/src/types/trace_filter.rs new file mode 100644 index 000000000..89f886af4 --- /dev/null +++ b/ethcore/src/types/trace_filter.rs @@ -0,0 +1,35 @@ +// 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 . + +//! Trace filter related types + +use std::mem; +use ipc::binary::{BinaryConvertError}; +use std::collections::VecDeque; +use std::ops::Range; +use util::{Address}; +use types::ids::BlockID; + +/// Easy to use trace filter. +#[derive(Binary)] +pub struct Filter { + /// Range of filtering. + pub range: Range, + /// From address. + pub from_address: Vec
, + /// To address. + pub to_address: Vec
, +} diff --git a/ethcore/src/types/tree_route.rs b/ethcore/src/types/tree_route.rs index 2ad0aa240..37413be57 100644 --- a/ethcore/src/types/tree_route.rs +++ b/ethcore/src/types/tree_route.rs @@ -17,9 +17,12 @@ //! Tree route info type definition use util::numbers::H256; +use ipc::BinaryConvertError; +use std::collections::VecDeque; +use std::mem; /// Represents a tree route between `from` block and `to` block: -#[derive(Debug)] +#[derive(Debug, Binary)] pub struct TreeRoute { /// A vector of hashes of all blocks, ordered from `from` to `to`. pub blocks: Vec, diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs index f33d640f4..cfc7420f2 100644 --- a/ipc/rpc/src/binary.rs +++ b/ipc/rpc/src/binary.rs @@ -315,6 +315,31 @@ impl BinaryConvertable for String { } } +impl BinaryConvertable for Range where T: BinaryConvertable { + fn size(&self) -> usize { + mem::size_of::() * 2 + } + + fn from_empty_bytes() -> Result { + Err(BinaryConvertError) + } + + fn to_bytes(&self, buffer: &mut[u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { + try!(self.start.to_bytes(&mut buffer[..mem::size_of::()], length_stack)); + try!(self.end.to_bytes(&mut buffer[mem::size_of::() + 1..], length_stack)); + Ok(()) + } + + fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { + Ok(try!(T::from_bytes(&buffer[..mem::size_of::()], length_stack))..try!(T::from_bytes(&buffer[mem::size_of::()+1..], length_stack))) + } + + fn len_params() -> usize { + assert_eq!(0, T::len_params()); + 0 + } +} + impl BinaryConvertable for ::std::cell::RefCell where T: BinaryConvertable { fn size(&self) -> usize { self.borrow().size() @@ -539,8 +564,6 @@ binary_fixed_size!(U512); binary_fixed_size!(H256); binary_fixed_size!(H2048); binary_fixed_size!(Address); -binary_fixed_size!(Range); -binary_fixed_size!(Range); #[test] fn vec_serialize() { diff --git a/ipc/rpc/src/interface.rs b/ipc/rpc/src/interface.rs index 820994a2b..d4514467f 100644 --- a/ipc/rpc/src/interface.rs +++ b/ipc/rpc/src/interface.rs @@ -91,7 +91,7 @@ pub fn invoke(method_num: u16, params: &Option>, w: &mut W) where W: } /// IpcSocket, read/write generalization -pub trait IpcSocket: Read + Write + Sync { +pub trait IpcSocket: Read + Write + Sync + Send { } /// Basically something that needs only socket to be spawned diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 7550adb84..ed9bfd347 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -25,6 +25,7 @@ transient-hashmap = "0.1" serde_macros = { version = "0.7.0", optional = true } clippy = { version = "0.0.78", optional = true} json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } +ethcore-ipc = { path = "../ipc/rpc" } [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 43c120e40..73a769b13 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -32,6 +32,7 @@ extern crate ethcore; extern crate ethsync; extern crate transient_hashmap; extern crate json_ipc_server as ipc; +extern crate ethcore_ipc; #[cfg(test)] extern crate ethjson; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 13f54feea..dd29b425e 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -30,6 +30,7 @@ use util::sha3::*; use util::rlp::{encode, decode, UntrustedRlp, View}; use ethcore::account_provider::AccountProvider; use ethcore::client::{MiningBlockChainClient, BlockID, TransactionID, UncleID}; +use ethcore::header::Header as BlockHeader; use ethcore::block::IsBlock; use ethcore::views::*; use ethcore::ethereum::Ethash; @@ -42,7 +43,6 @@ use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncIn use v1::helpers::CallRequest as CRequest; use v1::impls::{default_gas_price, dispatch_transaction, error_codes}; use serde; -use ethcore::header::Header as BlockHeader; /// Eth rpc implementation. pub struct EthClient where diff --git a/rpc/src/v1/types/filter.rs b/rpc/src/v1/types/filter.rs index a34bb9ae9..e07845211 100644 --- a/rpc/src/v1/types/filter.rs +++ b/rpc/src/v1/types/filter.rs @@ -84,7 +84,7 @@ impl Into for Filter { VariadicValue::Single(t) => Some(vec![t.into()]), VariadicValue::Multiple(t) => Some(t.into_iter().map(Into::into).collect()) }).filter_map(|m| m).collect()).into_iter(); - [iter.next(), iter.next(), iter.next(), iter.next()] + vec![iter.next(), iter.next(), iter.next(), iter.next()] } } } diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index cc193c9fc..b9ce8a3ea 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -162,7 +162,7 @@ pub enum Diff where T: Serialize { Changed(ChangedType), } -impl From> for Diff where T: Eq, U: Serialize + From { +impl From> for Diff where T: Eq + ::ethcore_ipc::BinaryConvertable, U: Serialize + From { fn from(c: account_diff::Diff) -> Self { match c { account_diff::Diff::Same => Diff::Same, @@ -205,7 +205,7 @@ impl Serialize for StateDiff { impl From for StateDiff { fn from(c: state_diff::StateDiff) -> Self { - StateDiff(c.0.into_iter().map(|(k, v)| (k.into(), v.into())).collect()) + StateDiff(c.raw.into_iter().map(|(k, v)| (k.into(), v.into())).collect()) } }