From 82373ab7a412e45eea373f52d3035e4ffcdbe860 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 20 Jan 2016 04:19:38 +0100 Subject: [PATCH 01/54] inital commit with eth_blockNumber working --- Cargo.toml | 3 +++ src/bin/client/ethrpc.rs | 53 ++++++++++++++++++++++++++++++++++++++++ src/bin/client/main.rs | 15 ++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/bin/client/ethrpc.rs diff --git a/Cargo.toml b/Cargo.toml index 04c4bf956..32be356c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,10 +20,13 @@ time = "0.1" evmjit = { path = "rust-evmjit", optional = true } ethash = { path = "ethash" } num_cpus = "0.2" +jsonrpc-core = { version = "1.0", optional = true } +jsonrpc-http-server = { version = "1.0", optional = true } [features] jit = ["evmjit"] evm_debug = [] +rpc = ["jsonrpc-core", "jsonrpc-http-server"] [[bin]] name = "client" diff --git a/src/bin/client/ethrpc.rs b/src/bin/client/ethrpc.rs new file mode 100644 index 000000000..d46a91559 --- /dev/null +++ b/src/bin/client/ethrpc.rs @@ -0,0 +1,53 @@ +extern crate jsonrpc_core; +extern crate jsonrpc_http_server; + +use std::sync::{Arc, RwLock}; +use self::jsonrpc_core::{IoHandler, IoDelegate, Params, Value, Error, ErrorCode}; +use ethcore::client::*; + +struct Eth { + client: Arc> +} + +impl Eth { + fn new(client: Arc>) -> Self { + Eth { + client: client + } + } + + fn block_number(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::U64(self.client.read().unwrap().chain_info().best_block_number)), + _ => Err(Error::new(ErrorCode::InvalidParams)), + } + } +} + +struct EthRpc; + +impl EthRpc { + fn build_handler(client: Arc>) -> IoHandler { + let mut handler = IoHandler::new(); + let mut eth = IoDelegate::new(Arc::new(Eth::new(client))); + eth.add_method("eth_blockNumber", Eth::block_number); + handler.add_delegate(eth); + handler + } +} + +pub struct HttpServer { + server: jsonrpc_http_server::Server +} + +impl HttpServer { + pub fn new(client: Arc>, threads: usize) -> HttpServer { + HttpServer { + server: jsonrpc_http_server::Server::new(EthRpc::build_handler(client), threads) + } + } + + pub fn start_async(self, addr: &str) { + self.server.start_async(addr) + } +} diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index 3335d8a72..bf1b82909 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -4,6 +4,9 @@ extern crate rustc_serialize; extern crate log; extern crate env_logger; +#[cfg(feature = "rpc")] +mod ethrpc; + use std::io::stdin; use std::env; use log::{LogLevelFilter}; @@ -26,10 +29,22 @@ fn setup_log() { builder.init().unwrap(); } + +#[cfg(feature = "rpc")] +fn setup_rpc_server(client: Arc>) { + let server = ethrpc::HttpServer::new(client, 1); + server.start_async("127.0.0.1:3030"); +} + +#[cfg(not(feature = "rpc"))] +fn setup_rpc_server(_client: Arc>) { +} + fn main() { setup_log(); let spec = ethereum::new_frontier(); let mut service = ClientService::start(spec).unwrap(); + setup_rpc_server(service.client()); let io_handler = Box::new(ClientIoHandler { client: service.client(), timer: 0, info: Default::default() }); service.io().register_handler(io_handler).expect("Error registering IO handler"); loop { From a8e4912551f1df3877189800d91d8445d17526ef Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 20 Jan 2016 15:49:49 +0100 Subject: [PATCH 02/54] cleanup ethrpc --- src/bin/client/ethrpc.rs | 75 +++++++++++++++++++++++++++++----------- src/bin/client/main.rs | 3 +- 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/bin/client/ethrpc.rs b/src/bin/client/ethrpc.rs index d46a91559..735250d87 100644 --- a/src/bin/client/ethrpc.rs +++ b/src/bin/client/ethrpc.rs @@ -5,17 +5,56 @@ use std::sync::{Arc, RwLock}; use self::jsonrpc_core::{IoHandler, IoDelegate, Params, Value, Error, ErrorCode}; use ethcore::client::*; -struct Eth { - client: Arc> +macro_rules! rpcerr { + () => (Err(Error::new(ErrorCode::InternalError))) } -impl Eth { - fn new(client: Arc>) -> Self { - Eth { +/// This could be a part of `jsonrpc_core`. Unfortunately, +/// "only traits defined in the current crate can be implemented for a type parameter". +pub trait IntoDelegate where T: Send + Sync + 'static { + /// This function should be called to translate custom type into IoDelegate + fn into_delegate(self) -> IoDelegate; +} + +/// eth rpc interface +pub trait Eth { + /// returns protocol version + fn protocol_version(&self, _: Params) -> Result { rpcerr!() } + + /// returns block author + fn author(&self, _: Params) -> Result { rpcerr!() } + + /// returns current gas_price + fn gas_price(&self, _: Params) -> Result { rpcerr!() } + + /// returns highest block number + fn block_number(&self, _: Params) -> Result { rpcerr!() } +} + +impl IntoDelegate for D where D: Eth + Send + Sync + 'static { + fn into_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("eth_protocolVersion", D::protocol_version); + delegate.add_method("eth_coinbase", D::author); + delegate.add_method("eth_gasPrice", D::gas_price); + delegate.add_method("eth_blockNumber", D::block_number); + delegate + } +} + +pub struct EthClient { + client: Arc>, +} + +impl EthClient { + pub fn new(client: Arc>) -> Self { + EthClient { client: client } } +} +impl Eth for EthClient { fn block_number(&self, params: Params) -> Result { match params { Params::None => Ok(Value::U64(self.client.read().unwrap().chain_info().best_block_number)), @@ -24,30 +63,26 @@ impl Eth { } } -struct EthRpc; - -impl EthRpc { - fn build_handler(client: Arc>) -> IoHandler { - let mut handler = IoHandler::new(); - let mut eth = IoDelegate::new(Arc::new(Eth::new(client))); - eth.add_method("eth_blockNumber", Eth::block_number); - handler.add_delegate(eth); - handler - } -} pub struct HttpServer { - server: jsonrpc_http_server::Server + handler: IoHandler, + threads: usize } impl HttpServer { - pub fn new(client: Arc>, threads: usize) -> HttpServer { + pub fn new(threads: usize) -> HttpServer { HttpServer { - server: jsonrpc_http_server::Server::new(EthRpc::build_handler(client), threads) + handler: IoHandler::new(), + threads: threads } } + pub fn add_delegate(&mut self, delegate: I) where D: Send + Sync + 'static, I: IntoDelegate { + self.handler.add_delegate(delegate.into_delegate()); + } + pub fn start_async(self, addr: &str) { - self.server.start_async(addr) + let server = jsonrpc_http_server::Server::new(self.handler, self.threads); + server.start_async(addr) } } diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index bf1b82909..3dd9b9c5c 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -32,7 +32,8 @@ fn setup_log() { #[cfg(feature = "rpc")] fn setup_rpc_server(client: Arc>) { - let server = ethrpc::HttpServer::new(client, 1); + let mut server = ethrpc::HttpServer::new(1); + server.add_delegate(ethrpc::EthClient::new(client)); server.start_async("127.0.0.1:3030"); } From 013ac2cf9a4b1ccb0c49610590520f6871e3963a Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 21 Jan 2016 00:54:19 +0100 Subject: [PATCH 03/54] rpc api in progress --- src/bin/client/ethrpc.rs | 119 +++++++++++++++++++++++++++++++-------- src/bin/client/main.rs | 7 ++- 2 files changed, 102 insertions(+), 24 deletions(-) diff --git a/src/bin/client/ethrpc.rs b/src/bin/client/ethrpc.rs index 735250d87..09c93041f 100644 --- a/src/bin/client/ethrpc.rs +++ b/src/bin/client/ethrpc.rs @@ -2,46 +2,101 @@ extern crate jsonrpc_core; extern crate jsonrpc_http_server; use std::sync::{Arc, RwLock}; +use rustc_serialize::hex::ToHex; use self::jsonrpc_core::{IoHandler, IoDelegate, Params, Value, Error, ErrorCode}; use ethcore::client::*; +use util::hash::*; macro_rules! rpcerr { - () => (Err(Error::new(ErrorCode::InternalError))) + () => (Err(Error::internal_error())) } -/// This could be a part of `jsonrpc_core`. Unfortunately, -/// "only traits defined in the current crate can be implemented for a type parameter". -pub trait IntoDelegate where T: Send + Sync + 'static { - /// This function should be called to translate custom type into IoDelegate - fn into_delegate(self) -> IoDelegate; +/// Web3 rpc interface. +pub trait Web3: Sized + Send + Sync + 'static { + /// Returns current client version. + fn client_version(&self, _: Params) -> Result { rpcerr!() } + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("web3_clientVersion", Web3::client_version); + delegate + } } -/// eth rpc interface -pub trait Eth { - /// returns protocol version + +/// Eth rpc interface. +pub trait Eth: Sized + Send + Sync + 'static { + /// Returns protocol version. fn protocol_version(&self, _: Params) -> Result { rpcerr!() } - /// returns block author + /// Returns block author. fn author(&self, _: Params) -> Result { rpcerr!() } - /// returns current gas_price + /// Returns current gas_price. fn gas_price(&self, _: Params) -> Result { rpcerr!() } - /// returns highest block number + /// Returns highest block number. fn block_number(&self, _: Params) -> Result { rpcerr!() } + + /// Returns block with given index / hash. + fn block(&self, _: Params) -> Result { rpcerr!() } + + /// Returns true if client is actively mining new blocks. + fn is_mining(&self, _: Params) -> Result { rpcerr!() } + + /// Returns the number of hashes per second that the node is mining with. + fn hashrate(&self, _: Params) -> Result { rpcerr!() } + + /// Returns the number of transactions in a block. + fn block_transaction_count(&self, _: Params) -> Result { rpcerr!() } + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("eth_protocolVersion", Eth::protocol_version); + delegate.add_method("eth_coinbase", Eth::author); + delegate.add_method("eth_gasPrice", Eth::gas_price); + delegate.add_method("eth_blockNumber", Eth::block_number); + delegate.add_method("eth_getBlockByNumber", Eth::block); + delegate.add_method("eth_mining", Eth::is_mining); + delegate.add_method("eth_hashrate", Eth::hashrate); + delegate.add_method("eth_getBlockTransactionCountByNumber", Eth::block_transaction_count); + delegate + } } -impl IntoDelegate for D where D: Eth + Send + Sync + 'static { - fn into_delegate(self) -> IoDelegate { +/// Net rpc interface. +pub trait Net: Sized + Send + Sync + 'static { + /// Returns protocol version. + fn version(&self, _: Params) -> Result { rpcerr!() } + + /// Returns number of peers connected to node. + fn peer_count(&self, _: Params) -> Result { rpcerr!() } + + fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); - delegate.add_method("eth_protocolVersion", D::protocol_version); - delegate.add_method("eth_coinbase", D::author); - delegate.add_method("eth_gasPrice", D::gas_price); - delegate.add_method("eth_blockNumber", D::block_number); + delegate.add_method("peer_count", Net::version); + delegate.add_method("net_version", Net::version); delegate } } +pub struct Web3Client; + +impl Web3Client { + pub fn new() -> Self { Web3Client } +} + +impl Web3 for Web3Client { + fn client_version(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::String("parity/0.1.0/-/rust1.7-nightly".to_string())), + _ => Err(Error::invalid_params()) + } + } +} + pub struct EthClient { client: Arc>, } @@ -55,15 +110,35 @@ impl EthClient { } impl Eth for EthClient { + fn protocol_version(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::U64(63)), + _ => Err(Error::invalid_params()) + } + } + + fn author(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::String(Address::new().to_hex())), + _ => Err(Error::invalid_params()) + } + } + fn block_number(&self, params: Params) -> Result { match params { Params::None => Ok(Value::U64(self.client.read().unwrap().chain_info().best_block_number)), - _ => Err(Error::new(ErrorCode::InvalidParams)), + _ => Err(Error::invalid_params()) + } + } + + fn is_mining(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::Bool(false)), + _ => Err(Error::invalid_params()) } } } - pub struct HttpServer { handler: IoHandler, threads: usize @@ -77,8 +152,8 @@ impl HttpServer { } } - pub fn add_delegate(&mut self, delegate: I) where D: Send + Sync + 'static, I: IntoDelegate { - self.handler.add_delegate(delegate.into_delegate()); + pub fn add_delegate(&mut self, delegate: IoDelegate) where D: Send + Sync + 'static { + self.handler.add_delegate(delegate); } pub fn start_async(self, addr: &str) { diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index 3dd9b9c5c..f9f073718 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -32,8 +32,11 @@ fn setup_log() { #[cfg(feature = "rpc")] fn setup_rpc_server(client: Arc>) { - let mut server = ethrpc::HttpServer::new(1); - server.add_delegate(ethrpc::EthClient::new(client)); + use self::ethrpc::*; + + let mut server = HttpServer::new(1); + server.add_delegate(Web3Client::new().to_delegate()); + server.add_delegate(EthClient::new(client).to_delegate()); server.start_async("127.0.0.1:3030"); } From 201c4726a22bc0d9e5f32d519f119596233a8be1 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 21 Jan 2016 01:19:29 +0100 Subject: [PATCH 04/54] split rpc into multiple files --- src/bin/client/ethrpc.rs | 163 ------------------------------ src/bin/client/main.rs | 4 +- src/bin/client/rpc/impls/eth.rs | 48 +++++++++ src/bin/client/rpc/impls/mod.rs | 7 ++ src/bin/client/rpc/impls/net.rs | 0 src/bin/client/rpc/impls/web3.rs | 17 ++++ src/bin/client/rpc/mod.rs | 38 +++++++ src/bin/client/rpc/traits/eth.rs | 45 +++++++++ src/bin/client/rpc/traits/mod.rs | 8 ++ src/bin/client/rpc/traits/net.rs | 20 ++++ src/bin/client/rpc/traits/web3.rs | 16 +++ 11 files changed, 201 insertions(+), 165 deletions(-) delete mode 100644 src/bin/client/ethrpc.rs create mode 100644 src/bin/client/rpc/impls/eth.rs create mode 100644 src/bin/client/rpc/impls/mod.rs create mode 100644 src/bin/client/rpc/impls/net.rs create mode 100644 src/bin/client/rpc/impls/web3.rs create mode 100644 src/bin/client/rpc/mod.rs create mode 100644 src/bin/client/rpc/traits/eth.rs create mode 100644 src/bin/client/rpc/traits/mod.rs create mode 100644 src/bin/client/rpc/traits/net.rs create mode 100644 src/bin/client/rpc/traits/web3.rs diff --git a/src/bin/client/ethrpc.rs b/src/bin/client/ethrpc.rs deleted file mode 100644 index 09c93041f..000000000 --- a/src/bin/client/ethrpc.rs +++ /dev/null @@ -1,163 +0,0 @@ -extern crate jsonrpc_core; -extern crate jsonrpc_http_server; - -use std::sync::{Arc, RwLock}; -use rustc_serialize::hex::ToHex; -use self::jsonrpc_core::{IoHandler, IoDelegate, Params, Value, Error, ErrorCode}; -use ethcore::client::*; -use util::hash::*; - -macro_rules! rpcerr { - () => (Err(Error::internal_error())) -} - -/// Web3 rpc interface. -pub trait Web3: Sized + Send + Sync + 'static { - /// Returns current client version. - fn client_version(&self, _: Params) -> Result { rpcerr!() } - - /// Should be used to convert object to io delegate. - fn to_delegate(self) -> IoDelegate { - let mut delegate = IoDelegate::new(Arc::new(self)); - delegate.add_method("web3_clientVersion", Web3::client_version); - delegate - } -} - - -/// Eth rpc interface. -pub trait Eth: Sized + Send + Sync + 'static { - /// Returns protocol version. - fn protocol_version(&self, _: Params) -> Result { rpcerr!() } - - /// Returns block author. - fn author(&self, _: Params) -> Result { rpcerr!() } - - /// Returns current gas_price. - fn gas_price(&self, _: Params) -> Result { rpcerr!() } - - /// Returns highest block number. - fn block_number(&self, _: Params) -> Result { rpcerr!() } - - /// Returns block with given index / hash. - fn block(&self, _: Params) -> Result { rpcerr!() } - - /// Returns true if client is actively mining new blocks. - fn is_mining(&self, _: Params) -> Result { rpcerr!() } - - /// Returns the number of hashes per second that the node is mining with. - fn hashrate(&self, _: Params) -> Result { rpcerr!() } - - /// Returns the number of transactions in a block. - fn block_transaction_count(&self, _: Params) -> Result { rpcerr!() } - - /// Should be used to convert object to io delegate. - fn to_delegate(self) -> IoDelegate { - let mut delegate = IoDelegate::new(Arc::new(self)); - delegate.add_method("eth_protocolVersion", Eth::protocol_version); - delegate.add_method("eth_coinbase", Eth::author); - delegate.add_method("eth_gasPrice", Eth::gas_price); - delegate.add_method("eth_blockNumber", Eth::block_number); - delegate.add_method("eth_getBlockByNumber", Eth::block); - delegate.add_method("eth_mining", Eth::is_mining); - delegate.add_method("eth_hashrate", Eth::hashrate); - delegate.add_method("eth_getBlockTransactionCountByNumber", Eth::block_transaction_count); - delegate - } -} - -/// Net rpc interface. -pub trait Net: Sized + Send + Sync + 'static { - /// Returns protocol version. - fn version(&self, _: Params) -> Result { rpcerr!() } - - /// Returns number of peers connected to node. - fn peer_count(&self, _: Params) -> Result { rpcerr!() } - - fn to_delegate(self) -> IoDelegate { - let mut delegate = IoDelegate::new(Arc::new(self)); - delegate.add_method("peer_count", Net::version); - delegate.add_method("net_version", Net::version); - delegate - } -} - -pub struct Web3Client; - -impl Web3Client { - pub fn new() -> Self { Web3Client } -} - -impl Web3 for Web3Client { - fn client_version(&self, params: Params) -> Result { - match params { - Params::None => Ok(Value::String("parity/0.1.0/-/rust1.7-nightly".to_string())), - _ => Err(Error::invalid_params()) - } - } -} - -pub struct EthClient { - client: Arc>, -} - -impl EthClient { - pub fn new(client: Arc>) -> Self { - EthClient { - client: client - } - } -} - -impl Eth for EthClient { - fn protocol_version(&self, params: Params) -> Result { - match params { - Params::None => Ok(Value::U64(63)), - _ => Err(Error::invalid_params()) - } - } - - fn author(&self, params: Params) -> Result { - match params { - Params::None => Ok(Value::String(Address::new().to_hex())), - _ => Err(Error::invalid_params()) - } - } - - fn block_number(&self, params: Params) -> Result { - match params { - Params::None => Ok(Value::U64(self.client.read().unwrap().chain_info().best_block_number)), - _ => Err(Error::invalid_params()) - } - } - - fn is_mining(&self, params: Params) -> Result { - match params { - Params::None => Ok(Value::Bool(false)), - _ => Err(Error::invalid_params()) - } - } -} - -pub struct HttpServer { - handler: IoHandler, - threads: usize -} - -impl HttpServer { - pub fn new(threads: usize) -> HttpServer { - HttpServer { - handler: IoHandler::new(), - threads: threads - } - } - - pub fn add_delegate(&mut self, delegate: IoDelegate) where D: Send + Sync + 'static { - self.handler.add_delegate(delegate); - } - - pub fn start_async(self, addr: &str) { - let server = jsonrpc_http_server::Server::new(self.handler, self.threads); - server.start_async(addr) - } -} diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index f9f073718..bb19ca700 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -5,7 +5,7 @@ extern crate log; extern crate env_logger; #[cfg(feature = "rpc")] -mod ethrpc; +mod rpc; use std::io::stdin; use std::env; @@ -32,7 +32,7 @@ fn setup_log() { #[cfg(feature = "rpc")] fn setup_rpc_server(client: Arc>) { - use self::ethrpc::*; + use self::rpc::*; let mut server = HttpServer::new(1); server.add_delegate(Web3Client::new().to_delegate()); diff --git a/src/bin/client/rpc/impls/eth.rs b/src/bin/client/rpc/impls/eth.rs new file mode 100644 index 000000000..89c23419e --- /dev/null +++ b/src/bin/client/rpc/impls/eth.rs @@ -0,0 +1,48 @@ +use std::sync::{Arc, RwLock}; +use rustc_serialize::hex::ToHex; +use util::hash::*; +use ethcore::client::*; +use rpc::jsonrpc_core::*; +use rpc::Eth; + +pub struct EthClient { + client: Arc>, +} + +impl EthClient { + pub fn new(client: Arc>) -> Self { + EthClient { + client: client + } + } +} + +impl Eth for EthClient { + fn protocol_version(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::U64(63)), + _ => Err(Error::invalid_params()) + } + } + + fn author(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::String(Address::new().to_hex())), + _ => Err(Error::invalid_params()) + } + } + + fn block_number(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::U64(self.client.read().unwrap().chain_info().best_block_number)), + _ => Err(Error::invalid_params()) + } + } + + fn is_mining(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::Bool(false)), + _ => Err(Error::invalid_params()) + } + } +} diff --git a/src/bin/client/rpc/impls/mod.rs b/src/bin/client/rpc/impls/mod.rs new file mode 100644 index 000000000..d229c5c13 --- /dev/null +++ b/src/bin/client/rpc/impls/mod.rs @@ -0,0 +1,7 @@ +//! Ethereum rpc interface implementation. +pub mod web3; +pub mod eth; +pub mod net; + +pub use self::web3::Web3Client; +pub use self::eth::EthClient; diff --git a/src/bin/client/rpc/impls/net.rs b/src/bin/client/rpc/impls/net.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/bin/client/rpc/impls/web3.rs b/src/bin/client/rpc/impls/web3.rs new file mode 100644 index 000000000..b7d8919e2 --- /dev/null +++ b/src/bin/client/rpc/impls/web3.rs @@ -0,0 +1,17 @@ +use rpc::jsonrpc_core::*; +use rpc::Web3; + +pub struct Web3Client; + +impl Web3Client { + pub fn new() -> Self { Web3Client } +} + +impl Web3 for Web3Client { + fn client_version(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::String("parity/0.1.0/-/rust1.7-nightly".to_string())), + _ => Err(Error::invalid_params()) + } + } +} diff --git a/src/bin/client/rpc/mod.rs b/src/bin/client/rpc/mod.rs new file mode 100644 index 000000000..1053904e9 --- /dev/null +++ b/src/bin/client/rpc/mod.rs @@ -0,0 +1,38 @@ +extern crate jsonrpc_core; +extern crate jsonrpc_http_server; + +use self::jsonrpc_core::{IoHandler, IoDelegate}; + +macro_rules! rpcerr { + () => (Err(Error::internal_error())) +} + +pub mod traits; +pub mod impls; + +pub use self::traits::{Web3, Eth, Net}; +pub use self::impls::*; + + +pub struct HttpServer { + handler: IoHandler, + threads: usize +} + +impl HttpServer { + pub fn new(threads: usize) -> HttpServer { + HttpServer { + handler: IoHandler::new(), + threads: threads + } + } + + pub fn add_delegate(&mut self, delegate: IoDelegate) where D: Send + Sync + 'static { + self.handler.add_delegate(delegate); + } + + pub fn start_async(self, addr: &str) { + let server = jsonrpc_http_server::Server::new(self.handler, self.threads); + server.start_async(addr) + } +} diff --git a/src/bin/client/rpc/traits/eth.rs b/src/bin/client/rpc/traits/eth.rs new file mode 100644 index 000000000..8703d21fc --- /dev/null +++ b/src/bin/client/rpc/traits/eth.rs @@ -0,0 +1,45 @@ +//! Eth rpc interface. +use std::sync::Arc; +use rpc::jsonrpc_core::*; + +/// Eth rpc interface. +pub trait Eth: Sized + Send + Sync + 'static { + /// Returns protocol version. + fn protocol_version(&self, _: Params) -> Result { rpcerr!() } + + /// Returns block author. + fn author(&self, _: Params) -> Result { rpcerr!() } + + /// Returns current gas_price. + fn gas_price(&self, _: Params) -> Result { rpcerr!() } + + /// Returns highest block number. + fn block_number(&self, _: Params) -> Result { rpcerr!() } + + /// Returns block with given index / hash. + fn block(&self, _: Params) -> Result { rpcerr!() } + + /// Returns true if client is actively mining new blocks. + fn is_mining(&self, _: Params) -> Result { rpcerr!() } + + /// Returns the number of hashes per second that the node is mining with. + fn hashrate(&self, _: Params) -> Result { rpcerr!() } + + /// Returns the number of transactions in a block. + fn block_transaction_count(&self, _: Params) -> Result { rpcerr!() } + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("eth_protocolVersion", Eth::protocol_version); + delegate.add_method("eth_coinbase", Eth::author); + delegate.add_method("eth_gasPrice", Eth::gas_price); + delegate.add_method("eth_blockNumber", Eth::block_number); + delegate.add_method("eth_getBlockByNumber", Eth::block); + delegate.add_method("eth_mining", Eth::is_mining); + delegate.add_method("eth_hashrate", Eth::hashrate); + delegate.add_method("eth_getBlockTransactionCountByNumber", Eth::block_transaction_count); + delegate + } +} + diff --git a/src/bin/client/rpc/traits/mod.rs b/src/bin/client/rpc/traits/mod.rs new file mode 100644 index 000000000..83f70f17d --- /dev/null +++ b/src/bin/client/rpc/traits/mod.rs @@ -0,0 +1,8 @@ +//! Ethereum rpc interfaces. +pub mod web3; +pub mod eth; +pub mod net; + +pub use self::web3::Web3; +pub use self::eth::Eth; +pub use self::net::Net; diff --git a/src/bin/client/rpc/traits/net.rs b/src/bin/client/rpc/traits/net.rs new file mode 100644 index 000000000..7cb7f6bee --- /dev/null +++ b/src/bin/client/rpc/traits/net.rs @@ -0,0 +1,20 @@ +//! Net rpc interface. +use std::sync::Arc; +use rpc::jsonrpc_core::*; + +/// Net rpc interface. +pub trait Net: Sized + Send + Sync + 'static { + /// Returns protocol version. + fn version(&self, _: Params) -> Result { rpcerr!() } + + /// Returns number of peers connected to node. + fn peer_count(&self, _: Params) -> Result { rpcerr!() } + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("peer_count", Net::version); + delegate.add_method("net_version", Net::version); + delegate + } +} diff --git a/src/bin/client/rpc/traits/web3.rs b/src/bin/client/rpc/traits/web3.rs new file mode 100644 index 000000000..b71c867aa --- /dev/null +++ b/src/bin/client/rpc/traits/web3.rs @@ -0,0 +1,16 @@ +//! Web3 rpc interface. +use std::sync::Arc; +use rpc::jsonrpc_core::*; + +/// Web3 rpc interface. +pub trait Web3: Sized + Send + Sync + 'static { + /// Returns current client version. + fn client_version(&self, _: Params) -> Result { rpcerr!() } + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("web3_clientVersion", Web3::client_version); + delegate + } +} From 85de41642e20e4c7c391af3962e475cb86931d5f Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 21 Jan 2016 11:25:39 +0100 Subject: [PATCH 05/54] rpc api in progress --- src/bin/client/main.rs | 4 ++- src/bin/client/rpc/impls/eth.rs | 42 +++++++++++++++++++++++++++++++- src/bin/client/rpc/impls/mod.rs | 3 ++- src/bin/client/rpc/impls/net.rs | 15 ++++++++++++ src/bin/client/rpc/mod.rs | 2 +- src/bin/client/rpc/traits/eth.rs | 20 +++++++++++++++ src/bin/client/rpc/traits/mod.rs | 2 +- 7 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index bb19ca700..fc1b10b8a 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -36,7 +36,9 @@ fn setup_rpc_server(client: Arc>) { let mut server = HttpServer::new(1); server.add_delegate(Web3Client::new().to_delegate()); - server.add_delegate(EthClient::new(client).to_delegate()); + server.add_delegate(EthClient::new(client.clone()).to_delegate()); + server.add_delegate(EthFilterClient::new(client).to_delegate()); + server.add_delegate(NetClient::new().to_delegate()); server.start_async("127.0.0.1:3030"); } diff --git a/src/bin/client/rpc/impls/eth.rs b/src/bin/client/rpc/impls/eth.rs index 89c23419e..1151909ec 100644 --- a/src/bin/client/rpc/impls/eth.rs +++ b/src/bin/client/rpc/impls/eth.rs @@ -3,7 +3,7 @@ use rustc_serialize::hex::ToHex; use util::hash::*; use ethcore::client::*; use rpc::jsonrpc_core::*; -use rpc::Eth; +use rpc::{Eth, EthFilter}; pub struct EthClient { client: Arc>, @@ -32,6 +32,13 @@ impl Eth for EthClient { } } + fn gas_price(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::U64(0)), + _ => Err(Error::invalid_params()) + } + } + fn block_number(&self, params: Params) -> Result { match params { Params::None => Ok(Value::U64(self.client.read().unwrap().chain_info().best_block_number)), @@ -45,4 +52,37 @@ impl Eth for EthClient { _ => Err(Error::invalid_params()) } } + + fn hashrate(&self, params: Params) -> Result { + match params { + Params::None => Ok(Value::U64(0)), + _ => Err(Error::invalid_params()) + } + } +} + +pub struct EthFilterClient { + client: Arc> +} + +impl EthFilterClient { + pub fn new(client: Arc>) -> Self { + EthFilterClient { + client: client + } + } +} + +impl EthFilter for EthFilterClient { + fn new_block_filter(&self, _params: Params) -> Result { + Ok(Value::U64(0)) + } + + fn new_pending_transaction_filter(&self, _params: Params) -> Result { + Ok(Value::U64(1)) + } + + fn filter_changes(&self, _: Params) -> Result { + Ok(Value::String(self.client.read().unwrap().chain_info().best_block_hash.to_hex())) + } } diff --git a/src/bin/client/rpc/impls/mod.rs b/src/bin/client/rpc/impls/mod.rs index d229c5c13..813a168fd 100644 --- a/src/bin/client/rpc/impls/mod.rs +++ b/src/bin/client/rpc/impls/mod.rs @@ -4,4 +4,5 @@ pub mod eth; pub mod net; pub use self::web3::Web3Client; -pub use self::eth::EthClient; +pub use self::eth::{EthClient, EthFilterClient}; +pub use self::net::NetClient; diff --git a/src/bin/client/rpc/impls/net.rs b/src/bin/client/rpc/impls/net.rs index e69de29bb..6e528d156 100644 --- a/src/bin/client/rpc/impls/net.rs +++ b/src/bin/client/rpc/impls/net.rs @@ -0,0 +1,15 @@ +//! Net rpc implementation. +use rpc::jsonrpc_core::*; +use rpc::Net; + +pub struct NetClient; + +impl NetClient { + pub fn new() -> Self { NetClient } +} + +impl Net for NetClient { + fn peer_count(&self, _params: Params) -> Result { + Ok(Value::U64(0)) + } +} diff --git a/src/bin/client/rpc/mod.rs b/src/bin/client/rpc/mod.rs index 1053904e9..bf18e4b5f 100644 --- a/src/bin/client/rpc/mod.rs +++ b/src/bin/client/rpc/mod.rs @@ -10,7 +10,7 @@ macro_rules! rpcerr { pub mod traits; pub mod impls; -pub use self::traits::{Web3, Eth, Net}; +pub use self::traits::{Web3, Eth, EthFilter, Net}; pub use self::impls::*; diff --git a/src/bin/client/rpc/traits/eth.rs b/src/bin/client/rpc/traits/eth.rs index 8703d21fc..dfc72e89a 100644 --- a/src/bin/client/rpc/traits/eth.rs +++ b/src/bin/client/rpc/traits/eth.rs @@ -43,3 +43,23 @@ pub trait Eth: Sized + Send + Sync + 'static { } } +// TODO: do filters api properly if we commit outselves to polling again... +pub trait EthFilter: Sized + Send + Sync + 'static { + /// Returns id of new block filter + fn new_block_filter(&self, _: Params) -> Result { rpcerr!() } + + /// Returns id of new block filter + fn new_pending_transaction_filter(&self, _: Params) -> Result { rpcerr!() } + + /// Returns filter changes since last poll + fn filter_changes(&self, _: Params) -> Result { rpcerr!() } + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("eth_newBlockFilter", EthFilter::new_block_filter); + delegate.add_method("eth_newPendingTransactionFilter", EthFilter::new_pending_transaction_filter); + delegate.add_method("eth_getFilterChanges", EthFilter::new_block_filter); + delegate + } +} diff --git a/src/bin/client/rpc/traits/mod.rs b/src/bin/client/rpc/traits/mod.rs index 83f70f17d..2fa52d538 100644 --- a/src/bin/client/rpc/traits/mod.rs +++ b/src/bin/client/rpc/traits/mod.rs @@ -4,5 +4,5 @@ pub mod eth; pub mod net; pub use self::web3::Web3; -pub use self::eth::Eth; +pub use self::eth::{Eth, EthFilter}; pub use self::net::Net; From f38b736c91499da04fbe6b44345181bf89ed63d8 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 25 Jan 2016 17:45:26 +0100 Subject: [PATCH 06/54] debugging rpc... --- src/bin/client/rpc/impls/eth.rs | 3 ++- src/bin/client/rpc/impls/net.rs | 4 ++++ src/bin/client/rpc/traits/eth.rs | 2 +- src/bin/client/rpc/traits/net.rs | 2 +- src/client.rs | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/bin/client/rpc/impls/eth.rs b/src/bin/client/rpc/impls/eth.rs index d960114ed..821eacd07 100644 --- a/src/bin/client/rpc/impls/eth.rs +++ b/src/bin/client/rpc/impls/eth.rs @@ -83,6 +83,7 @@ impl EthFilter for EthFilterClient { } fn filter_changes(&self, _: Params) -> Result { - Ok(Value::String(self.client.chain_info().best_block_hash.to_hex())) + println!("filter changes: {:?}", self.client.chain_info().best_block_hash.to_hex()); + Ok(Value::Array(vec![Value::String(self.client.chain_info().best_block_hash.to_hex())])) } } diff --git a/src/bin/client/rpc/impls/net.rs b/src/bin/client/rpc/impls/net.rs index 6e528d156..f0109429c 100644 --- a/src/bin/client/rpc/impls/net.rs +++ b/src/bin/client/rpc/impls/net.rs @@ -9,6 +9,10 @@ impl NetClient { } impl Net for NetClient { + fn version(&self, _: Params) -> Result { + Ok(Value::U64(63)) + } + fn peer_count(&self, _params: Params) -> Result { Ok(Value::U64(0)) } diff --git a/src/bin/client/rpc/traits/eth.rs b/src/bin/client/rpc/traits/eth.rs index dfc72e89a..856111444 100644 --- a/src/bin/client/rpc/traits/eth.rs +++ b/src/bin/client/rpc/traits/eth.rs @@ -59,7 +59,7 @@ pub trait EthFilter: Sized + Send + Sync + 'static { let mut delegate = IoDelegate::new(Arc::new(self)); delegate.add_method("eth_newBlockFilter", EthFilter::new_block_filter); delegate.add_method("eth_newPendingTransactionFilter", EthFilter::new_pending_transaction_filter); - delegate.add_method("eth_getFilterChanges", EthFilter::new_block_filter); + delegate.add_method("eth_getFilterChanges", EthFilter::filter_changes); delegate } } diff --git a/src/bin/client/rpc/traits/net.rs b/src/bin/client/rpc/traits/net.rs index 7cb7f6bee..63c64edb3 100644 --- a/src/bin/client/rpc/traits/net.rs +++ b/src/bin/client/rpc/traits/net.rs @@ -13,8 +13,8 @@ pub trait Net: Sized + Send + Sync + 'static { /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); - delegate.add_method("peer_count", Net::version); delegate.add_method("net_version", Net::version); + delegate.add_method("net_peerCount", Net::peer_count); delegate } } diff --git a/src/client.rs b/src/client.rs index 4461f3d7b..01da143e5 100644 --- a/src/client.rs +++ b/src/client.rs @@ -269,7 +269,7 @@ impl Client { /// Tick the client. pub fn tick(&self) { - self.chain.read().unwrap().collect_garbage(false); + //self.chain.read().unwrap().collect_garbage(false); } } From 5237c575660a1d9dd0566dbfe6a4d0b588a20fdd Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 26 Jan 2016 00:42:07 +0100 Subject: [PATCH 07/54] block transaction count --- src/bin/client/rpc/impls/eth.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin/client/rpc/impls/eth.rs b/src/bin/client/rpc/impls/eth.rs index 821eacd07..f4d102131 100644 --- a/src/bin/client/rpc/impls/eth.rs +++ b/src/bin/client/rpc/impls/eth.rs @@ -59,6 +59,10 @@ impl Eth for EthClient { _ => Err(Error::invalid_params()) } } + + fn block_transaction_count(&self, _: Params) -> Result { + Ok(Value::U64(0)) + } } pub struct EthFilterClient { @@ -83,7 +87,6 @@ impl EthFilter for EthFilterClient { } fn filter_changes(&self, _: Params) -> Result { - println!("filter changes: {:?}", self.client.chain_info().best_block_hash.to_hex()); Ok(Value::Array(vec![Value::String(self.client.chain_info().best_block_hash.to_hex())])) } } From b1282fe1f45ffca0dae5848ea684ef53b28f3dc8 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 26 Jan 2016 11:37:24 +0100 Subject: [PATCH 08/54] api block struct --- src/bin/client/main.rs | 2 ++ src/bin/client/rpc/impls/eth.rs | 6 +++++- src/bin/client/rpc/impls/mod.rs | 6 +++--- src/bin/client/rpc/mod.rs | 3 ++- src/bin/client/rpc/types/block.rs | 32 +++++++++++++++++++++++++++++++ src/bin/client/rpc/types/mod.rs | 1 + 6 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 src/bin/client/rpc/types/block.rs create mode 100644 src/bin/client/rpc/types/mod.rs diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index b88a28d72..53d5b2cd6 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -1,5 +1,7 @@ #![feature(plugin)] #![plugin(docopt_macros)] +// required for serde, move it to a separate library +#![feature(custom_derive, custom_attribute)] extern crate docopt; extern crate rustc_serialize; extern crate ethcore_util as util; diff --git a/src/bin/client/rpc/impls/eth.rs b/src/bin/client/rpc/impls/eth.rs index f4d102131..8fed91a14 100644 --- a/src/bin/client/rpc/impls/eth.rs +++ b/src/bin/client/rpc/impls/eth.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, RwLock}; +use std::sync::Arc; use rustc_serialize::hex::ToHex; use util::hash::*; use ethcore::client::*; @@ -63,6 +63,10 @@ impl Eth for EthClient { fn block_transaction_count(&self, _: Params) -> Result { Ok(Value::U64(0)) } + + fn block(&self, _: Params) -> Result { + Ok(Value::Null) + } } pub struct EthFilterClient { diff --git a/src/bin/client/rpc/impls/mod.rs b/src/bin/client/rpc/impls/mod.rs index 813a168fd..f10d613d0 100644 --- a/src/bin/client/rpc/impls/mod.rs +++ b/src/bin/client/rpc/impls/mod.rs @@ -1,7 +1,7 @@ //! Ethereum rpc interface implementation. -pub mod web3; -pub mod eth; -pub mod net; +mod web3; +mod eth; +mod net; pub use self::web3::Web3Client; pub use self::eth::{EthClient, EthFilterClient}; diff --git a/src/bin/client/rpc/mod.rs b/src/bin/client/rpc/mod.rs index bf18e4b5f..64f9137f0 100644 --- a/src/bin/client/rpc/mod.rs +++ b/src/bin/client/rpc/mod.rs @@ -8,7 +8,8 @@ macro_rules! rpcerr { } pub mod traits; -pub mod impls; +mod impls; +mod types; pub use self::traits::{Web3, Eth, EthFilter, Net}; pub use self::impls::*; diff --git a/src/bin/client/rpc/types/block.rs b/src/bin/client/rpc/types/block.rs new file mode 100644 index 000000000..ffb0f8042 --- /dev/null +++ b/src/bin/client/rpc/types/block.rs @@ -0,0 +1,32 @@ +use util::hash::*; +use util::uint::*; + +#[derive(Serialize)] +pub struct Block { + hash: H256, + #[serde(rename="parentHash")] + parent_hash: H256, + #[serde(rename="sha3Uncles")] + uncles_hash: H256, + author: Address, + // TODO: get rid of this one + miner: Address, + #[serde(rename="stateRoot")] + state_root: H256, + #[serde(rename="transactionsRoot")] + transactions_root: H256, + #[serde(rename="receiptsRoot")] + receipts_root: H256, + number: u64, + #[serde(rename="gasUsed")] + gas_used: U256, + #[serde(rename="gasLimit")] + gas_limit: U256, + // TODO: figure out how to properly serialize bytes + //#[serde(rename="extraData")] + //extra_data: Vec, + #[serde(rename="logsBloom")] + logs_bloom: H2048, + timestamp: u64 +} + diff --git a/src/bin/client/rpc/types/mod.rs b/src/bin/client/rpc/types/mod.rs new file mode 100644 index 000000000..fc9210db1 --- /dev/null +++ b/src/bin/client/rpc/types/mod.rs @@ -0,0 +1 @@ +mod block; From 800154a8ae66a941c50a5adacccfe94195831e85 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 14:39:49 +0400 Subject: [PATCH 09/54] client test creating --- src/tests/client.rs | 20 ++++++++++++++++++++ src/tests/mod.rs | 1 + 2 files changed, 21 insertions(+) create mode 100644 src/tests/client.rs diff --git a/src/tests/client.rs b/src/tests/client.rs new file mode 100644 index 000000000..25c8cb9b0 --- /dev/null +++ b/src/tests/client.rs @@ -0,0 +1,20 @@ +use ethereum; +use client::{BlockChainClient,Client}; +use std::env; +use pod_state::*; + + +#[test] +fn test_client_is_created() { + + let mut spec = ethereum::new_frontier_like_test(); + spec.set_genesis_state(PodState::from_json(test.find("pre").unwrap())); + spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); + + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + + let client_result = Client::new(spec, &dir, IOChannel::disconnected()); + + assert!(client_result.is_ok()); +} \ No newline at end of file diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c30f7f9b8..c6e38dbd0 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -4,3 +4,4 @@ mod test_common; mod transaction; mod executive; mod state; +mod client; \ No newline at end of file From d27c7f3902efb5e48635e2b307457c0e6fa20a63 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 26 Jan 2016 11:51:35 +0100 Subject: [PATCH 10/54] rpc block serialize test --- src/bin/client/rpc/types/block.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bin/client/rpc/types/block.rs b/src/bin/client/rpc/types/block.rs index ffb0f8042..138140f60 100644 --- a/src/bin/client/rpc/types/block.rs +++ b/src/bin/client/rpc/types/block.rs @@ -1,7 +1,7 @@ use util::hash::*; use util::uint::*; -#[derive(Serialize)] +#[derive(Default, Serialize)] pub struct Block { hash: H256, #[serde(rename="parentHash")] @@ -30,3 +30,12 @@ pub struct Block { timestamp: u64 } +#[test] +fn test_block_serialize() { + use serde_json; + + let block = Block::default(); + let serialized = serde_json::to_string(&block).unwrap(); + println!("s: {:?}", serialized); + assert!(false); +} From 46e0a81c52dce6905b3361068d8f63e10524f1d2 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 14:55:12 +0400 Subject: [PATCH 11/54] more of testing --- res/ethereum/tests | 2 +- src/tests/client.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/res/ethereum/tests b/res/ethereum/tests index dc86e6359..e838fd909 160000 --- a/res/ethereum/tests +++ b/res/ethereum/tests @@ -1 +1 @@ -Subproject commit dc86e6359675440aea59ddb48648a01c799925d8 +Subproject commit e838fd90998fc5502d0b7c9427a4c231f9a6953d diff --git a/src/tests/client.rs b/src/tests/client.rs index 25c8cb9b0..c0f202edd 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -2,6 +2,7 @@ use ethereum; use client::{BlockChainClient,Client}; use std::env; use pod_state::*; +use super::test_common::*; #[test] From 3ac40b68f862f734871bbc7ca19f9dc840689ea0 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 26 Jan 2016 13:14:22 +0100 Subject: [PATCH 12/54] rpc and bin moved to its own crates --- Cargo.toml | 10 ---------- bin/Cargo.toml | 20 +++++++++++++++++++ {src/bin/client => bin/src}/main.rs | 5 ++--- rpc/Cargo.toml | 19 ++++++++++++++++++ {src/bin/client/rpc => rpc/src}/impls/eth.rs | 4 ++-- {src/bin/client/rpc => rpc/src}/impls/mod.rs | 0 {src/bin/client/rpc => rpc/src}/impls/net.rs | 4 ++-- {src/bin/client/rpc => rpc/src}/impls/web3.rs | 4 ++-- src/bin/client/rpc/mod.rs => rpc/src/lib.rs | 8 +++++++- {src/bin/client/rpc => rpc/src}/traits/eth.rs | 2 +- {src/bin/client/rpc => rpc/src}/traits/mod.rs | 0 {src/bin/client/rpc => rpc/src}/traits/net.rs | 2 +- .../bin/client/rpc => rpc/src}/traits/web3.rs | 2 +- .../bin/client/rpc => rpc/src}/types/block.rs | 8 ++++---- {src/bin/client/rpc => rpc/src}/types/mod.rs | 0 15 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 bin/Cargo.toml rename {src/bin/client => bin/src}/main.rs (98%) create mode 100644 rpc/Cargo.toml rename {src/bin/client/rpc => rpc/src}/impls/eth.rs (97%) rename {src/bin/client/rpc => rpc/src}/impls/mod.rs (100%) rename {src/bin/client/rpc => rpc/src}/impls/net.rs (88%) rename {src/bin/client/rpc => rpc/src}/impls/web3.rs (88%) rename src/bin/client/rpc/mod.rs => rpc/src/lib.rs (80%) rename {src/bin/client/rpc => rpc/src}/traits/eth.rs (99%) rename {src/bin/client/rpc => rpc/src}/traits/mod.rs (100%) rename {src/bin/client/rpc => rpc/src}/traits/net.rs (95%) rename {src/bin/client/rpc => rpc/src}/traits/web3.rs (94%) rename {src/bin/client/rpc => rpc/src}/types/block.rs (84%) rename {src/bin/client/rpc => rpc/src}/types/mod.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 14f12e646..a0ea692b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,18 +21,8 @@ evmjit = { path = "rust-evmjit", optional = true } ethash = { path = "ethash" } num_cpus = "0.2" clippy = "0.0.37" -docopt = "0.6" -docopt_macros = "0.6" -ctrlc = "1.0" -jsonrpc-core = { version = "1.0", optional = true } -jsonrpc-http-server = { version = "1.0", optional = true } [features] jit = ["evmjit"] evm_debug = [] test-heavy = [] -rpc = ["jsonrpc-core", "jsonrpc-http-server"] - -[[bin]] -name = "client" -path = "src/bin/client/main.rs" diff --git a/bin/Cargo.toml b/bin/Cargo.toml new file mode 100644 index 000000000..ba258b586 --- /dev/null +++ b/bin/Cargo.toml @@ -0,0 +1,20 @@ +[package] +description = "Ethcore client." +name = "ethcore-client" +version = "0.1.0" +license = "GPL-3.0" +authors = ["Ethcore "] + +[dependencies] +log = "0.3" +env_logger = "0.3" +rustc-serialize = "0.3" +docopt = "0.6" +docopt_macros = "0.6" +ctrlc = "1.0" +ethcore-util = { path = "../util" } +ethcore-rpc = { path = "../rpc", optional = true } +ethcore = { path = ".." } + +[features] +rpc = ["ethcore-rpc"] diff --git a/src/bin/client/main.rs b/bin/src/main.rs similarity index 98% rename from src/bin/client/main.rs rename to bin/src/main.rs index 53d5b2cd6..942a5cf24 100644 --- a/src/bin/client/main.rs +++ b/bin/src/main.rs @@ -1,7 +1,6 @@ #![feature(plugin)] #![plugin(docopt_macros)] // required for serde, move it to a separate library -#![feature(custom_derive, custom_attribute)] extern crate docopt; extern crate rustc_serialize; extern crate ethcore_util as util; @@ -11,7 +10,7 @@ extern crate env_logger; extern crate ctrlc; #[cfg(feature = "rpc")] -mod rpc; +extern crate ethcore_rpc as rpc; use std::env; use log::{LogLevelFilter}; @@ -52,7 +51,7 @@ fn setup_log(init: &String) { #[cfg(feature = "rpc")] fn setup_rpc_server(client: Arc) { - use self::rpc::*; + use rpc::*; let mut server = HttpServer::new(1); server.add_delegate(Web3Client::new().to_delegate()); diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml new file mode 100644 index 000000000..d0f9f50e8 --- /dev/null +++ b/rpc/Cargo.toml @@ -0,0 +1,19 @@ +[package] +description = "Ethcore jsonrpc" +name = "ethcore-rpc" +version = "0.1.0" +license = "GPL-3.0" +authors = ["Marek Kotewicz , diff --git a/src/bin/client/rpc/impls/mod.rs b/rpc/src/impls/mod.rs similarity index 100% rename from src/bin/client/rpc/impls/mod.rs rename to rpc/src/impls/mod.rs diff --git a/src/bin/client/rpc/impls/net.rs b/rpc/src/impls/net.rs similarity index 88% rename from src/bin/client/rpc/impls/net.rs rename to rpc/src/impls/net.rs index f0109429c..a1d36de54 100644 --- a/src/bin/client/rpc/impls/net.rs +++ b/rpc/src/impls/net.rs @@ -1,6 +1,6 @@ //! Net rpc implementation. -use rpc::jsonrpc_core::*; -use rpc::Net; +use jsonrpc_core::*; +use traits::Net; pub struct NetClient; diff --git a/src/bin/client/rpc/impls/web3.rs b/rpc/src/impls/web3.rs similarity index 88% rename from src/bin/client/rpc/impls/web3.rs rename to rpc/src/impls/web3.rs index b7d8919e2..58e7858eb 100644 --- a/src/bin/client/rpc/impls/web3.rs +++ b/rpc/src/impls/web3.rs @@ -1,5 +1,5 @@ -use rpc::jsonrpc_core::*; -use rpc::Web3; +use jsonrpc_core::*; +use traits::Web3; pub struct Web3Client; diff --git a/src/bin/client/rpc/mod.rs b/rpc/src/lib.rs similarity index 80% rename from src/bin/client/rpc/mod.rs rename to rpc/src/lib.rs index 64f9137f0..148e9f134 100644 --- a/src/bin/client/rpc/mod.rs +++ b/rpc/src/lib.rs @@ -1,5 +1,12 @@ +#![feature(custom_derive, custom_attribute, plugin)] +#![plugin(serde_macros)] + +extern crate rustc_serialize; +extern crate serde; extern crate jsonrpc_core; extern crate jsonrpc_http_server; +extern crate ethcore_util as util; +extern crate ethcore; use self::jsonrpc_core::{IoHandler, IoDelegate}; @@ -14,7 +21,6 @@ mod types; pub use self::traits::{Web3, Eth, EthFilter, Net}; pub use self::impls::*; - pub struct HttpServer { handler: IoHandler, threads: usize diff --git a/src/bin/client/rpc/traits/eth.rs b/rpc/src/traits/eth.rs similarity index 99% rename from src/bin/client/rpc/traits/eth.rs rename to rpc/src/traits/eth.rs index 856111444..31e9df164 100644 --- a/src/bin/client/rpc/traits/eth.rs +++ b/rpc/src/traits/eth.rs @@ -1,6 +1,6 @@ //! Eth rpc interface. use std::sync::Arc; -use rpc::jsonrpc_core::*; +use jsonrpc_core::*; /// Eth rpc interface. pub trait Eth: Sized + Send + Sync + 'static { diff --git a/src/bin/client/rpc/traits/mod.rs b/rpc/src/traits/mod.rs similarity index 100% rename from src/bin/client/rpc/traits/mod.rs rename to rpc/src/traits/mod.rs diff --git a/src/bin/client/rpc/traits/net.rs b/rpc/src/traits/net.rs similarity index 95% rename from src/bin/client/rpc/traits/net.rs rename to rpc/src/traits/net.rs index 63c64edb3..4df8d7114 100644 --- a/src/bin/client/rpc/traits/net.rs +++ b/rpc/src/traits/net.rs @@ -1,6 +1,6 @@ //! Net rpc interface. use std::sync::Arc; -use rpc::jsonrpc_core::*; +use jsonrpc_core::*; /// Net rpc interface. pub trait Net: Sized + Send + Sync + 'static { diff --git a/src/bin/client/rpc/traits/web3.rs b/rpc/src/traits/web3.rs similarity index 94% rename from src/bin/client/rpc/traits/web3.rs rename to rpc/src/traits/web3.rs index b71c867aa..8e73d4304 100644 --- a/src/bin/client/rpc/traits/web3.rs +++ b/rpc/src/traits/web3.rs @@ -1,6 +1,6 @@ //! Web3 rpc interface. use std::sync::Arc; -use rpc::jsonrpc_core::*; +use jsonrpc_core::*; /// Web3 rpc interface. pub trait Web3: Sized + Send + Sync + 'static { diff --git a/src/bin/client/rpc/types/block.rs b/rpc/src/types/block.rs similarity index 84% rename from src/bin/client/rpc/types/block.rs rename to rpc/src/types/block.rs index 138140f60..c15c8186d 100644 --- a/src/bin/client/rpc/types/block.rs +++ b/rpc/src/types/block.rs @@ -1,7 +1,7 @@ use util::hash::*; use util::uint::*; -#[derive(Default, Serialize)] +#[derive(Default)] pub struct Block { hash: H256, #[serde(rename="parentHash")] @@ -35,7 +35,7 @@ fn test_block_serialize() { use serde_json; let block = Block::default(); - let serialized = serde_json::to_string(&block).unwrap(); - println!("s: {:?}", serialized); - assert!(false); + //let serialized = serde_json::to_string(&block).unwrap(); + //println!("s: {:?}", serialized); + //assert!(false); } diff --git a/src/bin/client/rpc/types/mod.rs b/rpc/src/types/mod.rs similarity index 100% rename from src/bin/client/rpc/types/mod.rs rename to rpc/src/types/mod.rs From 81bffd48e89be4d4d2745f69f00c006743fdd2ab Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 17:33:22 +0400 Subject: [PATCH 13/54] basic client tests working --- src/block.rs | 2 +- src/block_queue.rs | 2 +- src/tests/client.rs | 92 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/src/block.rs b/src/block.rs index 1ff326430..0e928e9b0 100644 --- a/src/block.rs +++ b/src/block.rs @@ -85,7 +85,7 @@ impl IsBlock for Block { /// /// It's a bit like a Vec, eccept that whenever a transaction is pushed, we execute it and /// maintain the system `state()`. We also archive execution receipts in preparation for later block creation. -pub struct OpenBlock<'x, 'y> { + pub struct OpenBlock<'x, 'y> { block: Block, engine: &'x Engine, last_hashes: &'y LastHashes, diff --git a/src/block_queue.rs b/src/block_queue.rs index fa091d0c4..c45a86a8b 100644 --- a/src/block_queue.rs +++ b/src/block_queue.rs @@ -191,7 +191,7 @@ impl BlockQueue { /// Wait for queue to be empty pub fn flush(&mut self) { let mut verification = self.verification.lock().unwrap(); - while !verification.unverified.is_empty() && !verification.verifying.is_empty() { + while !verification.unverified.is_empty() || !verification.verifying.is_empty() { verification = self.empty.wait(verification).unwrap(); } } diff --git a/src/tests/client.rs b/src/tests/client.rs index c0f202edd..c14f2e2f0 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -1,21 +1,85 @@ -use ethereum; -use client::{BlockChainClient,Client}; + use client::{BlockChainClient,Client}; use std::env; -use pod_state::*; use super::test_common::*; +use std::path::PathBuf; +use spec::*; + +#[cfg(test)] +fn get_random_temp_dir() -> PathBuf { + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + dir +} + +#[cfg(test)] +fn get_test_spec() -> Spec { + Spec::new_test() +} + +#[cfg(test)] +fn get_good_dummy_block() -> Bytes { + let mut block_header = Header::new(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + block_header.timestamp = 40; + block_header.number = 1; + block_header.parent_hash = test_engine.spec().genesis_header().hash(); + block_header.state_root = test_engine.spec().genesis_header().state_root; + + create_test_block(&block_header) +} + +#[cfg(test)] +fn create_test_block(header: &Header) -> Bytes { + let mut rlp = RlpStream::new_list(3); + rlp.append(header); + rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); + rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); + rlp.out() +} #[test] -fn test_client_is_created() { - - let mut spec = ethereum::new_frontier_like_test(); - spec.set_genesis_state(PodState::from_json(test.find("pre").unwrap())); - spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); - - let mut dir = env::temp_dir(); - dir.push(H32::random().hex()); - - let client_result = Client::new(spec, &dir, IOChannel::disconnected()); - +fn created() { + let client_result = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()); assert!(client_result.is_ok()); +} + +#[test] +fn imports_from_empty() { + let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + client.import_verified_blocks(&IoChannel::disconnected()); + client.flush_queue(); +} + +#[test] +fn imports_good_block() { + + ::env_logger::init().ok(); + + let client = Client::new(get_test_spec(), &get_random_temp_dir(), 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"); + } + + client.flush_queue(); + + client.import_verified_blocks(&IoChannel::disconnected()); + + let block = client.block_header_at(1).unwrap(); + + assert!(!block.is_empty()); +} + +#[test] +fn query_none_block() { + let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + + let non_existant = client.block_header_at(188); + + assert!(non_existant == Option::None); } \ No newline at end of file From 8d30f9fecbd91e132ccf368d4b6eb35ed403718f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 17:55:08 +0400 Subject: [PATCH 14/54] bad block import checks --- src/tests/client.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index c14f2e2f0..a9d212bc1 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -31,6 +31,21 @@ fn get_good_dummy_block() -> Bytes { create_test_block(&block_header) } +#[cfg(test)] +fn get_bad_state_dummy_block() -> Bytes { + let mut block_header = Header::new(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + block_header.timestamp = 40; + block_header.number = 1; + block_header.parent_hash = test_engine.spec().genesis_header().hash(); + block_header.state_root = x!(0xbad); + + create_test_block(&block_header) +} + #[cfg(test)] fn create_test_block(header: &Header) -> Bytes { let mut rlp = RlpStream::new_list(3); @@ -40,6 +55,23 @@ fn create_test_block(header: &Header) -> Bytes { rlp.out() } +#[cfg(test)] +fn get_test_client_with_blocks(blocks: Vec) -> Arc { + let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + + for block in &blocks { + if let Err(_) = client.import_block(block.clone()) { + panic!("panic importing block which is well-formed"); + } + } + + client.flush_queue(); + + client.import_verified_blocks(&IoChannel::disconnected()); + + client +} + #[test] fn created() { @@ -81,5 +113,13 @@ fn query_none_block() { let non_existant = client.block_header_at(188); - assert!(non_existant == Option::None); + assert!(non_existant.is_none()); +} + +#[test] +fn query_bad_block() { + let client = get_test_client_with_blocks(vec![get_bad_state_dummy_block()]); + let bad_block:Option = client.block_header_at(1); + + assert!(bad_block.is_none()); } \ No newline at end of file From 253f56afe1f5928f76b1e0efcbe75193f74f0021 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 18:03:12 +0400 Subject: [PATCH 15/54] hack indent --- src/block.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/block.rs b/src/block.rs index 0e928e9b0..31378e8a6 100644 --- a/src/block.rs +++ b/src/block.rs @@ -108,6 +108,7 @@ pub struct SealedBlock { uncle_bytes: Bytes, } + impl<'x, 'y> OpenBlock<'x, 'y> { /// Create a new OpenBlock ready for transaction pushing. pub fn new<'a, 'b>(engine: &'a Engine, db: JournalDB, parent: &Header, last_hashes: &'b LastHashes, author: Address, extra_data: Bytes) -> OpenBlock<'a, 'b> { From b8c2f9cf15c77257384833e29bdeef9ec809dc61 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 21:05:25 +0400 Subject: [PATCH 16/54] chain info test --- src/tests/client.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index a9d212bc1..f6641ff91 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -1,4 +1,4 @@ - use client::{BlockChainClient,Client}; +use client::{BlockChainClient,Client}; use std::env; use super::test_common::*; use std::path::PathBuf; @@ -88,9 +88,6 @@ fn imports_from_empty() { #[test] fn imports_good_block() { - - ::env_logger::init().ok(); - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); let good_block = get_good_dummy_block(); @@ -122,4 +119,13 @@ fn query_bad_block() { let bad_block:Option = client.block_header_at(1); assert!(bad_block.is_none()); +} + +#[test] +fn returns_chain_info() { + let dummy_block = get_good_dummy_block(); + let client = get_test_client_with_blocks(vec![dummy_block.clone()]); + let block = BlockView::new(&dummy_block); + let info = client.chain_info(); + assert_eq!(info.best_block_hash, block.header().hash()); } \ No newline at end of file From cd57e480f51072f6920d2fe0431989ae531c7144 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 21:12:25 +0400 Subject: [PATCH 17/54] fix indentation again --- src/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/block.rs b/src/block.rs index 31378e8a6..5691d2bf5 100644 --- a/src/block.rs +++ b/src/block.rs @@ -85,7 +85,7 @@ impl IsBlock for Block { /// /// It's a bit like a Vec, eccept that whenever a transaction is pushed, we execute it and /// maintain the system `state()`. We also archive execution receipts in preparation for later block creation. - pub struct OpenBlock<'x, 'y> { +pub struct OpenBlock<'x, 'y> { block: Block, engine: &'x Engine, last_hashes: &'y LastHashes, From f07fc497c5b0516137617d0cf40bc446293e032a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 21:14:06 +0400 Subject: [PATCH 18/54] cleanup --- src/block.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/block.rs b/src/block.rs index 5691d2bf5..1ff326430 100644 --- a/src/block.rs +++ b/src/block.rs @@ -108,7 +108,6 @@ pub struct SealedBlock { uncle_bytes: Bytes, } - impl<'x, 'y> OpenBlock<'x, 'y> { /// Create a new OpenBlock ready for transaction pushing. pub fn new<'a, 'b>(engine: &'a Engine, db: JournalDB, parent: &Header, last_hashes: &'b LastHashes, author: Address, extra_data: Bytes) -> OpenBlock<'a, 'b> { From 91828065f45cf1a543218151397f24f4707859d3 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 26 Jan 2016 22:06:11 +0400 Subject: [PATCH 19/54] fixed line spaces --- src/tests/client.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index f6641ff91..eb58699b4 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -58,17 +58,13 @@ fn create_test_block(header: &Header) -> Bytes { #[cfg(test)] fn get_test_client_with_blocks(blocks: Vec) -> Arc { let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); - for block in &blocks { if let Err(_) = client.import_block(block.clone()) { panic!("panic importing block which is well-formed"); } } - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); - client } @@ -89,18 +85,14 @@ fn imports_from_empty() { #[test] fn imports_good_block() { let client = Client::new(get_test_spec(), &get_random_temp_dir(), 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"); } - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); let block = client.block_header_at(1).unwrap(); - assert!(!block.is_empty()); } @@ -109,7 +101,6 @@ fn query_none_block() { let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header_at(188); - assert!(non_existant.is_none()); } From 2f42e0eda0af6207d3d7d59b007af02256d88806 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 26 Jan 2016 19:24:33 +0100 Subject: [PATCH 20/54] parity on netstats --- rpc/Cargo.toml | 1 - rpc/src/impls/eth.rs | 20 ++++++++++++++------ rpc/src/lib.rs | 3 ++- rpc/src/traits/eth.rs | 1 + rpc/src/types/block.rs | 6 +++--- rpc/src/types/mod.rs | 17 +++++++++++++++++ util/Cargo.toml | 1 + util/src/hash.rs | 37 +++++++++++++++++++++++++++++++++++++ util/src/lib.rs | 1 + util/src/uint.rs | 13 +++++++++++++ 10 files changed, 89 insertions(+), 11 deletions(-) diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index d0f9f50e8..ccdd46679 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -8,7 +8,6 @@ authors = ["Marek Kotewicz , @@ -27,7 +28,7 @@ impl Eth for EthClient { fn author(&self, params: Params) -> Result { match params { - Params::None => Ok(Value::String(Address::new().to_hex())), + Params::None => Ok(as_value(&Address::new())), _ => Err(Error::invalid_params()) } } @@ -64,8 +65,15 @@ impl Eth for EthClient { Ok(Value::U64(0)) } - fn block(&self, _: Params) -> Result { - Ok(Value::Null) + fn block(&self, params: Params) -> Result { + if let Params::Array(ref arr) = params { + if let [ref h, Value::Bool(ref include_transactions)] = arr as &[Value] { + if let Ok(hash) = from_value::(h.clone()) { + return Ok(as_value(&Block::default())) + } + } + } + Err(Error::invalid_params()) } } @@ -91,6 +99,6 @@ impl EthFilter for EthFilterClient { } fn filter_changes(&self, _: Params) -> Result { - Ok(Value::Array(vec![Value::String(self.client.chain_info().best_block_hash.to_hex())])) + Ok(Value::Array(vec![as_value(&self.client.chain_info().best_block_hash)])) } } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 148e9f134..43a24a1fb 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -1,8 +1,9 @@ #![feature(custom_derive, custom_attribute, plugin)] +#![feature(slice_patterns)] #![plugin(serde_macros)] -extern crate rustc_serialize; extern crate serde; +extern crate serde_json; extern crate jsonrpc_core; extern crate jsonrpc_http_server; extern crate ethcore_util as util; diff --git a/rpc/src/traits/eth.rs b/rpc/src/traits/eth.rs index 31e9df164..35b59a91c 100644 --- a/rpc/src/traits/eth.rs +++ b/rpc/src/traits/eth.rs @@ -35,6 +35,7 @@ pub trait Eth: Sized + Send + Sync + 'static { delegate.add_method("eth_coinbase", Eth::author); delegate.add_method("eth_gasPrice", Eth::gas_price); delegate.add_method("eth_blockNumber", Eth::block_number); + delegate.add_method("eth_getBlockByHash", Eth::block); delegate.add_method("eth_getBlockByNumber", Eth::block); delegate.add_method("eth_mining", Eth::is_mining); delegate.add_method("eth_hashrate", Eth::hashrate); diff --git a/rpc/src/types/block.rs b/rpc/src/types/block.rs index c15c8186d..7b23e2e0c 100644 --- a/rpc/src/types/block.rs +++ b/rpc/src/types/block.rs @@ -1,7 +1,7 @@ use util::hash::*; use util::uint::*; -#[derive(Default)] +#[derive(Default, Serialize)] pub struct Block { hash: H256, #[serde(rename="parentHash")] @@ -35,7 +35,7 @@ fn test_block_serialize() { use serde_json; let block = Block::default(); - //let serialized = serde_json::to_string(&block).unwrap(); - //println!("s: {:?}", serialized); + let serialized = serde_json::to_string(&block).unwrap(); + println!("s: {:?}", serialized); //assert!(false); } diff --git a/rpc/src/types/mod.rs b/rpc/src/types/mod.rs index fc9210db1..a2f1da63e 100644 --- a/rpc/src/types/mod.rs +++ b/rpc/src/types/mod.rs @@ -1 +1,18 @@ +use serde::{Serialize, Deserialize, de}; +use serde_json::value::{Value, Serializer, Deserializer}; + mod block; + +pub fn as_value(s: &S) -> Value where S: Serialize { + let mut serializer = Serializer::new(); + // should never panic! + s.serialize(&mut serializer).unwrap(); + serializer.unwrap() +} + +pub fn from_value(value: Value) -> Result::Error> where D: Deserialize { + let mut deserialier = Deserializer::new(value); + Deserialize::deserialize(&mut deserialier) +} + +pub use self::block::Block; diff --git a/util/Cargo.toml b/util/Cargo.toml index a91bff962..362db33b2 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -25,6 +25,7 @@ itertools = "0.4" crossbeam = "0.2" slab = { git = "https://github.com/arkpar/slab.git" } sha3 = { path = "sha3" } +serde = "0.6.7" clippy = "*" # Always newest, since we use nightly [dev-dependencies] diff --git a/util/src/hash.rs b/util/src/hash.rs index 0e4139f3c..011746028 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -8,6 +8,8 @@ use rand::os::OsRng; use bytes::{BytesConvertable,Populatable}; use from_json::*; use uint::{Uint, U256}; +use rustc_serialize::hex::ToHex; +use serde; /// Trait for a fixed-size byte array to be used as the output of hash functions. /// @@ -205,6 +207,41 @@ macro_rules! impl_hash { } } + impl serde::Serialize for $from { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer { + let mut hex = "0x".to_owned(); + hex.push_str(self.to_hex().as_ref()); + serializer.visit_str(hex.as_ref()) + } + } + + impl serde::Deserialize for $from { + fn deserialize(deserializer: &mut D) -> Result<$from, D::Error> + where D: serde::Deserializer { + struct HashVisitor; + + impl serde::de::Visitor for HashVisitor { + type Value = $from; + + fn visit_str(&mut self, value: &str) -> Result where E: serde::Error { + // 0x + len + if value.len() != 2 + $size * 2 { + return Err(serde::Error::syntax("Invalid length.")); + } + + value[2..].from_hex().map(|ref v| $from::from_slice(v)).map_err(|_| serde::Error::syntax("Invalid valid hex.")) + } + + fn visit_string(&mut self, value: String) -> Result where E: serde::Error { + self.visit_str(value.as_ref()) + } + } + + deserializer.visit(HashVisitor) + } + } + impl FromJson for $from { fn from_json(json: &Json) -> Self { match *json { diff --git a/util/src/lib.rs b/util/src/lib.rs index 970c0713c..b1b93968c 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -55,6 +55,7 @@ extern crate secp256k1; extern crate arrayvec; extern crate elastic_array; extern crate crossbeam; +extern crate serde; /// TODO [Gav Wood] Please document me pub mod standard; diff --git a/util/src/uint.rs b/util/src/uint.rs index ab136d7c6..de05ca4a8 100644 --- a/util/src/uint.rs +++ b/util/src/uint.rs @@ -23,6 +23,8 @@ use standard::*; use from_json::*; +use rustc_serialize::hex::ToHex; +use serde; macro_rules! impl_map_from { ($thing:ident, $from:ty, $to:ty) => { @@ -436,6 +438,17 @@ macro_rules! construct_uint { } } + impl serde::Serialize for $name { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: serde::Serializer { + let mut hex = "0x".to_owned(); + let mut bytes = [0u8; 8 * $n_words]; + self.to_bytes(&mut bytes); + hex.push_str(bytes.to_hex().as_ref()); + serializer.visit_str(hex.as_ref()) + } + } + impl From for $name { fn from(value: u64) -> $name { let mut ret = [0; $n_words]; From 4e62b5201087eb5c191ddbf1eaf581f12a3d4b96 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 04:24:32 +0400 Subject: [PATCH 21/54] blockchain cache tests --- src/blockchain.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/blockchain.rs b/src/blockchain.rs index 3bd31688a..16e75b08d 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -628,6 +628,25 @@ mod tests { use util::hash::*; use blockchain::*; + fn get_populated_bc() -> BlockChain { + let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a059262c330941f3fe2a34d16d6e3c7b30d2ceb37c6a0e9a994c494ee1a61d2410885aa4c8bf8e56e264c0c0".from_hex().unwrap(); + let b1 = "f90261f901f9a05716670833ec874362d65fea27a7cd35af5897d275b31a44944113111e4e96d2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a0e78628dd45a1f8dc495594d83b76c588a3ee67463260f8b7d4a42f574aeab29aa0e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd882520884562791e580a051b3ecba4e3f2b49c11d42dd0851ec514b1be3138080f72a2b6e83868275d98f8877671f479c414b47f862f86080018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ca09e2709d7ec9bbe6b1bbbf0b2088828d14cd5e8642a1fee22dc74bfa89761a7f9a04bd8813dee4be989accdb708b1c2e325a7e9c695a8024e30e89d6c644e424747c0".from_hex().unwrap(); + let b2 = "f902ccf901f9a0437e51676ff10756fcfee5edd9159fa41dbcb1b2c592850450371cbecd54ee4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap(); + let b3a = "f90261f901f9a036fde1253128666fcb95a5956da14a73489e988bb72738717ec1d31e1cee781aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a09dc4b1357c0b7b8108f8a098f4f9a1a274957bc9ebc22a9ae67ae81739e5b19ca007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefd882524d84562791eb80a074861666bd346c025889745c793b91ab9cd1e2ca19b5cf3c50d04d135b0a4d2b8809fe9587ea4cdc04f862f86002018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d01801ba06fd84874d36d5de9e8e48978c03619b53a96b7ae0a4cd1ac118f103098b44801a00572596974dd7df4f9f69bd7456585618c568d8434ef6453391b89281ce12ae1c0".from_hex().unwrap(); + let b3b = "f90265f901f9a036fde1253128666fcb95a5956da14a73489e988bb72738717ec1d31e1cee781aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ab87dc338bfd6f662b1cd90bc0c9e40a1b2146a095312393c9e13ce3a5008b09a0e609b7a7d4b8a2403ec1268627ecd98783627246e8f1b26addb3ff504f76a054a0592fabf92476512952db3a69a2481a42912e668a1ee28c4c322e703bb665f8beb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefd882a1f084562791ee80a0fe7098fa7e4ac5d637eea81fb23f8f78346826dbab430068dd9a249d0afa99818853e1a6b201ae3545f866f86402018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d0284c04062261ca06edc9ce8e7da4cc34067beb325dcad59e5655a164a5100a50bc3eb681b12c716a0abf9053d5de65b1be81fe50d327b84de685efbeecea34e7b747180a6c6023e44c0".from_hex().unwrap(); + + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + + let bc = BlockChain::new(&genesis, &dir); + bc.insert_block(&b1); + bc.insert_block(&b2); + bc.insert_block(&b3a); + bc.insert_block(&b3b); + + bc + } + #[test] fn valid_tests_extra32() { let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a0363659b251bf8b819179874c8cce7b9b983d7f3704cbb58a3b334431f7032871889032d09c281e1236c0c0".from_hex().unwrap(); @@ -773,4 +792,11 @@ mod tests { assert_eq!(bc.best_block_hash(), b1_hash); } } + + #[test] + fn blocks_get_garbage_collected() { + let bc = get_populated_bc(); + bc.squeeze_to_fit(CacheSize { blocks: 0, block_logs: 0, transaction_addresses: 0, block_details: 0, blocks_blooms: 0 } ); + assert_eq!(bc.cache_size().blocks, 0); + } } From 8d8782056a3e5d4166f55c1f007767ca26e9f1b5 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 13:22:51 +0400 Subject: [PATCH 22/54] failing test for sqeeze to fit code --- src/blockchain.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/blockchain.rs b/src/blockchain.rs index dcc348440..3f55f3ea1 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -803,5 +803,8 @@ mod tests { let bc = get_populated_bc(); bc.squeeze_to_fit(CacheSize { blocks: 0, block_logs: 0, transaction_addresses: 0, block_details: 0, blocks_blooms: 0 } ); assert_eq!(bc.cache_size().blocks, 0); + assert_eq!(bc.cache_size().block_details, 0); + assert_eq!(bc.cache_size().block_logs, 0); + assert_eq!(bc.cache_size().blocks_blooms, 0); } } From b4263c1755a63d55f2cd60e3484458728f778f02 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 13:38:47 +0400 Subject: [PATCH 23/54] squeeze/garbage --- src/blockchain.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/blockchain.rs b/src/blockchain.rs index 3f55f3ea1..40abb1c8d 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -799,12 +799,20 @@ mod tests { } #[test] - fn blocks_get_garbage_collected() { + fn can_be_squeezed() { let bc = get_populated_bc(); bc.squeeze_to_fit(CacheSize { blocks: 0, block_logs: 0, transaction_addresses: 0, block_details: 0, blocks_blooms: 0 } ); - assert_eq!(bc.cache_size().blocks, 0); - assert_eq!(bc.cache_size().block_details, 0); + assert_eq!(bc.cache_size().blocks, 1624); + assert_eq!(bc.cache_size().block_details, 3712); assert_eq!(bc.cache_size().block_logs, 0); assert_eq!(bc.cache_size().blocks_blooms, 0); } + + #[test] + fn can_collect_garbage() { + let bc = get_populated_bc(); + bc.collect_garbage(false); + assert_eq!(bc.cache_size().blocks, 1624); + + } } From d2229f519ddfd8ec0cfdcd69b6f2fe9f73647dc5 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 14:50:39 +0400 Subject: [PATCH 24/54] test helpers initial --- src/tests/helpers.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/tests/helpers.rs diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs new file mode 100644 index 000000000..e69de29bb From dddbf589451a61daeecd122d4e83e6ae3b9e3165 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 14:50:48 +0400 Subject: [PATCH 25/54] test helpers initial --- src/tests/client.rs | 23 +++++-------------- src/tests/helpers.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index eb58699b4..57ab6e577 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -3,18 +3,7 @@ use std::env; use super::test_common::*; use std::path::PathBuf; use spec::*; - -#[cfg(test)] -fn get_random_temp_dir() -> PathBuf { - let mut dir = env::temp_dir(); - dir.push(H32::random().hex()); - dir -} - -#[cfg(test)] -fn get_test_spec() -> Spec { - Spec::new_test() -} +use super::helpers::*; #[cfg(test)] fn get_good_dummy_block() -> Bytes { @@ -57,7 +46,7 @@ fn create_test_block(header: &Header) -> Bytes { #[cfg(test)] fn get_test_client_with_blocks(blocks: Vec) -> Arc { - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); for block in &blocks { if let Err(_) = client.import_block(block.clone()) { panic!("panic importing block which is well-formed"); @@ -71,20 +60,20 @@ fn get_test_client_with_blocks(blocks: Vec) -> Arc { #[test] fn created() { - let client_result = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()); + let client_result = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()); assert!(client_result.is_ok()); } #[test] fn imports_from_empty() { - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); client.import_verified_blocks(&IoChannel::disconnected()); client.flush_queue(); } #[test] fn imports_good_block() { - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + let client = Client::new(get_test_spec(), &get_random_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"); @@ -98,7 +87,7 @@ fn imports_good_block() { #[test] fn query_none_block() { - let client = Client::new(get_test_spec(), &get_random_temp_dir(), IoChannel::disconnected()).unwrap(); + let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header_at(188); assert!(non_existant.is_none()); diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index e69de29bb..4cbd36692 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -0,0 +1,54 @@ +use client::{BlockChainClient,Client}; +use std::env; +use super::test_common::*; +use std::path::PathBuf; +use spec::*; +use std::fs::{create_dir_all}; + +#[cfg(test)] +const FIXED_TEMP_DIR_NAME: &'static str = "parity-temp"; + + +#[cfg(test)] +pub fn get_tests_temp_dir() -> PathBuf { + let mut dir = env::temp_dir(); + dir.push(FIXED_TEMP_DIR_NAME); + if let Err(_) = create_dir_all(&dir) { + panic!("failed to create test dir!"); + } + dir +} + +#[cfg(test)] +pub fn get_random_path() -> PathBuf { + let mut dir = get_tests_temp_dir(); + dir.push(H32::random().hex()); + dir +} + + +#[cfg(test)] +pub fn get_test_spec() -> Spec { + Spec::new_test() +} + +#[cfg(test)] +pub fn generate_dummy_client(block_number: usize) { + let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); + + let mut rolling_hash = test_engine.spec().genesis_header().hash(); + let mut rolling_state = test_engine.spec().genesis_header().state_root; + let mut rolling_block_number = 1; + + for _ in 0..block_number { + let mut header = Header::new(); + + header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); + header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); + header.timestamp = 40; + header.number = rolling_block_number; + header.parent_hash = test_engine.spec().genesis_header().hash(); + header.state_root = test_engine.spec().genesis_header().state_root; + } + +} \ No newline at end of file diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 290c2e293..17da72d77 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -6,3 +6,4 @@ mod executive; mod state; mod client; mod chain; +mod helpers; \ No newline at end of file From 58651392065f67071991cbb587cf71aa48ca8516 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 12:31:54 +0100 Subject: [PATCH 26/54] block visible on netstats --- rpc/src/impls/eth.rs | 39 +++++++++++++++++++++++++++++++++------ rpc/src/impls/web3.rs | 3 ++- rpc/src/types/block.rs | 33 +++++++++++++++++++-------------- rpc/src/types/mod.rs | 2 +- src/client.rs | 8 ++++++++ src/externalities.rs | 31 ++++++++++--------------------- 6 files changed, 73 insertions(+), 43 deletions(-) diff --git a/rpc/src/impls/eth.rs b/rpc/src/impls/eth.rs index 54372ab3a..f0ad73c57 100644 --- a/rpc/src/impls/eth.rs +++ b/rpc/src/impls/eth.rs @@ -1,10 +1,12 @@ use std::sync::Arc; -use serde_json; use jsonrpc_core::*; use util::hash::*; +use util::uint::*; +use util::sha3::*; use ethcore::client::*; +use ethcore::views::*; use traits::{Eth, EthFilter}; -use types::{Block, as_value, from_value}; +use types::{Block, to_value, from_value}; pub struct EthClient { client: Arc, @@ -28,7 +30,7 @@ impl Eth for EthClient { fn author(&self, params: Params) -> Result { match params { - Params::None => Ok(as_value(&Address::new())), + Params::None => Ok(to_value(&Address::new())), _ => Err(Error::invalid_params()) } } @@ -67,9 +69,34 @@ impl Eth for EthClient { fn block(&self, params: Params) -> Result { if let Params::Array(ref arr) = params { - if let [ref h, Value::Bool(ref include_transactions)] = arr as &[Value] { + if let [ref h, Value::Bool(ref _include_txs)] = arr as &[Value] { if let Ok(hash) = from_value::(h.clone()) { - return Ok(as_value(&Block::default())) + return match (self.client.block_header(&hash), self.client.block_details(&hash)) { + (Some(bytes), Some(details)) => { + let view = HeaderView::new(&bytes); + let block = Block { + hash: view.sha3(), + parent_hash: view.parent_hash(), + uncles_hash: view.uncles_hash(), + author: view.author(), + miner: view.author(), + state_root: view.state_root(), + transactions_root: view.transactions_root(), + receipts_root: view.receipts_root(), + number: U256::from(view.number()), + gas_used: view.gas_used(), + gas_limit: view.gas_limit(), + logs_bloom: view.log_bloom(), + timestamp: U256::from(view.timestamp()), + difficulty: view.difficulty(), + total_difficulty: details.total_difficulty, + uncles: vec![], + transactions: vec![] + }; + Ok(to_value(&block)) + }, + _ => Ok(Value::Null), + } } } } @@ -99,6 +126,6 @@ impl EthFilter for EthFilterClient { } fn filter_changes(&self, _: Params) -> Result { - Ok(Value::Array(vec![as_value(&self.client.chain_info().best_block_hash)])) + Ok(Value::Array(vec![to_value(&self.client.chain_info().best_block_hash)])) } } diff --git a/rpc/src/impls/web3.rs b/rpc/src/impls/web3.rs index 58e7858eb..50eb9c6f5 100644 --- a/rpc/src/impls/web3.rs +++ b/rpc/src/impls/web3.rs @@ -10,7 +10,8 @@ impl Web3Client { impl Web3 for Web3Client { fn client_version(&self, params: Params) -> Result { match params { - Params::None => Ok(Value::String("parity/0.1.0/-/rust1.7-nightly".to_string())), + //Params::None => Ok(Value::String("parity/0.1.0/-/rust1.7-nightly".to_owned())), + Params::None => Ok(Value::String("surprise/0.1.0/surprise/surprise".to_owned())), _ => Err(Error::invalid_params()) } } diff --git a/rpc/src/types/block.rs b/rpc/src/types/block.rs index 7b23e2e0c..ac1e673a5 100644 --- a/rpc/src/types/block.rs +++ b/rpc/src/types/block.rs @@ -1,33 +1,38 @@ use util::hash::*; use util::uint::*; -#[derive(Default, Serialize)] +#[derive(Default, Debug, Serialize)] pub struct Block { - hash: H256, + pub hash: H256, #[serde(rename="parentHash")] - parent_hash: H256, + pub parent_hash: H256, #[serde(rename="sha3Uncles")] - uncles_hash: H256, - author: Address, + pub uncles_hash: H256, + pub author: Address, // TODO: get rid of this one - miner: Address, + pub miner: Address, #[serde(rename="stateRoot")] - state_root: H256, + pub state_root: H256, #[serde(rename="transactionsRoot")] - transactions_root: H256, + pub transactions_root: H256, #[serde(rename="receiptsRoot")] - receipts_root: H256, - number: u64, + pub receipts_root: H256, + pub number: U256, #[serde(rename="gasUsed")] - gas_used: U256, + pub gas_used: U256, #[serde(rename="gasLimit")] - gas_limit: U256, + pub gas_limit: U256, // TODO: figure out how to properly serialize bytes //#[serde(rename="extraData")] //extra_data: Vec, #[serde(rename="logsBloom")] - logs_bloom: H2048, - timestamp: u64 + pub logs_bloom: H2048, + pub timestamp: U256, + pub difficulty: U256, + #[serde(rename="totalDifficulty")] + pub total_difficulty: U256, + pub uncles: Vec, + pub transactions: Vec } #[test] diff --git a/rpc/src/types/mod.rs b/rpc/src/types/mod.rs index a2f1da63e..0b7d97916 100644 --- a/rpc/src/types/mod.rs +++ b/rpc/src/types/mod.rs @@ -3,7 +3,7 @@ use serde_json::value::{Value, Serializer, Deserializer}; mod block; -pub fn as_value(s: &S) -> Value where S: Serialize { +pub fn to_value(s: &S) -> Value where S: Serialize { let mut serializer = Serializer::new(); // should never panic! s.serialize(&mut serializer).unwrap(); diff --git a/src/client.rs b/src/client.rs index 2e9029709..e8d8fc8f2 100644 --- a/src/client.rs +++ b/src/client.rs @@ -11,6 +11,7 @@ use service::NetSyncMessage; use env_info::LastHashes; use verification::*; use block::*; +use extras::BlockDetails; /// General block status #[derive(Debug)] @@ -64,6 +65,9 @@ pub trait BlockChainClient : Sync + Send { /// Get block status by block header hash. fn block_status(&self, hash: &H256) -> BlockStatus; + /// Get familial details concerning a block. + fn block_details(&self, hash: &H256) -> Option; + /// Get raw block header data by block number. fn block_header_at(&self, n: BlockNumber) -> Option; @@ -299,6 +303,10 @@ impl BlockChainClient for Client { fn block_status(&self, hash: &H256) -> BlockStatus { if self.chain.read().unwrap().is_known(&hash) { BlockStatus::InChain } else { BlockStatus::Unknown } } + + fn block_details(&self, hash: &H256) -> Option { + self.chain.read().unwrap().block_details(hash) + } fn block_header_at(&self, n: BlockNumber) -> Option { self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_header(&h)) diff --git a/src/externalities.rs b/src/externalities.rs index f9a79c3c0..8b16cc72b 100644 --- a/src/externalities.rs +++ b/src/externalities.rs @@ -19,8 +19,7 @@ pub enum OutputPolicy<'a> { pub struct OriginInfo { address: Address, origin: Address, - gas_price: U256, - value: U256 + gas_price: U256 } impl OriginInfo { @@ -29,11 +28,7 @@ impl OriginInfo { OriginInfo { address: params.address.clone(), origin: params.origin.clone(), - gas_price: params.gas_price.clone(), - value: match params.value { - ActionValue::Transfer(val) => val, - ActionValue::Apparent(val) => val, - } + gas_price: params.gas_price.clone() } } } @@ -116,7 +111,7 @@ impl<'a> Ext for Externalities<'a> { origin: self.origin_info.origin.clone(), gas: *gas, gas_price: self.origin_info.gas_price.clone(), - value: ActionValue::Transfer(value.clone()), + value: value.clone(), code: Some(code.to_vec()), data: None, }; @@ -136,29 +131,24 @@ impl<'a> Ext for Externalities<'a> { fn call(&mut self, gas: &U256, - sender_address: &Address, - receive_address: &Address, - value: Option, + address: &Address, + value: &U256, data: &[u8], code_address: &Address, output: &mut [u8]) -> MessageCallResult { - let mut params = ActionParams { - sender: sender_address.clone(), - address: receive_address.clone(), - value: ActionValue::Apparent(self.origin_info.value.clone()), + let params = ActionParams { code_address: code_address.clone(), + address: address.clone(), + sender: self.origin_info.address.clone(), origin: self.origin_info.origin.clone(), gas: *gas, gas_price: self.origin_info.gas_price.clone(), + value: value.clone(), code: self.state.code(code_address), data: Some(data.to_vec()), }; - if let Some(value) = value { - params.value = ActionValue::Transfer(value); - } - let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth); match ex.call(params, self.substate, BytesRef::Fixed(output)) { @@ -168,10 +158,9 @@ impl<'a> Ext for Externalities<'a> { } fn extcode(&self, address: &Address) -> Bytes { - self.state.code(address).unwrap_or_else(|| vec![]) + self.state.code(address).unwrap_or(vec![]) } - #[allow(match_ref_pats)] fn ret(&mut self, gas: &U256, data: &[u8]) -> Result { match &mut self.output { &mut OutputPolicy::Return(BytesRef::Fixed(ref mut slice)) => unsafe { From 5998c16b17ecc454d4871e8ef0ec9e7010315c90 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 13:08:56 +0100 Subject: [PATCH 27/54] reverted incorrect changes to externalities --- src/externalities.rs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/externalities.rs b/src/externalities.rs index e3a363fbc..f9a79c3c0 100644 --- a/src/externalities.rs +++ b/src/externalities.rs @@ -19,7 +19,8 @@ pub enum OutputPolicy<'a> { pub struct OriginInfo { address: Address, origin: Address, - gas_price: U256 + gas_price: U256, + value: U256 } impl OriginInfo { @@ -28,7 +29,11 @@ impl OriginInfo { OriginInfo { address: params.address.clone(), origin: params.origin.clone(), - gas_price: params.gas_price.clone() + gas_price: params.gas_price.clone(), + value: match params.value { + ActionValue::Transfer(val) => val, + ActionValue::Apparent(val) => val, + } } } } @@ -111,7 +116,7 @@ impl<'a> Ext for Externalities<'a> { origin: self.origin_info.origin.clone(), gas: *gas, gas_price: self.origin_info.gas_price.clone(), - value: value.clone(), + value: ActionValue::Transfer(value.clone()), code: Some(code.to_vec()), data: None, }; @@ -131,24 +136,29 @@ impl<'a> Ext for Externalities<'a> { fn call(&mut self, gas: &U256, - address: &Address, - value: &U256, + sender_address: &Address, + receive_address: &Address, + value: Option, data: &[u8], code_address: &Address, output: &mut [u8]) -> MessageCallResult { - let params = ActionParams { + let mut params = ActionParams { + sender: sender_address.clone(), + address: receive_address.clone(), + value: ActionValue::Apparent(self.origin_info.value.clone()), code_address: code_address.clone(), - address: address.clone(), - sender: self.origin_info.address.clone(), origin: self.origin_info.origin.clone(), gas: *gas, gas_price: self.origin_info.gas_price.clone(), - value: value.clone(), code: self.state.code(code_address), data: Some(data.to_vec()), }; + if let Some(value) = value { + params.value = ActionValue::Transfer(value); + } + let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth); match ex.call(params, self.substate, BytesRef::Fixed(output)) { @@ -158,9 +168,10 @@ impl<'a> Ext for Externalities<'a> { } fn extcode(&self, address: &Address) -> Bytes { - self.state.code(address).unwrap_or(vec![]) + self.state.code(address).unwrap_or_else(|| vec![]) } + #[allow(match_ref_pats)] fn ret(&mut self, gas: &U256, data: &[u8]) -> Result { match &mut self.output { &mut OutputPolicy::Return(BytesRef::Fixed(ref mut slice)) => unsafe { @@ -204,7 +215,6 @@ impl<'a> Ext for Externalities<'a> { fn suicide(&mut self, refund_address: &Address) { let address = self.origin_info.address.clone(); let balance = self.balance(&address); - trace!("Suiciding {} -> {} (xfer: {})", address, refund_address, balance); self.state.transfer_balance(&address, refund_address, &balance); self.substate.suicides.insert(address); } From 996db7cd29db5d641faaf979cd57ce846c0e3273 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 13:11:09 +0100 Subject: [PATCH 28/54] uncommented client tick --- src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index 904a4e02d..50c4e3f81 100644 --- a/src/client.rs +++ b/src/client.rs @@ -294,7 +294,7 @@ impl Client { /// Tick the client. pub fn tick(&self) { - //self.chain.read().unwrap().collect_garbage(false); + self.chain.read().unwrap().collect_garbage(false); } } From 38164d6b21323b78f49ddfb1201fe5084a1bda41 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 16:23:24 +0400 Subject: [PATCH 29/54] extra tests --- src/blockchain.rs | 36 ------------------------------------ src/client.rs | 12 ++++++++++++ src/tests/client.rs | 37 ++++++++++++++++++++++++++----------- src/tests/helpers.rs | 37 ++++++++++++++++++++++++++++++++----- 4 files changed, 70 insertions(+), 52 deletions(-) diff --git a/src/blockchain.rs b/src/blockchain.rs index 40abb1c8d..a0b554bcc 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -633,25 +633,6 @@ mod tests { use util::hash::*; use blockchain::*; - fn get_populated_bc() -> BlockChain { - let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a059262c330941f3fe2a34d16d6e3c7b30d2ceb37c6a0e9a994c494ee1a61d2410885aa4c8bf8e56e264c0c0".from_hex().unwrap(); - let b1 = "f90261f901f9a05716670833ec874362d65fea27a7cd35af5897d275b31a44944113111e4e96d2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a0e78628dd45a1f8dc495594d83b76c588a3ee67463260f8b7d4a42f574aeab29aa0e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd882520884562791e580a051b3ecba4e3f2b49c11d42dd0851ec514b1be3138080f72a2b6e83868275d98f8877671f479c414b47f862f86080018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ca09e2709d7ec9bbe6b1bbbf0b2088828d14cd5e8642a1fee22dc74bfa89761a7f9a04bd8813dee4be989accdb708b1c2e325a7e9c695a8024e30e89d6c644e424747c0".from_hex().unwrap(); - let b2 = "f902ccf901f9a0437e51676ff10756fcfee5edd9159fa41dbcb1b2c592850450371cbecd54ee4fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap(); - let b3a = "f90261f901f9a036fde1253128666fcb95a5956da14a73489e988bb72738717ec1d31e1cee781aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a09dc4b1357c0b7b8108f8a098f4f9a1a274957bc9ebc22a9ae67ae81739e5b19ca007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefd882524d84562791eb80a074861666bd346c025889745c793b91ab9cd1e2ca19b5cf3c50d04d135b0a4d2b8809fe9587ea4cdc04f862f86002018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d01801ba06fd84874d36d5de9e8e48978c03619b53a96b7ae0a4cd1ac118f103098b44801a00572596974dd7df4f9f69bd7456585618c568d8434ef6453391b89281ce12ae1c0".from_hex().unwrap(); - let b3b = "f90265f901f9a036fde1253128666fcb95a5956da14a73489e988bb72738717ec1d31e1cee781aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ab87dc338bfd6f662b1cd90bc0c9e40a1b2146a095312393c9e13ce3a5008b09a0e609b7a7d4b8a2403ec1268627ecd98783627246e8f1b26addb3ff504f76a054a0592fabf92476512952db3a69a2481a42912e668a1ee28c4c322e703bb665f8beb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefd882a1f084562791ee80a0fe7098fa7e4ac5d637eea81fb23f8f78346826dbab430068dd9a249d0afa99818853e1a6b201ae3545f866f86402018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d0284c04062261ca06edc9ce8e7da4cc34067beb325dcad59e5655a164a5100a50bc3eb681b12c716a0abf9053d5de65b1be81fe50d327b84de685efbeecea34e7b747180a6c6023e44c0".from_hex().unwrap(); - - let mut dir = env::temp_dir(); - dir.push(H32::random().hex()); - - let bc = BlockChain::new(&genesis, &dir); - bc.insert_block(&b1); - bc.insert_block(&b2); - bc.insert_block(&b3a); - bc.insert_block(&b3b); - - bc - } - #[test] fn valid_tests_extra32() { let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a0363659b251bf8b819179874c8cce7b9b983d7f3704cbb58a3b334431f7032871889032d09c281e1236c0c0".from_hex().unwrap(); @@ -798,21 +779,4 @@ mod tests { } } - #[test] - fn can_be_squeezed() { - let bc = get_populated_bc(); - bc.squeeze_to_fit(CacheSize { blocks: 0, block_logs: 0, transaction_addresses: 0, block_details: 0, blocks_blooms: 0 } ); - assert_eq!(bc.cache_size().blocks, 1624); - assert_eq!(bc.cache_size().block_details, 3712); - assert_eq!(bc.cache_size().block_logs, 0); - assert_eq!(bc.cache_size().blocks_blooms, 0); - } - - #[test] - fn can_collect_garbage() { - let bc = get_populated_bc(); - bc.collect_garbage(false); - assert_eq!(bc.cache_size().blocks, 1624); - - } } diff --git a/src/client.rs b/src/client.rs index a83ff554e..28b5ada88 100644 --- a/src/client.rs +++ b/src/client.rs @@ -292,6 +292,18 @@ impl Client { pub fn tick(&self) { self.chain.read().unwrap().collect_garbage(false); } + + /// Minimizes cache used by the client. + pub fn minimize_cache(&self) { + self.chain.read().unwrap().squeeze_to_fit( + CacheSize { + blocks: 0, + block_logs: 0, + transaction_addresses: 0, + block_details: 0, + blocks_blooms: 0 + }); + } } impl BlockChainClient for Client { diff --git a/src/tests/client.rs b/src/tests/client.rs index 57ab6e577..2b8a97551 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -1,8 +1,5 @@ use client::{BlockChainClient,Client}; -use std::env; use super::test_common::*; -use std::path::PathBuf; -use spec::*; use super::helpers::*; #[cfg(test)] @@ -35,14 +32,6 @@ fn get_bad_state_dummy_block() -> Bytes { create_test_block(&block_header) } -#[cfg(test)] -fn create_test_block(header: &Header) -> Bytes { - let mut rlp = RlpStream::new_list(3); - rlp.append(header); - rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); - rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); - rlp.out() -} #[cfg(test)] fn get_test_client_with_blocks(blocks: Vec) -> Arc { @@ -108,4 +97,30 @@ fn returns_chain_info() { let block = BlockView::new(&dummy_block); let info = client.chain_info(); assert_eq!(info.best_block_hash, block.header().hash()); +} + +#[test] +fn imports_block_sequence() { + let client = generate_dummy_client(6); + let block = client.block_header_at(5).unwrap(); + + assert!(!block.is_empty()); +} + + +#[test] +fn can_have_cash_minimized() { + let client = generate_dummy_client(20); + client.minimize_cache(); + assert!(client.cache_info().blocks < 2048); + assert!(client.cache_info().block_details < 4096); + assert_eq!(client.cache_info().block_logs, 0); + assert_eq!(client.cache_info().blocks_blooms, 0); +} + +#[test] +fn can_collect_garbage() { + let client = generate_dummy_client(100); + client.tick(); + assert!(client.cache_info().blocks < 100 * 1024); } \ No newline at end of file diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 4cbd36692..7f9b8ba42 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -32,23 +32,50 @@ pub fn get_test_spec() -> Spec { Spec::new_test() } + #[cfg(test)] -pub fn generate_dummy_client(block_number: usize) { +pub fn create_test_block(header: &Header) -> Bytes { + let mut rlp = RlpStream::new_list(3); + rlp.append(header); + rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); + rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); + rlp.out() +} + +#[cfg(test)] +pub fn generate_dummy_client(block_number: usize) -> Arc { let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); + let test_spec = get_test_spec(); + let test_engine = test_spec.to_engine().unwrap(); + let state_root = test_engine.spec().genesis_header().state_root; let mut rolling_hash = test_engine.spec().genesis_header().hash(); - let mut rolling_state = test_engine.spec().genesis_header().state_root; let mut rolling_block_number = 1; + let mut rolling_timestamp = 40; for _ in 0..block_number { let mut header = Header::new(); header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap()); header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap()); - header.timestamp = 40; + header.timestamp = rolling_timestamp; header.number = rolling_block_number; - header.parent_hash = test_engine.spec().genesis_header().hash(); - header.state_root = test_engine.spec().genesis_header().state_root; + header.parent_hash = rolling_hash; + header.state_root = state_root.clone(); + + rolling_hash = header.hash(); + rolling_block_number = rolling_block_number + 1; + rolling_timestamp = rolling_timestamp + 10; + + if let Err(_) = client.import_block(create_test_block(&header)) { + panic!("error importing block which is valid by definition"); + } + } + client.flush_queue(); + client.import_verified_blocks(&IoChannel::disconnected()); + + client + } \ No newline at end of file From fe0363e230440341d7540444dd295bdbef2b7e16 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 13:28:15 +0100 Subject: [PATCH 30/54] Fix import for bcMultiChainTest. Fixes #223 --- src/block_queue.rs | 14 ++++++++------ src/client.rs | 15 +++++++++------ src/error.rs | 2 +- src/sync/chain.rs | 4 ++-- src/sync/tests.rs | 11 ++++++----- src/tests/chain.rs | 20 +++++++++++++------- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/block_queue.rs b/src/block_queue.rs index e0868c011..dab3a5fe3 100644 --- a/src/block_queue.rs +++ b/src/block_queue.rs @@ -200,34 +200,36 @@ impl BlockQueue { /// Add a block to the queue. pub fn import_block(&mut self, bytes: Bytes) -> ImportResult { let header = BlockView::new(&bytes).header(); - if self.processing.contains(&header.hash()) { + let h = header.hash(); + if self.processing.contains(&h) { return Err(ImportError::AlreadyQueued); } { let mut verification = self.verification.lock().unwrap(); - if verification.bad.contains(&header.hash()) { + if verification.bad.contains(&h) { return Err(ImportError::Bad(None)); } if verification.bad.contains(&header.parent_hash) { - verification.bad.insert(header.hash()); + verification.bad.insert(h.clone()); return Err(ImportError::Bad(None)); } } match verify_block_basic(&header, &bytes, self.engine.deref().deref()) { Ok(()) => { - self.processing.insert(header.hash()); + self.processing.insert(h.clone()); self.verification.lock().unwrap().unverified.push_back(UnVerifiedBlock { header: header, bytes: bytes }); self.more_to_verify.notify_all(); + Ok(h) }, Err(err) => { flushln!("Stage 1 block verification failed for {}\nError: {:?}", BlockView::new(&bytes).header_view().sha3(), err); warn!(target: "client", "Stage 1 block verification failed for {}\nError: {:?}", BlockView::new(&bytes).header_view().sha3(), err); - self.verification.lock().unwrap().bad.insert(header.hash()); + self.verification.lock().unwrap().bad.insert(h.clone()); + Err(From::from(err)) } } - Ok(()) } /// Mark given block and all its children as bad. Stops verification. diff --git a/src/client.rs b/src/client.rs index a83ff554e..8aea437e4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -193,7 +193,8 @@ impl Client { } /// This is triggered by a message coming from a block queue when the block is ready for insertion - pub fn import_verified_blocks(&self, _io: &IoChannel) { + pub fn import_verified_blocks(&self, _io: &IoChannel) -> usize { + let mut ret = 0; let mut bad = HashSet::new(); let _import_lock = self.import_lock.lock(); let blocks = self.block_queue.write().unwrap().drain(128); @@ -211,7 +212,7 @@ impl Client { warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); bad.insert(block.header.hash()); - return; + break; }; let parent = match self.chain.read().unwrap().block_header(&header.parent_hash) { Some(p) => p, @@ -220,7 +221,7 @@ impl Client { warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); bad.insert(block.header.hash()); - return; + break; }, }; // build last hashes @@ -244,14 +245,14 @@ impl Client { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); bad.insert(block.header.hash()); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); - return; + break; } }; if let Err(e) = verify_block_final(&header, result.block().header()) { flushln!("Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); - return; + break; } self.chain.write().unwrap().insert_block(&block.bytes); //TODO: err here? @@ -260,12 +261,14 @@ impl Client { Ok(_) => (), Err(e) => { warn!(target: "client", "State DB commit failed: {:?}", e); - return; + break; } } self.report.write().unwrap().accrue_block(&block); trace!(target: "client", "Imported #{} ({})", header.number(), header.hash()); + ret += 1; } + ret } /// Clear cached state overlay diff --git a/src/error.rs b/src/error.rs index bc2bdfe97..cdc0c2d25 100644 --- a/src/error.rs +++ b/src/error.rs @@ -145,7 +145,7 @@ impl From for ImportError { } /// Result of import block operation. -pub type ImportResult = Result<(), ImportError>; +pub type ImportResult = Result; #[derive(Debug)] /// General error type which should be capable of representing all errors in ethcore. diff --git a/src/sync/chain.rs b/src/sync/chain.rs index aaba701c2..1f79477af 100644 --- a/src/sync/chain.rs +++ b/src/sync/chain.rs @@ -415,7 +415,7 @@ impl ChainSync { Err(ImportError::AlreadyQueued) => { trace!(target: "sync", "New block already queued {:?}", h); }, - Ok(()) => { + Ok(_) => { trace!(target: "sync", "New block queued {:?}", h); }, Err(e) => { @@ -680,7 +680,7 @@ impl ChainSync { self.last_imported_block = headers.0 + i as BlockNumber; self.last_imported_hash = h.clone(); }, - Ok(()) => { + Ok(_) => { trace!(target: "sync", "Block queued {:?}", h); self.last_imported_block = headers.0 + i as BlockNumber; self.last_imported_hash = h.clone(); diff --git a/src/sync/tests.rs b/src/sync/tests.rs index 50d6efab2..cc0645b50 100644 --- a/src/sync/tests.rs +++ b/src/sync/tests.rs @@ -114,6 +114,7 @@ impl BlockChainClient for TestBlockChainClient { fn import_block(&self, b: Bytes) -> ImportResult { let header = Rlp::new(&b).val_at::(0); + let h = header.hash(); let number: usize = header.number as usize; if number > self.blocks.read().unwrap().len() { panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().unwrap().len(), number); @@ -134,9 +135,9 @@ impl BlockChainClient for TestBlockChainClient { let len = self.numbers.read().unwrap().len(); if number == len { *self.difficulty.write().unwrap().deref_mut() += header.difficulty; - mem::replace(self.last_hash.write().unwrap().deref_mut(), header.hash()); - self.blocks.write().unwrap().insert(header.hash(), b); - self.numbers.write().unwrap().insert(number, header.hash()); + mem::replace(self.last_hash.write().unwrap().deref_mut(), h.clone()); + self.blocks.write().unwrap().insert(h.clone(), b); + self.numbers.write().unwrap().insert(number, h.clone()); let mut parent_hash = header.parent_hash; if number > 0 { let mut n = number - 1; @@ -148,9 +149,9 @@ impl BlockChainClient for TestBlockChainClient { } } else { - self.blocks.write().unwrap().insert(header.hash(), b.to_vec()); + self.blocks.write().unwrap().insert(h.clone(), b.to_vec()); } - Ok(()) + Ok(h) } fn queue_info(&self) -> BlockQueueInfo { diff --git a/src/tests/chain.rs b/src/tests/chain.rs index ec899c73b..8ba5e3671 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -21,7 +21,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { flush(format!(" - {}...", name)); - let blocks: Vec = test["blocks"].as_array().unwrap().iter().map(|e| xjson!(&e["rlp"])).collect(); + let blocks: Vec<(Bytes, bool)> = test["blocks"].as_array().unwrap().iter().map(|e| (xjson!(&e["rlp"]), e.find("blockHeader").is_some())).collect(); let mut spec = ethereum::new_frontier_like_test(); let s = PodState::from_json(test.find("pre").unwrap()); spec.set_genesis_state(s); @@ -32,11 +32,17 @@ fn do_json_test(json_data: &[u8]) -> Vec { dir.push(H32::random().hex()); { let client = Client::new(spec, &dir, IoChannel::disconnected()).unwrap(); - for b in blocks.into_iter().filter(|ref b| Block::is_good(b)) { - client.import_block(b).unwrap(); + for (b, is_valid) in blocks.into_iter() { + let mut hash = H256::new(); + if Block::is_good(&b) { + if let Ok(h) = client.import_block(b.clone()) { + hash = h; + } + } + client.flush_queue(); + let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; + assert_eq!(imported_ok, is_valid); // may yet be invalid for the later stages, so can't do a hard check. } - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); } fs::remove_dir_all(&dir).unwrap(); @@ -55,8 +61,8 @@ declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTes declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} // STILL FAILS declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"} declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} -declare_test!{BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} // FAILS -declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} // FAILS +declare_test!{BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} +declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"} declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} From f6d7adf693973bbf92b6d0c7192728e6d31a21af Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 13:29:52 +0100 Subject: [PATCH 31/54] Remove misleading comment. --- src/tests/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 8ba5e3671..894303a4c 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -41,7 +41,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { } client.flush_queue(); let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; - assert_eq!(imported_ok, is_valid); // may yet be invalid for the later stages, so can't do a hard check. + assert_eq!(imported_ok, is_valid); } fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); } From 1897d55a791e7ea77e6840d4eb6437bf6a8cc99f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 16:41:41 +0400 Subject: [PATCH 32/54] removed unused cfg options --- src/tests/client.rs | 3 --- src/tests/helpers.rs | 7 +------ 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index 2b8a97551..92bf31c89 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -2,7 +2,6 @@ use client::{BlockChainClient,Client}; use super::test_common::*; use super::helpers::*; -#[cfg(test)] fn get_good_dummy_block() -> Bytes { let mut block_header = Header::new(); let test_spec = get_test_spec(); @@ -17,7 +16,6 @@ fn get_good_dummy_block() -> Bytes { create_test_block(&block_header) } -#[cfg(test)] fn get_bad_state_dummy_block() -> Bytes { let mut block_header = Header::new(); let test_spec = get_test_spec(); @@ -33,7 +31,6 @@ fn get_bad_state_dummy_block() -> Bytes { } -#[cfg(test)] fn get_test_client_with_blocks(blocks: Vec) -> Arc { let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); for block in &blocks { diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 7f9b8ba42..4aa2ae8fc 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -5,11 +5,10 @@ use std::path::PathBuf; use spec::*; use std::fs::{create_dir_all}; -#[cfg(test)] + const FIXED_TEMP_DIR_NAME: &'static str = "parity-temp"; -#[cfg(test)] pub fn get_tests_temp_dir() -> PathBuf { let mut dir = env::temp_dir(); dir.push(FIXED_TEMP_DIR_NAME); @@ -19,7 +18,6 @@ pub fn get_tests_temp_dir() -> PathBuf { dir } -#[cfg(test)] pub fn get_random_path() -> PathBuf { let mut dir = get_tests_temp_dir(); dir.push(H32::random().hex()); @@ -27,13 +25,11 @@ pub fn get_random_path() -> PathBuf { } -#[cfg(test)] pub fn get_test_spec() -> Spec { Spec::new_test() } -#[cfg(test)] pub fn create_test_block(header: &Header) -> Bytes { let mut rlp = RlpStream::new_list(3); rlp.append(header); @@ -42,7 +38,6 @@ pub fn create_test_block(header: &Header) -> Bytes { rlp.out() } -#[cfg(test)] pub fn generate_dummy_client(block_number: usize) -> Arc { let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); From 500dd1480dbcd38abac150f0d03e116064c8cca2 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 13:59:14 +0100 Subject: [PATCH 33/54] temporarily comment out checking zero prefixed int --- util/src/bytes.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/util/src/bytes.rs b/util/src/bytes.rs index 3144dd482..b8d440345 100644 --- a/util/src/bytes.rs +++ b/util/src/bytes.rs @@ -274,8 +274,8 @@ pub enum FromBytesError { DataIsTooShort, /// TODO [debris] Please document me DataIsTooLong, - /// Integer-representation is non-canonically prefixed with zero byte(s). - ZeroPrefixedInt, + // Integer-representation is non-canonically prefixed with zero byte(s). + //ZeroPrefixedInt, } impl StdError for FromBytesError { @@ -312,9 +312,9 @@ macro_rules! impl_uint_from_bytes { match bytes.len() { 0 => Ok(0), l if l <= mem::size_of::<$to>() => { - if bytes[0] == 0 { - return Err(FromBytesError::ZeroPrefixedInt) - } + //if bytes[0] == 0 { + //return Err(FromBytesError::ZeroPrefixedInt) + //} let mut res = 0 as $to; for i in 0..l { let shift = (l - 1 - i) * 8; @@ -349,9 +349,10 @@ macro_rules! impl_uint_from_bytes { ($name: ident) => { impl FromBytes for $name { fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> { - if !bytes.is_empty() && bytes[0] == 0 { - Err(FromBytesError::ZeroPrefixedInt) - } else if bytes.len() <= $name::SIZE { + //if !bytes.is_empty() && bytes[0] == 0 { + //Err(FromBytesError::ZeroPrefixedInt) + //} else + if bytes.len() <= $name::SIZE { Ok($name::from(bytes)) } else { Err(FromBytesError::DataIsTooLong) From 2f7857520e2f3f7de101b0dc669258e68bb6b777 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 14:09:32 +0100 Subject: [PATCH 34/54] Fix block number check (makme it strict!). --- src/error.rs | 4 +++- src/tests/chain.rs | 15 +++++++++------ src/verification.rs | 10 +++++----- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/error.rs b/src/error.rs index cdc0c2d25..4ca988679 100644 --- a/src/error.rs +++ b/src/error.rs @@ -120,7 +120,9 @@ pub enum BlockError { /// TODO [arkpar] Please document me InvalidParentHash(Mismatch), /// TODO [arkpar] Please document me - InvalidNumber(OutOfBounds), + InvalidNumber(Mismatch), + /// Block number isn't sensible. + RidiculousNumber(OutOfBounds), /// TODO [arkpar] Please document me UnknownParent(H256), /// TODO [Gav Wood] Please document me diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 894303a4c..dfc46ae5a 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -42,6 +42,9 @@ fn do_json_test(json_data: &[u8]) -> Vec { client.flush_queue(); let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; assert_eq!(imported_ok, is_valid); + if imported_ok { + flushln!("Imported {}; best block {}", hash, client.chain_info().best_block_hash); + } } fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); } @@ -60,13 +63,13 @@ declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest" declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} // STILL FAILS declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} // STILL FAILS declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"} -declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} +declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} // FAILS AGAIN? declare_test!{BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"} declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} -declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} -declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"} // FAILS -declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} // FAILS -declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} // FAILS -declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} // FAILS +declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} // FAILS AGAIN? +declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"} +declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} +declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} // STILL FAILS +declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} diff --git a/src/verification.rs b/src/verification.rs index 064c0b7d7..158f28f95 100644 --- a/src/verification.rs +++ b/src/verification.rs @@ -162,7 +162,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> /// Check basic header parameters. fn verify_header(header: &Header, engine: &Engine) -> Result<(), Error> { if header.number >= From::from(BlockNumber::max_value()) { - return Err(From::from(BlockError::InvalidNumber(OutOfBounds { max: Some(From::from(BlockNumber::max_value())), min: None, found: header.number }))) + return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { max: Some(From::from(BlockNumber::max_value())), min: None, found: header.number }))) } if header.gas_used > header.gas_limit { return Err(From::from(BlockError::TooMuchGasUsed(OutOfBounds { max: Some(header.gas_limit), min: None, found: header.gas_used }))); @@ -186,8 +186,8 @@ fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> { if header.timestamp <= parent.timestamp { return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp + 1), found: header.timestamp }))) } - if header.number <= parent.number { - return Err(From::from(BlockError::InvalidNumber(OutOfBounds { max: None, min: Some(parent.number + 1), found: header.number }))); + if header.number != parent.number + 1 { + return Err(From::from(BlockError::InvalidNumber(Mismatch { expected: parent.number + 1, found: header.number }))); } Ok(()) } @@ -400,7 +400,7 @@ mod tests { header = good.clone(); header.number = BlockNumber::max_value(); check_fail(basic_test(&create_test_block(&header), engine.deref()), - InvalidNumber(OutOfBounds { max: Some(BlockNumber::max_value()), min: None, found: header.number })); + RidiculousNumber(OutOfBounds { max: Some(BlockNumber::max_value()), min: None, found: header.number })); header = good.clone(); header.gas_used = header.gas_limit + From::from(1); @@ -443,7 +443,7 @@ mod tests { header = good.clone(); header.number = 9; check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine.deref(), &bc), - InvalidNumber(OutOfBounds { max: None, min: Some(parent.number + 1), found: header.number })); + InvalidNumber(Mismatch { expected: parent.number + 1, found: header.number })); header = good.clone(); let mut bad_uncles = good_uncles.clone(); From 16138533bc0fcef75a322e2bf7e78f103bc4c206 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 14:10:52 +0100 Subject: [PATCH 35/54] Remove miseading comment. --- src/tests/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/chain.rs b/src/tests/chain.rs index dfc46ae5a..661968764 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -63,7 +63,7 @@ declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest" declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} // STILL FAILS declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} // STILL FAILS declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"} -declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} // FAILS AGAIN? +declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} declare_test!{BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"} From d2cd6f69cbb1bb25c16d84988419c57f09093eed Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 17:21:54 +0400 Subject: [PATCH 36/54] added temp directory struct with drop --- src/tests/client.rs | 15 ++++++++++----- src/tests/helpers.rs | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/tests/client.rs b/src/tests/client.rs index 92bf31c89..f6887cb9c 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -32,7 +32,8 @@ fn get_bad_state_dummy_block() -> Bytes { fn get_test_client_with_blocks(blocks: Vec) -> Arc { - let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); + let dir = RandomTempPath::new(); + let client = Client::new(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"); @@ -46,20 +47,23 @@ fn get_test_client_with_blocks(blocks: Vec) -> Arc { #[test] fn created() { - let client_result = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()); + let dir = RandomTempPath::new(); + let client_result = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()); assert!(client_result.is_ok()); } #[test] fn imports_from_empty() { - let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); + let dir = RandomTempPath::new(); + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); client.import_verified_blocks(&IoChannel::disconnected()); client.flush_queue(); } #[test] fn imports_good_block() { - let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); + let dir = RandomTempPath::new(); + let client = Client::new(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"); @@ -73,7 +77,8 @@ fn imports_good_block() { #[test] fn query_none_block() { - let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); + let dir = RandomTempPath::new(); + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header_at(188); assert!(non_existant.is_none()); diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index 4aa2ae8fc..e7c717f42 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -3,25 +3,33 @@ use std::env; use super::test_common::*; use std::path::PathBuf; use spec::*; -use std::fs::{create_dir_all}; +use std::fs::{remove_dir_all}; -const FIXED_TEMP_DIR_NAME: &'static str = "parity-temp"; - - -pub fn get_tests_temp_dir() -> PathBuf { - let mut dir = env::temp_dir(); - dir.push(FIXED_TEMP_DIR_NAME); - if let Err(_) = create_dir_all(&dir) { - panic!("failed to create test dir!"); - } - dir +pub struct RandomTempPath { + path: PathBuf } -pub fn get_random_path() -> PathBuf { - let mut dir = get_tests_temp_dir(); - dir.push(H32::random().hex()); - dir +impl RandomTempPath { + pub fn new() -> RandomTempPath { + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + RandomTempPath { + path: dir.clone() + } + } + + pub fn as_path(&self) -> &PathBuf { + &self.path + } +} + +impl Drop for RandomTempPath { + fn drop(&mut self) { + if let Err(e) = remove_dir_all(self.as_path()) { + panic!("failed to remove temp directory, probably something failed to destroyed ({})", e); + } + } } @@ -39,7 +47,9 @@ pub fn create_test_block(header: &Header) -> Bytes { } pub fn generate_dummy_client(block_number: usize) -> Arc { - let client = Client::new(get_test_spec(), &get_random_path(), IoChannel::disconnected()).unwrap(); + let dir = RandomTempPath::new(); + + let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); let test_spec = get_test_spec(); let test_engine = test_spec.to_engine().unwrap(); From 322c1a6cb27ab9a9c2a691e84b1f96a8123b831a Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 14:25:12 +0100 Subject: [PATCH 37/54] use jsonrpc 1.1, moved params deserialization to jsonrpc-core --- rpc/Cargo.toml | 4 +-- rpc/src/impls/eth.rs | 66 ++++++++++++++++++++---------------------- rpc/src/types/block.rs | 10 ------- rpc/src/types/mod.rs | 15 ---------- 4 files changed, 33 insertions(+), 62 deletions(-) diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index ccdd46679..1f10180d6 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -11,8 +11,8 @@ authors = ["Marek Kotewicz , @@ -30,7 +30,7 @@ impl Eth for EthClient { fn author(&self, params: Params) -> Result { match params { - Params::None => Ok(to_value(&Address::new())), + Params::None => to_value(&Address::new()), _ => Err(Error::invalid_params()) } } @@ -68,39 +68,35 @@ impl Eth for EthClient { } fn block(&self, params: Params) -> Result { - if let Params::Array(ref arr) = params { - if let [ref h, Value::Bool(ref _include_txs)] = arr as &[Value] { - if let Ok(hash) = from_value::(h.clone()) { - return match (self.client.block_header(&hash), self.client.block_details(&hash)) { - (Some(bytes), Some(details)) => { - let view = HeaderView::new(&bytes); - let block = Block { - hash: view.sha3(), - parent_hash: view.parent_hash(), - uncles_hash: view.uncles_hash(), - author: view.author(), - miner: view.author(), - state_root: view.state_root(), - transactions_root: view.transactions_root(), - receipts_root: view.receipts_root(), - number: U256::from(view.number()), - gas_used: view.gas_used(), - gas_limit: view.gas_limit(), - logs_bloom: view.log_bloom(), - timestamp: U256::from(view.timestamp()), - difficulty: view.difficulty(), - total_difficulty: details.total_difficulty, - uncles: vec![], - transactions: vec![] - }; - Ok(to_value(&block)) - }, - _ => Ok(Value::Null), - } - } - } + match from_params::<(H256, bool)>(params) { + Ok((hash, _include_txs)) => match (self.client.block_header(&hash), self.client.block_details(&hash)) { + (Some(bytes), Some(details)) => { + let view = HeaderView::new(&bytes); + let block = Block { + hash: view.sha3(), + parent_hash: view.parent_hash(), + uncles_hash: view.uncles_hash(), + author: view.author(), + miner: view.author(), + state_root: view.state_root(), + transactions_root: view.transactions_root(), + receipts_root: view.receipts_root(), + number: U256::from(view.number()), + gas_used: view.gas_used(), + gas_limit: view.gas_limit(), + logs_bloom: view.log_bloom(), + timestamp: U256::from(view.timestamp()), + difficulty: view.difficulty(), + total_difficulty: details.total_difficulty, + uncles: vec![], + transactions: vec![] + }; + to_value(&block) + }, + _ => Ok(Value::Null) + }, + Err(err) => Err(err) } - Err(Error::invalid_params()) } } @@ -126,6 +122,6 @@ impl EthFilter for EthFilterClient { } fn filter_changes(&self, _: Params) -> Result { - Ok(Value::Array(vec![to_value(&self.client.chain_info().best_block_hash)])) + to_value(&self.client.chain_info().best_block_hash).map(|v| Value::Array(vec![v])) } } diff --git a/rpc/src/types/block.rs b/rpc/src/types/block.rs index ac1e673a5..740cf3e09 100644 --- a/rpc/src/types/block.rs +++ b/rpc/src/types/block.rs @@ -34,13 +34,3 @@ pub struct Block { pub uncles: Vec, pub transactions: Vec } - -#[test] -fn test_block_serialize() { - use serde_json; - - let block = Block::default(); - let serialized = serde_json::to_string(&block).unwrap(); - println!("s: {:?}", serialized); - //assert!(false); -} diff --git a/rpc/src/types/mod.rs b/rpc/src/types/mod.rs index 0b7d97916..7be32e84d 100644 --- a/rpc/src/types/mod.rs +++ b/rpc/src/types/mod.rs @@ -1,18 +1,3 @@ -use serde::{Serialize, Deserialize, de}; -use serde_json::value::{Value, Serializer, Deserializer}; - mod block; -pub fn to_value(s: &S) -> Value where S: Serialize { - let mut serializer = Serializer::new(); - // should never panic! - s.serialize(&mut serializer).unwrap(); - serializer.unwrap() -} - -pub fn from_value(value: Value) -> Result::Error> where D: Deserialize { - let mut deserialier = Deserializer::new(value); - Deserialize::deserialize(&mut deserialier) -} - pub use self::block::Block; From e068bad4e0488bf090c3590cbe1a171565af627e Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 14:31:43 +0100 Subject: [PATCH 38/54] Revert "temporarily comment out checking zero prefixed int" This reverts commit 500dd1480dbcd38abac150f0d03e116064c8cca2. --- util/src/bytes.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/util/src/bytes.rs b/util/src/bytes.rs index b8d440345..3144dd482 100644 --- a/util/src/bytes.rs +++ b/util/src/bytes.rs @@ -274,8 +274,8 @@ pub enum FromBytesError { DataIsTooShort, /// TODO [debris] Please document me DataIsTooLong, - // Integer-representation is non-canonically prefixed with zero byte(s). - //ZeroPrefixedInt, + /// Integer-representation is non-canonically prefixed with zero byte(s). + ZeroPrefixedInt, } impl StdError for FromBytesError { @@ -312,9 +312,9 @@ macro_rules! impl_uint_from_bytes { match bytes.len() { 0 => Ok(0), l if l <= mem::size_of::<$to>() => { - //if bytes[0] == 0 { - //return Err(FromBytesError::ZeroPrefixedInt) - //} + if bytes[0] == 0 { + return Err(FromBytesError::ZeroPrefixedInt) + } let mut res = 0 as $to; for i in 0..l { let shift = (l - 1 - i) * 8; @@ -349,10 +349,9 @@ macro_rules! impl_uint_from_bytes { ($name: ident) => { impl FromBytes for $name { fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> { - //if !bytes.is_empty() && bytes[0] == 0 { - //Err(FromBytesError::ZeroPrefixedInt) - //} else - if bytes.len() <= $name::SIZE { + if !bytes.is_empty() && bytes[0] == 0 { + Err(FromBytesError::ZeroPrefixedInt) + } else if bytes.len() <= $name::SIZE { Ok($name::from(bytes)) } else { Err(FromBytesError::DataIsTooLong) From 1402fd5c4c455e95ad0d1ed87fa3f1bf2f028454 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 14:32:10 +0100 Subject: [PATCH 39/54] updated eth filter comment --- rpc/src/traits/eth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/src/traits/eth.rs b/rpc/src/traits/eth.rs index 35b59a91c..63aadbc74 100644 --- a/rpc/src/traits/eth.rs +++ b/rpc/src/traits/eth.rs @@ -44,7 +44,7 @@ pub trait Eth: Sized + Send + Sync + 'static { } } -// TODO: do filters api properly if we commit outselves to polling again... +// TODO: do filters api properly pub trait EthFilter: Sized + Send + Sync + 'static { /// Returns id of new block filter fn new_block_filter(&self, _: Params) -> Result { rpcerr!() } From 7ffe9344ed730b2b6981dc46608a6e147c0f4f01 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 14:43:43 +0100 Subject: [PATCH 40/54] replaced client block_details with block_total_difficulty --- rpc/src/impls/eth.rs | 6 +++--- src/client.rs | 16 +++++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/rpc/src/impls/eth.rs b/rpc/src/impls/eth.rs index af71ac0d5..ac27111d6 100644 --- a/rpc/src/impls/eth.rs +++ b/rpc/src/impls/eth.rs @@ -69,8 +69,8 @@ impl Eth for EthClient { fn block(&self, params: Params) -> Result { match from_params::<(H256, bool)>(params) { - Ok((hash, _include_txs)) => match (self.client.block_header(&hash), self.client.block_details(&hash)) { - (Some(bytes), Some(details)) => { + Ok((hash, _include_txs)) => match (self.client.block_header(&hash), self.client.block_total_difficulty(&hash)) { + (Some(bytes), Some(total_difficulty)) => { let view = HeaderView::new(&bytes); let block = Block { hash: view.sha3(), @@ -87,7 +87,7 @@ impl Eth for EthClient { logs_bloom: view.log_bloom(), timestamp: U256::from(view.timestamp()), difficulty: view.difficulty(), - total_difficulty: details.total_difficulty, + total_difficulty: total_difficulty, uncles: vec![], transactions: vec![] }; diff --git a/src/client.rs b/src/client.rs index 50c4e3f81..0d0fcae95 100644 --- a/src/client.rs +++ b/src/client.rs @@ -13,7 +13,6 @@ use service::NetSyncMessage; use env_info::LastHashes; use verification::*; use block::*; -use extras::BlockDetails; /// General block status #[derive(Debug)] @@ -67,8 +66,8 @@ pub trait BlockChainClient : Sync + Send { /// Get block status by block header hash. fn block_status(&self, hash: &H256) -> BlockStatus; - /// Get familial details concerning a block. - fn block_details(&self, hash: &H256) -> Option; + /// Get block total difficulty. + fn block_total_difficulty(&self, hash: &H256) -> Option; /// Get raw block header data by block number. fn block_header_at(&self, n: BlockNumber) -> Option; @@ -83,6 +82,9 @@ pub trait BlockChainClient : Sync + Send { /// Get block status by block number. fn block_status_at(&self, n: BlockNumber) -> BlockStatus; + /// Get block total difficulty. + fn block_total_difficulty_at(&self, n: BlockNumber) -> Option; + /// Get a tree route between `from` and `to`. /// See `BlockChain::tree_route`. fn tree_route(&self, from: &H256, to: &H256) -> Option; @@ -321,8 +323,8 @@ impl BlockChainClient for Client { if self.chain.read().unwrap().is_known(&hash) { BlockStatus::InChain } else { BlockStatus::Unknown } } - fn block_details(&self, hash: &H256) -> Option { - self.chain.read().unwrap().block_details(hash) + fn block_total_difficulty(&self, hash: &H256) -> Option { + self.chain.read().unwrap().block_details(hash).map(|d| d.total_difficulty) } fn block_header_at(&self, n: BlockNumber) -> Option { @@ -344,6 +346,10 @@ impl BlockChainClient for Client { } } + fn block_total_difficulty_at(&self, n: BlockNumber) -> Option { + self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_total_difficulty(&h)) + } + fn tree_route(&self, from: &H256, to: &H256) -> Option { self.chain.read().unwrap().tree_route(from.clone(), to.clone()) } From 9979e159bd0f962b927e25a571e9a266f03fc12b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 14:44:02 +0100 Subject: [PATCH 41/54] Ethash nonce is H64 not a u64. --- src/ethereum/ethash.rs | 8 ++++---- util/src/hash.rs | 12 +++++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/ethereum/ethash.rs b/src/ethereum/ethash.rs index a677a86cc..019d764df 100644 --- a/src/ethereum/ethash.rs +++ b/src/ethereum/ethash.rs @@ -101,7 +101,7 @@ impl Engine for Ethash { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { // check the seal fields. try!(UntrustedRlp::new(&header.seal[0]).as_val::()); - try!(UntrustedRlp::new(&header.seal[1]).as_val::()); + try!(UntrustedRlp::new(&header.seal[1]).as_val::()); let min_difficulty = decode(self.spec().engine_params.get("minimumDifficulty").unwrap()); if header.difficulty < min_difficulty { @@ -109,7 +109,7 @@ impl Engine for Ethash { } let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(quick_get_difficulty( &Ethash::to_ethash(header.bare_hash()), - header.nonce(), + header.nonce().low_u64(), &Ethash::to_ethash(header.mix_hash())))); if difficulty < header.difficulty { return Err(From::from(BlockError::InvalidEthashDifficulty(Mismatch { expected: header.difficulty, found: difficulty }))); @@ -118,7 +118,7 @@ impl Engine for Ethash { } fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { - let result = self.pow.compute_light(header.number as u64, &Ethash::to_ethash(header.bare_hash()), header.nonce()); + let result = self.pow.compute_light(header.number as u64, &Ethash::to_ethash(header.bare_hash()), header.nonce().low_u64()); let mix = Ethash::from_ethash(result.mix_hash); let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(result.value)); if mix != header.mix_hash() { @@ -208,7 +208,7 @@ impl Ethash { } impl Header { - fn nonce(&self) -> u64 { + fn nonce(&self) -> H64 { decode(&self.seal()[1]) } fn mix_hash(&self) -> H256 { diff --git a/util/src/hash.rs b/util/src/hash.rs index 252877a24..8b55c01cd 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -41,6 +41,8 @@ pub trait FixedHash: Sized + BytesConvertable + Populatable + FromStr + Default fn contains<'a>(&'a self, b: &'a Self) -> bool; /// TODO [debris] Please document me fn is_zero(&self) -> bool; + /// Return the lowest 8 bytes interpreted as a BigEndian integer. + fn low_u64(&self) -> u64; } fn clean_0x(s: &str) -> &str { @@ -71,8 +73,8 @@ macro_rules! impl_hash { &self.0 } } - impl DerefMut for $from { + impl DerefMut for $from { #[inline] fn deref_mut(&mut self) -> &mut [u8] { &mut self.0 @@ -190,6 +192,14 @@ macro_rules! impl_hash { fn is_zero(&self) -> bool { self.eq(&Self::new()) } + + fn low_u64(&self) -> u64 { + let mut ret = 0u64; + for i in 0..min($size, 8) { + ret |= (self.0[$size - 1 - i] as u64) << (i * 8); + } + ret + } } impl FromStr for $from { From a012043e18365ec6e0192bad2f54229bc6c4ac50 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 14:55:50 +0100 Subject: [PATCH 42/54] Fixes #226. --- src/tests/chain.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 661968764..97dc2767f 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -68,8 +68,8 @@ declare_test!{BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTes declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"} declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} -declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} // FAILS AGAIN? +declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} // FAILS: ZeroPrefixed Int. declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"} declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} -declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} // STILL FAILS +declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} From d7bfc6f10b511ab365ac72f91376651cf0b571f1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 15:01:59 +0100 Subject: [PATCH 43/54] Remove misleading comment. --- src/tests/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 97dc2767f..0cf13acb4 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -68,7 +68,7 @@ declare_test!{BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTes declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"} declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} -declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} // FAILS: ZeroPrefixed Int. +declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"} declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} From f1edf627ae18a7ad54098373cae8df8facf1581f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 19:01:33 +0400 Subject: [PATCH 44/54] fixed notes --- src/blockchain.rs | 1 - src/client.rs | 11 ----------- src/tests/client.rs | 11 ----------- 3 files changed, 23 deletions(-) diff --git a/src/blockchain.rs b/src/blockchain.rs index a0b554bcc..da9ee04c2 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -778,5 +778,4 @@ mod tests { assert_eq!(bc.best_block_hash(), b1_hash); } } - } diff --git a/src/client.rs b/src/client.rs index 28b5ada88..9aa9854b6 100644 --- a/src/client.rs +++ b/src/client.rs @@ -293,17 +293,6 @@ impl Client { self.chain.read().unwrap().collect_garbage(false); } - /// Minimizes cache used by the client. - pub fn minimize_cache(&self) { - self.chain.read().unwrap().squeeze_to_fit( - CacheSize { - blocks: 0, - block_logs: 0, - transaction_addresses: 0, - block_details: 0, - blocks_blooms: 0 - }); - } } impl BlockChainClient for Client { diff --git a/src/tests/client.rs b/src/tests/client.rs index f6887cb9c..f6d603f43 100644 --- a/src/tests/client.rs +++ b/src/tests/client.rs @@ -109,17 +109,6 @@ fn imports_block_sequence() { assert!(!block.is_empty()); } - -#[test] -fn can_have_cash_minimized() { - let client = generate_dummy_client(20); - client.minimize_cache(); - assert!(client.cache_info().blocks < 2048); - assert!(client.cache_info().block_details < 4096); - assert_eq!(client.cache_info().block_logs, 0); - assert_eq!(client.cache_info().blocks_blooms, 0); -} - #[test] fn can_collect_garbage() { let client = generate_dummy_client(100); From 7e7b2880957442adc83732ecd8eef21193b251af Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 16:02:03 +0100 Subject: [PATCH 45/54] Fixes #221 --- src/tests/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 0cf13acb4..44e30e7ea 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -61,7 +61,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"} declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"} declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} // STILL FAILS -declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} // STILL FAILS +declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"} declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} declare_test!{BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} From d4c76eed0f55141bdfbaa0a9f074c6cb94eebc77 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 16:05:23 +0100 Subject: [PATCH 46/54] Fixes #220. --- src/tests/chain.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 44e30e7ea..babd2a42f 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -42,9 +42,6 @@ fn do_json_test(json_data: &[u8]) -> Vec { client.flush_queue(); let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; assert_eq!(imported_ok, is_valid); - if imported_ok { - flushln!("Imported {}; best block {}", hash, client.chain_info().best_block_hash); - } } fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); } @@ -60,7 +57,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"} declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"} -declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} // STILL FAILS +declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"} declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} From 0312c08494e6779829c42393a3ed96b5f8dfa454 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 27 Jan 2016 19:07:35 +0400 Subject: [PATCH 47/54] spaces fix --- src/client.rs | 1 - src/tests/helpers.rs | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/client.rs b/src/client.rs index 9aa9854b6..a83ff554e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -292,7 +292,6 @@ impl Client { pub fn tick(&self) { self.chain.read().unwrap().collect_garbage(false); } - } impl BlockChainClient for Client { diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index e7c717f42..a566392cc 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -32,12 +32,10 @@ impl Drop for RandomTempPath { } } - pub fn get_test_spec() -> Spec { Spec::new_test() } - pub fn create_test_block(header: &Header) -> Bytes { let mut rlp = RlpStream::new_list(3); rlp.append(header); @@ -50,7 +48,6 @@ pub fn generate_dummy_client(block_number: usize) -> Arc { let dir = RandomTempPath::new(); let client = Client::new(get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); - let test_spec = get_test_spec(); let test_engine = test_spec.to_engine().unwrap(); let state_root = test_engine.spec().genesis_header().state_root; @@ -77,10 +74,7 @@ pub fn generate_dummy_client(block_number: usize) -> Arc { } } - client.flush_queue(); client.import_verified_blocks(&IoChannel::disconnected()); - client - } \ No newline at end of file From 0cd2e855698ada995467b48767a2462e521dafa5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 16:13:21 +0100 Subject: [PATCH 48/54] Remove flushlns and tidy ready for primetime. --- src/block_queue.rs | 2 -- src/client.rs | 5 ----- src/tests/chain.rs | 5 +---- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/block_queue.rs b/src/block_queue.rs index dab3a5fe3..5ce649710 100644 --- a/src/block_queue.rs +++ b/src/block_queue.rs @@ -158,7 +158,6 @@ impl BlockQueue { }, Err(err) => { let mut v = verification.lock().unwrap(); - flushln!("Stage 2 block verification failed for {}\nError: {:?}", block_hash, err); warn!(target: "client", "Stage 2 block verification failed for {}\nError: {:?}", block_hash, err); v.bad.insert(block_hash.clone()); v.verifying.retain(|e| e.hash != block_hash); @@ -224,7 +223,6 @@ impl BlockQueue { Ok(h) }, Err(err) => { - flushln!("Stage 1 block verification failed for {}\nError: {:?}", BlockView::new(&bytes).header_view().sha3(), err); warn!(target: "client", "Stage 1 block verification failed for {}\nError: {:?}", BlockView::new(&bytes).header_view().sha3(), err); self.verification.lock().unwrap().bad.insert(h.clone()); Err(From::from(err)) diff --git a/src/client.rs b/src/client.rs index 8aea437e4..33ba19147 100644 --- a/src/client.rs +++ b/src/client.rs @@ -199,7 +199,6 @@ impl Client { let _import_lock = self.import_lock.lock(); let blocks = self.block_queue.write().unwrap().drain(128); for block in blocks { -// flushln!("Importing {}...", block.header.hash()); if bad.contains(&block.header.parent_hash) { self.block_queue.write().unwrap().mark_as_bad(&block.header.hash()); bad.insert(block.header.hash()); @@ -208,7 +207,6 @@ impl Client { let header = &block.header; if let Err(e) = verify_block_family(&header, &block.bytes, self.engine.deref().deref(), self.chain.read().unwrap().deref()) { - flushln!("Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); bad.insert(block.header.hash()); @@ -217,7 +215,6 @@ impl Client { let parent = match self.chain.read().unwrap().block_header(&header.parent_hash) { Some(p) => p, None => { - flushln!("Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash); warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); bad.insert(block.header.hash()); @@ -241,7 +238,6 @@ impl Client { let result = match enact_verified(&block, self.engine.deref().deref(), db, &parent, &last_hashes) { Ok(b) => b, Err(e) => { - flushln!("Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); bad.insert(block.header.hash()); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); @@ -249,7 +245,6 @@ impl Client { } }; if let Err(e) = verify_block_final(&header, result.block().header()) { - flushln!("Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); self.block_queue.write().unwrap().mark_as_bad(&header.hash()); break; diff --git a/src/tests/chain.rs b/src/tests/chain.rs index babd2a42f..42b4ee78a 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -33,11 +33,8 @@ fn do_json_test(json_data: &[u8]) -> Vec { { let client = Client::new(spec, &dir, IoChannel::disconnected()).unwrap(); for (b, is_valid) in blocks.into_iter() { - let mut hash = H256::new(); if Block::is_good(&b) { - if let Ok(h) = client.import_block(b.clone()) { - hash = h; - } + let _ = client.import_block(b.clone()); } client.flush_queue(); let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; From 765666faedd2932bb2a89c178b3554989ab8567b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 16:37:32 +0100 Subject: [PATCH 49/54] Rwmove squeeze_to_fit --- src/blockchain.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/blockchain.rs b/src/blockchain.rs index da9ee04c2..fb3755ff2 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -565,15 +565,6 @@ impl BlockChain { } } - /// Tries to squeeze the cache if its too big. - pub fn squeeze_to_fit(&self, size: CacheSize) { - self.blocks.write().unwrap().squeeze(size.blocks); - self.block_details.write().unwrap().squeeze(size.block_details); - self.transaction_addresses.write().unwrap().squeeze(size.transaction_addresses); - self.block_logs.write().unwrap().squeeze(size.block_logs); - self.blocks_blooms.write().unwrap().squeeze(size.blocks_blooms); - } - /// Let the cache system know that a cacheable item has been used. fn note_used(&self, id: CacheID) { let mut cache_man = self.cache_man.write().unwrap(); From 1c67dfdaf9de4851d210833940531da6293f5c51 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 16:41:15 +0100 Subject: [PATCH 50/54] Fix network test. --- src/sync/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 78a5d7613..3223b69bf 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs @@ -9,13 +9,13 @@ /// extern crate ethcore; /// use std::env; /// use std::sync::Arc; -/// use util::network::NetworkService; +/// use util::network::{NetworkService,NetworkConfiguration}; /// use ethcore::client::Client; /// use ethcore::sync::EthSync; /// use ethcore::ethereum; /// /// fn main() { -/// let mut service = NetworkService::start().unwrap(); +/// let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); /// let dir = env::temp_dir(); /// let client = Client::new(ethereum::new_frontier(), &dir, service.io().channel()).unwrap(); /// EthSync::register(&mut service, client); From f7a0f1056803fe6ef819040a236d04872f5aa332 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 16:58:53 +0100 Subject: [PATCH 51/54] missing methods --- src/sync/tests.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sync/tests.rs b/src/sync/tests.rs index 50d6efab2..646933122 100644 --- a/src/sync/tests.rs +++ b/src/sync/tests.rs @@ -51,6 +51,10 @@ impl TestBlockChainClient { } impl BlockChainClient for TestBlockChainClient { + fn block_total_difficulty(&self, _h: &H256) -> Option { + unimplemented!(); + } + fn block_header(&self, h: &H256) -> Option { self.blocks.read().unwrap().get(h).map(|r| Rlp::new(r).at(0).as_raw().to_vec()) @@ -76,6 +80,10 @@ impl BlockChainClient for TestBlockChainClient { } } + fn block_total_difficulty_at(&self, _number: BlockNumber) -> Option { + unimplemented!(); + } + fn block_header_at(&self, n: BlockNumber) -> Option { self.numbers.read().unwrap().get(&(n as usize)).and_then(|h| self.block_header(h)) } From 61c64d264b6ee81c9f11be3bfc429f1d49ffa995 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 17:08:59 +0100 Subject: [PATCH 52/54] moved rust-evmjit -> evmjit, added clippy and basic docs to rpc crate --- Cargo.toml | 2 +- bin/src/main.rs | 1 - {rust-evmjit => evmjit}/.gitignore | 0 {rust-evmjit => evmjit}/Cargo.toml | 0 {rust-evmjit => evmjit}/src/lib.rs | 0 rpc/Cargo.toml | 1 + rpc/src/impls/eth.rs | 5 +++++ rpc/src/impls/net.rs | 2 ++ rpc/src/impls/web3.rs | 3 +++ rpc/src/lib.rs | 8 +++++++- rpc/src/traits/eth.rs | 1 + util/Cargo.toml | 2 +- 12 files changed, 21 insertions(+), 4 deletions(-) rename {rust-evmjit => evmjit}/.gitignore (100%) rename {rust-evmjit => evmjit}/Cargo.toml (100%) rename {rust-evmjit => evmjit}/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 489c1f27e..872e1e675 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ heapsize = "0.2.0" rust-crypto = "0.2.34" time = "0.1" #interpolate_idents = { git = "https://github.com/SkylerLipthay/interpolate_idents" } -evmjit = { path = "rust-evmjit", optional = true } +evmjit = { path = "evmjit", optional = true } ethash = { path = "ethash" } num_cpus = "0.2" clippy = "0.0.37" diff --git a/bin/src/main.rs b/bin/src/main.rs index 942a5cf24..402a0c7c1 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -1,6 +1,5 @@ #![feature(plugin)] #![plugin(docopt_macros)] -// required for serde, move it to a separate library extern crate docopt; extern crate rustc_serialize; extern crate ethcore_util as util; diff --git a/rust-evmjit/.gitignore b/evmjit/.gitignore similarity index 100% rename from rust-evmjit/.gitignore rename to evmjit/.gitignore diff --git a/rust-evmjit/Cargo.toml b/evmjit/Cargo.toml similarity index 100% rename from rust-evmjit/Cargo.toml rename to evmjit/Cargo.toml diff --git a/rust-evmjit/src/lib.rs b/evmjit/src/lib.rs similarity index 100% rename from rust-evmjit/src/lib.rs rename to evmjit/src/lib.rs diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 1f10180d6..ab7072c85 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -15,4 +15,5 @@ jsonrpc-core = "1.1" jsonrpc-http-server = "1.1" ethcore-util = { path = "../util" } ethcore = { path = ".." } +clippy = "0.0.37" diff --git a/rpc/src/impls/eth.rs b/rpc/src/impls/eth.rs index ac27111d6..91c05541a 100644 --- a/rpc/src/impls/eth.rs +++ b/rpc/src/impls/eth.rs @@ -1,3 +1,4 @@ +//! Eth rpc implementation. use std::sync::Arc; use jsonrpc_core::*; use util::hash::*; @@ -8,11 +9,13 @@ use ethcore::views::*; use traits::{Eth, EthFilter}; use types::Block; +/// Eth rpc implementation. pub struct EthClient { client: Arc, } impl EthClient { + /// Creates new EthClient. pub fn new(client: Arc) -> Self { EthClient { client: client @@ -100,11 +103,13 @@ impl Eth for EthClient { } } +/// Eth filter rpc implementation. pub struct EthFilterClient { client: Arc } impl EthFilterClient { + /// Creates new Eth filter client. pub fn new(client: Arc) -> Self { EthFilterClient { client: client diff --git a/rpc/src/impls/net.rs b/rpc/src/impls/net.rs index a1d36de54..20ed4d077 100644 --- a/rpc/src/impls/net.rs +++ b/rpc/src/impls/net.rs @@ -2,9 +2,11 @@ use jsonrpc_core::*; use traits::Net; +/// Net rpc implementation. pub struct NetClient; impl NetClient { + /// Creates new NetClient. pub fn new() -> Self { NetClient } } diff --git a/rpc/src/impls/web3.rs b/rpc/src/impls/web3.rs index 50eb9c6f5..0188aa179 100644 --- a/rpc/src/impls/web3.rs +++ b/rpc/src/impls/web3.rs @@ -1,9 +1,12 @@ +//! Web3 rpc implementation. use jsonrpc_core::*; use traits::Web3; +/// Web3 rpc implementation. pub struct Web3Client; impl Web3Client { + /// Creates new Web3Client. pub fn new() -> Self { Web3Client } } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 43a24a1fb..816eeb4a4 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -1,6 +1,8 @@ +//! Ethcore rpc. +#![warn(missing_docs)] #![feature(custom_derive, custom_attribute, plugin)] -#![feature(slice_patterns)] #![plugin(serde_macros)] +#![plugin(clippy)] extern crate serde; extern crate serde_json; @@ -22,12 +24,14 @@ mod types; pub use self::traits::{Web3, Eth, EthFilter, Net}; pub use self::impls::*; +/// Http server. pub struct HttpServer { handler: IoHandler, threads: usize } impl HttpServer { + /// Construct new http server object with given number of threads. pub fn new(threads: usize) -> HttpServer { HttpServer { handler: IoHandler::new(), @@ -35,10 +39,12 @@ impl HttpServer { } } + /// Add io delegate. pub fn add_delegate(&mut self, delegate: IoDelegate) where D: Send + Sync + 'static { self.handler.add_delegate(delegate); } + /// Start server asynchronously in new thread pub fn start_async(self, addr: &str) { let server = jsonrpc_http_server::Server::new(self.handler, self.threads); server.start_async(addr) diff --git a/rpc/src/traits/eth.rs b/rpc/src/traits/eth.rs index 63aadbc74..25756a713 100644 --- a/rpc/src/traits/eth.rs +++ b/rpc/src/traits/eth.rs @@ -44,6 +44,7 @@ pub trait Eth: Sized + Send + Sync + 'static { } } +/// Eth filters rpc api (polling). // TODO: do filters api properly pub trait EthFilter: Sized + Send + Sync + 'static { /// Returns id of new block filter diff --git a/util/Cargo.toml b/util/Cargo.toml index 362db33b2..d0e2e0ab7 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -26,7 +26,7 @@ crossbeam = "0.2" slab = { git = "https://github.com/arkpar/slab.git" } sha3 = { path = "sha3" } serde = "0.6.7" -clippy = "*" # Always newest, since we use nightly +clippy = "0.0.37" [dev-dependencies] json-tests = { path = "json-tests" } From 856c348e3eb39879761207bae2412e8b56cdacd2 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 17:14:41 +0100 Subject: [PATCH 53/54] moved old rpc implementation to v1/ dir --- bin/src/main.rs | 2 +- rpc/src/lib.rs | 7 +------ rpc/src/{ => v1}/impls/eth.rs | 4 ++-- rpc/src/{ => v1}/impls/mod.rs | 0 rpc/src/{ => v1}/impls/net.rs | 2 +- rpc/src/{ => v1}/impls/web3.rs | 2 +- rpc/src/v1/mod.rs | 10 ++++++++++ rpc/src/{ => v1}/traits/eth.rs | 0 rpc/src/{ => v1}/traits/mod.rs | 0 rpc/src/{ => v1}/traits/net.rs | 0 rpc/src/{ => v1}/traits/web3.rs | 0 rpc/src/{ => v1}/types/block.rs | 0 rpc/src/{ => v1}/types/mod.rs | 0 13 files changed, 16 insertions(+), 11 deletions(-) rename rpc/src/{ => v1}/impls/eth.rs (98%) rename rpc/src/{ => v1}/impls/mod.rs (100%) rename rpc/src/{ => v1}/impls/net.rs (94%) rename rpc/src/{ => v1}/impls/web3.rs (95%) create mode 100644 rpc/src/v1/mod.rs rename rpc/src/{ => v1}/traits/eth.rs (100%) rename rpc/src/{ => v1}/traits/mod.rs (100%) rename rpc/src/{ => v1}/traits/net.rs (100%) rename rpc/src/{ => v1}/traits/web3.rs (100%) rename rpc/src/{ => v1}/types/block.rs (100%) rename rpc/src/{ => v1}/types/mod.rs (100%) diff --git a/bin/src/main.rs b/bin/src/main.rs index 402a0c7c1..712635652 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -50,7 +50,7 @@ fn setup_log(init: &String) { #[cfg(feature = "rpc")] fn setup_rpc_server(client: Arc) { - use rpc::*; + use rpc::v1::*; let mut server = HttpServer::new(1); server.add_delegate(Web3Client::new().to_delegate()); diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 816eeb4a4..7bc1d6987 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -17,12 +17,7 @@ macro_rules! rpcerr { () => (Err(Error::internal_error())) } -pub mod traits; -mod impls; -mod types; - -pub use self::traits::{Web3, Eth, EthFilter, Net}; -pub use self::impls::*; +pub mod v1; /// Http server. pub struct HttpServer { diff --git a/rpc/src/impls/eth.rs b/rpc/src/v1/impls/eth.rs similarity index 98% rename from rpc/src/impls/eth.rs rename to rpc/src/v1/impls/eth.rs index 91c05541a..46718601b 100644 --- a/rpc/src/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -6,8 +6,8 @@ use util::uint::*; use util::sha3::*; use ethcore::client::*; use ethcore::views::*; -use traits::{Eth, EthFilter}; -use types::Block; +use v1::traits::{Eth, EthFilter}; +use v1::types::Block; /// Eth rpc implementation. pub struct EthClient { diff --git a/rpc/src/impls/mod.rs b/rpc/src/v1/impls/mod.rs similarity index 100% rename from rpc/src/impls/mod.rs rename to rpc/src/v1/impls/mod.rs diff --git a/rpc/src/impls/net.rs b/rpc/src/v1/impls/net.rs similarity index 94% rename from rpc/src/impls/net.rs rename to rpc/src/v1/impls/net.rs index 20ed4d077..7bf9cb248 100644 --- a/rpc/src/impls/net.rs +++ b/rpc/src/v1/impls/net.rs @@ -1,6 +1,6 @@ //! Net rpc implementation. use jsonrpc_core::*; -use traits::Net; +use v1::traits::Net; /// Net rpc implementation. pub struct NetClient; diff --git a/rpc/src/impls/web3.rs b/rpc/src/v1/impls/web3.rs similarity index 95% rename from rpc/src/impls/web3.rs rename to rpc/src/v1/impls/web3.rs index 0188aa179..5117ebf16 100644 --- a/rpc/src/impls/web3.rs +++ b/rpc/src/v1/impls/web3.rs @@ -1,6 +1,6 @@ //! Web3 rpc implementation. use jsonrpc_core::*; -use traits::Web3; +use v1::traits::Web3; /// Web3 rpc implementation. pub struct Web3Client; diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs new file mode 100644 index 000000000..a7da1a441 --- /dev/null +++ b/rpc/src/v1/mod.rs @@ -0,0 +1,10 @@ +//! Ethcore rpc v1. +//! +//! Compliant with ethereum rpc. + +pub mod traits; +mod impls; +mod types; + +pub use self::traits::{Web3, Eth, EthFilter, Net}; +pub use self::impls::*; diff --git a/rpc/src/traits/eth.rs b/rpc/src/v1/traits/eth.rs similarity index 100% rename from rpc/src/traits/eth.rs rename to rpc/src/v1/traits/eth.rs diff --git a/rpc/src/traits/mod.rs b/rpc/src/v1/traits/mod.rs similarity index 100% rename from rpc/src/traits/mod.rs rename to rpc/src/v1/traits/mod.rs diff --git a/rpc/src/traits/net.rs b/rpc/src/v1/traits/net.rs similarity index 100% rename from rpc/src/traits/net.rs rename to rpc/src/v1/traits/net.rs diff --git a/rpc/src/traits/web3.rs b/rpc/src/v1/traits/web3.rs similarity index 100% rename from rpc/src/traits/web3.rs rename to rpc/src/v1/traits/web3.rs diff --git a/rpc/src/types/block.rs b/rpc/src/v1/types/block.rs similarity index 100% rename from rpc/src/types/block.rs rename to rpc/src/v1/types/block.rs diff --git a/rpc/src/types/mod.rs b/rpc/src/v1/types/mod.rs similarity index 100% rename from rpc/src/types/mod.rs rename to rpc/src/v1/types/mod.rs From b93bf662b976de476d10b6061a43f5968f692dce Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 17:18:38 +0100 Subject: [PATCH 54/54] added Clippy to client executable, added missing docs --- bin/Cargo.toml | 1 + bin/src/main.rs | 8 ++++++-- rpc/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bin/Cargo.toml b/bin/Cargo.toml index ba258b586..7174ada14 100644 --- a/bin/Cargo.toml +++ b/bin/Cargo.toml @@ -15,6 +15,7 @@ ctrlc = "1.0" ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc", optional = true } ethcore = { path = ".." } +clippy = "0.0.37" [features] rpc = ["ethcore-rpc"] diff --git a/bin/src/main.rs b/bin/src/main.rs index 712635652..190bab311 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -1,5 +1,9 @@ +//! Ethcore client application. + +#![warn(missing_docs)] #![feature(plugin)] #![plugin(docopt_macros)] +#![plugin(clippy)] extern crate docopt; extern crate rustc_serialize; extern crate ethcore_util as util; @@ -34,7 +38,7 @@ Options: -h --help Show this screen. "); -fn setup_log(init: &String) { +fn setup_log(init: &str) { let mut builder = LogBuilder::new(); builder.filter(None, LogLevelFilter::Info); @@ -52,7 +56,7 @@ fn setup_log(init: &String) { fn setup_rpc_server(client: Arc) { use rpc::v1::*; - let mut server = HttpServer::new(1); + let mut server = rpc::HttpServer::new(1); server.add_delegate(Web3Client::new().to_delegate()); server.add_delegate(EthClient::new(client.clone()).to_delegate()); server.add_delegate(EthFilterClient::new(client).to_delegate()); diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index ab7072c85..ee1c97f5f 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore jsonrpc" name = "ethcore-rpc" version = "0.1.0" license = "GPL-3.0" -authors = ["Marek Kotewicz