From 61c64d264b6ee81c9f11be3bfc429f1d49ffa995 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 17:08:59 +0100 Subject: [PATCH 01/11] 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 02/11] 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 03/11] 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 Date: Wed, 27 Jan 2016 17:24:11 +0100 Subject: [PATCH 04/11] Add homestead & random tests. --- src/tests/chain.rs | 3 ++ src/tests/homestead_chain.rs | 67 ++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + 3 files changed, 71 insertions(+) create mode 100644 src/tests/homestead_chain.rs diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 42b4ee78a..613d9f6ff 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -67,3 +67,6 @@ declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHe declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} + +declare_test!{BlockchainTests_RandomTests_bl10251623GO, "BlockchainTests/RandomTests/bl10251623GO"} +declare_test!{BlockchainTests_RandomTests_bl201507071825GO, "BlockchainTests/RandomTests/bl201507071825GO"} diff --git a/src/tests/homestead_chain.rs b/src/tests/homestead_chain.rs new file mode 100644 index 000000000..5d090aefb --- /dev/null +++ b/src/tests/homestead_chain.rs @@ -0,0 +1,67 @@ +use std::env; +use super::test_common::*; +use client::{BlockChainClient,Client}; +use pod_state::*; +use block::Block; +use ethereum; + +fn do_json_test(json_data: &[u8]) -> Vec { + let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); + let mut failed = Vec::new(); + + for (name, test) in json.as_object().unwrap() { + let mut fail = false; + { + let mut fail_unless = |cond: bool| if !cond && !fail { + failed.push(name.clone()); + flush(format!("FAIL\n")); + fail = true; + true + } else {false}; + + flush(format!(" - {}...", name)); + + 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_homestead_test(); + let s = PodState::from_json(test.find("pre").unwrap()); + spec.set_genesis_state(s); + spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); + assert!(spec.is_state_root_valid()); + + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + { + let client = Client::new(spec, &dir, IoChannel::disconnected()).unwrap(); + for (b, is_valid) in blocks.into_iter() { + if Block::is_good(&b) { + let _ = client.import_block(b.clone()); + } + client.flush_queue(); + let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; + assert_eq!(imported_ok, is_valid); + } + fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); + } + fs::remove_dir_all(&dir).unwrap(); + } + if !fail { + flush(format!("ok\n")); + } + } + println!("!!! {:?} tests from failed.", failed.len()); + failed +} + +declare_test!{BlockchainTests_Homestead_bcBlockGasLimitTest, "BlockchainTests/Homestead/bcBlockGasLimitTest"} +declare_test!{BlockchainTests_Homestead_bcForkStressTest, "BlockchainTests/Homestead/bcForkStressTest"} +declare_test!{BlockchainTests_Homestead_bcGasPricerTest, "BlockchainTests/Homestead/bcGasPricerTest"} +declare_test!{BlockchainTests_Homestead_bcInvalidHeaderTest, "BlockchainTests/Homestead/bcInvalidHeaderTest"} +declare_test!{BlockchainTests_Homestead_bcInvalidRLPTest, "BlockchainTests/Homestead/bcInvalidRLPTest"} +declare_test!{BlockchainTests_Homestead_bcMultiChainTest, "BlockchainTests/Homestead/bcMultiChainTest"} +declare_test!{BlockchainTests_Homestead_bcRPC_API_Test, "BlockchainTests/Homestead/bcRPC_API_Test"} +declare_test!{BlockchainTests_Homestead_bcStateTest, "BlockchainTests/Homestead/bcStateTest"} +declare_test!{BlockchainTests_Homestead_bcTotalDifficultyTest, "BlockchainTests/Homestead/bcTotalDifficultyTest"} +declare_test!{BlockchainTests_Homestead_bcUncleHeaderValiditiy, "BlockchainTests/Homestead/bcUncleHeaderValiditiy"} +declare_test!{BlockchainTests_Homestead_bcUncleTest, "BlockchainTests/Homestead/bcUncleTest"} +declare_test!{BlockchainTests_Homestead_bcValidBlockTest, "BlockchainTests/Homestead/bcValidBlockTest"} +declare_test!{BlockchainTests_Homestead_bcWalletTest, "BlockchainTests/Homestead/bcWalletTest"} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 17da72d77..73dc6ef9a 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -6,4 +6,5 @@ mod executive; mod state; mod client; mod chain; +mod homestead_chain; mod helpers; \ No newline at end of file From 382b22b93b997d944ea91a4fd328abcdee502b47 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Wed, 27 Jan 2016 17:25:19 +0100 Subject: [PATCH 05/11] Fixing suicide with self-refund to be consistent with CPP. --- src/externalities.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/externalities.rs b/src/externalities.rs index f1b8c1958..6a874330c 100644 --- a/src/externalities.rs +++ b/src/externalities.rs @@ -215,8 +215,13 @@ 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); + if &address == refund_address { + // TODO [todr] To be consisted with CPP client we set balance to 0 in that case. + self.state.sub_balance(&address, &balance); + } else { + trace!("Suiciding {} -> {} (xfer: {})", address, refund_address, balance); + self.state.transfer_balance(&address, refund_address, &balance); + } self.substate.suicides.insert(address); } From dec9c3a642a334f9396e8632b063515802c473a5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 27 Jan 2016 17:32:12 +0100 Subject: [PATCH 06/11] Remove code duplication. --- src/tests/chain.rs | 16 +++++++++-- src/tests/homestead_chain.rs | 51 ++---------------------------------- 2 files changed, 16 insertions(+), 51 deletions(-) diff --git a/src/tests/chain.rs b/src/tests/chain.rs index 613d9f6ff..ca7884315 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -5,7 +5,12 @@ use pod_state::*; use block::Block; use ethereum; -fn do_json_test(json_data: &[u8]) -> Vec { +pub enum ChainEra { + Frontier, + Homestead, +} + +pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); let mut failed = Vec::new(); @@ -22,7 +27,10 @@ fn do_json_test(json_data: &[u8]) -> Vec { flush(format!(" - {}...", name)); 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 mut spec = match era { + ChainEra::Frontier => ethereum::new_frontier_test(), + ChainEra::Homestead => ethereum::new_homestead_test(), + }; let s = PodState::from_json(test.find("pre").unwrap()); spec.set_genesis_state(s); spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); @@ -52,6 +60,10 @@ fn do_json_test(json_data: &[u8]) -> Vec { failed } +fn do_json_test(json_data: &[u8]) -> Vec { + json_chain_test(json_data, ChainEra::Frontier) +} + declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"} declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"} declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} diff --git a/src/tests/homestead_chain.rs b/src/tests/homestead_chain.rs index 5d090aefb..a9f544d8f 100644 --- a/src/tests/homestead_chain.rs +++ b/src/tests/homestead_chain.rs @@ -1,55 +1,8 @@ -use std::env; use super::test_common::*; -use client::{BlockChainClient,Client}; -use pod_state::*; -use block::Block; -use ethereum; +use super::chain::{ChainEra, json_chain_test}; fn do_json_test(json_data: &[u8]) -> Vec { - let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); - let mut failed = Vec::new(); - - for (name, test) in json.as_object().unwrap() { - let mut fail = false; - { - let mut fail_unless = |cond: bool| if !cond && !fail { - failed.push(name.clone()); - flush(format!("FAIL\n")); - fail = true; - true - } else {false}; - - flush(format!(" - {}...", name)); - - 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_homestead_test(); - let s = PodState::from_json(test.find("pre").unwrap()); - spec.set_genesis_state(s); - spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap()); - assert!(spec.is_state_root_valid()); - - let mut dir = env::temp_dir(); - dir.push(H32::random().hex()); - { - let client = Client::new(spec, &dir, IoChannel::disconnected()).unwrap(); - for (b, is_valid) in blocks.into_iter() { - if Block::is_good(&b) { - let _ = client.import_block(b.clone()); - } - client.flush_queue(); - let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0; - assert_eq!(imported_ok, is_valid); - } - fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"])); - } - fs::remove_dir_all(&dir).unwrap(); - } - if !fail { - flush(format!("ok\n")); - } - } - println!("!!! {:?} tests from failed.", failed.len()); - failed + json_chain_test(json_data, ChainEra::Homestead) } declare_test!{BlockchainTests_Homestead_bcBlockGasLimitTest, "BlockchainTests/Homestead/bcBlockGasLimitTest"} From 09b9001c65279c0449635f17ecd65e5b2322ce34 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 18:17:20 +0100 Subject: [PATCH 07/11] stub for rpc eth methods --- rpc/src/lib.rs | 4 -- rpc/src/v1/traits/eth.rs | 132 +++++++++++++++++++++++++++++++------- rpc/src/v1/traits/mod.rs | 5 ++ rpc/src/v1/traits/net.rs | 4 +- rpc/src/v1/traits/web3.rs | 2 +- 5 files changed, 116 insertions(+), 31 deletions(-) diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 7bc1d6987..a27afb5f6 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -13,10 +13,6 @@ extern crate ethcore; use self::jsonrpc_core::{IoHandler, IoDelegate}; -macro_rules! rpcerr { - () => (Err(Error::internal_error())) -} - pub mod v1; /// Http server. diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 25756a713..1586e7069 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -5,41 +5,125 @@ use 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!() } + fn protocol_version(&self, _: Params) -> Result { rpc_unimplemented!() } /// Returns the number of hashes per second that the node is mining with. - fn hashrate(&self, _: Params) -> Result { rpcerr!() } + fn hashrate(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns block author. + fn author(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns true if client is actively mining new blocks. + fn is_mining(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns current gas_price. + fn gas_price(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns accounts list. + fn accounts(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns highest block number. + fn block_number(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns balance of the given account. + fn balance(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns content of the storage at given address. + fn storage_at(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns block with given index / hash. + fn block(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns the number of transactions sent from given address at given time (block number). + fn transaction_count(&self, _: Params) -> Result { rpc_unimplemented!() } /// Returns the number of transactions in a block. - fn block_transaction_count(&self, _: Params) -> Result { rpcerr!() } + fn block_transaction_count(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns the number of uncles in a given block. + fn block_uncles_count(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns the code at given address at given time (block number). + fn code_at(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Sends transaction. + fn send_transaction(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Call contract. + fn call(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Estimate gas needed for execution of given contract. + fn estimate_gas(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns transaction at given block and index. + fn transaction_at(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns transaction receipt. + fn transaction_receipt(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns an uncles at given block and index. + fn uncle_at(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns available compilers. + fn compilers(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Compiles lll code. + fn compile_lll(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Compiles solidity. + fn compile_solidity(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Compiles serpent. + fn compile_serpent(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns logs matching given filter object. + fn logs(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns the hash of the current block, the seedHash, and the boundary condition to be met. + fn work(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Used for submitting a proof-of-work solution. + fn submit_work(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Used for submitting mining hashrate. + fn submit_hashrate(&self, _: Params) -> Result { rpc_unimplemented!() } /// 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_hashrate", Eth::hashrate); delegate.add_method("eth_coinbase", Eth::author); + delegate.add_method("eth_mining", Eth::is_mining); delegate.add_method("eth_gasPrice", Eth::gas_price); + delegate.add_method("eth_accounts", Eth::accounts); delegate.add_method("eth_blockNumber", Eth::block_number); + delegate.add_method("eth_balance", Eth::balance); + delegate.add_method("eth_getStorageAt", Eth::storage_at); + delegate.add_method("eth_getTransactionCount", Eth::transaction_count); + delegate.add_method("eth_getBlockTransactionCountByHash", Eth::block_transaction_count); + delegate.add_method("eth_getBlockTransactionCountByNumber", Eth::block_transaction_count); + delegate.add_method("eth_getUncleCountByBlockHash", Eth::block_uncles_count); + delegate.add_method("eth_getUncleCountByBlockNumber", Eth::block_uncles_count); + delegate.add_method("eth_code", Eth::code_at); + delegate.add_method("eth_sendTransaction", Eth::send_transaction); + delegate.add_method("eth_call", Eth::call); + delegate.add_method("eth_estimateGas", Eth::estimate_gas); 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); - delegate.add_method("eth_getBlockTransactionCountByNumber", Eth::block_transaction_count); + delegate.add_method("eth_getTransactionByBlockHashAndIndex", Eth::transaction_at); + delegate.add_method("eth_getTransactionByBlockNumberAndIndex", Eth::transaction_at); + delegate.add_method("eth_getTransactionReceipt", Eth::transaction_receipt); + delegate.add_method("eth_getUncleByBlockHashAndIndex", Eth::uncle_at); + delegate.add_method("eth_getUncleByBlockNumberAndIndex", Eth::uncle_at); + delegate.add_method("eth_getCompilers", Eth::compilers); + delegate.add_method("eth_compileLLL", Eth::compile_lll); + delegate.add_method("eth_compileSolidity", Eth::compile_solidity); + delegate.add_method("eth_compileSerpent", Eth::compile_serpent); + delegate.add_method("eth_getLogs", Eth::logs); + delegate.add_method("eth_getWork", Eth::work); + delegate.add_method("eth_submitWork", Eth::submit_work); + delegate.add_method("eth_submitHashrate", Eth::submit_hashrate); delegate } } @@ -48,13 +132,13 @@ pub trait Eth: Sized + Send + Sync + 'static { // 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!() } + fn new_block_filter(&self, _: Params) -> Result { rpc_unimplemented!() } /// Returns id of new block filter - fn new_pending_transaction_filter(&self, _: Params) -> Result { rpcerr!() } + fn new_pending_transaction_filter(&self, _: Params) -> Result { rpc_unimplemented!() } /// Returns filter changes since last poll - fn filter_changes(&self, _: Params) -> Result { rpcerr!() } + fn filter_changes(&self, _: Params) -> Result { rpc_unimplemented!() } /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs index 2fa52d538..70c825175 100644 --- a/rpc/src/v1/traits/mod.rs +++ b/rpc/src/v1/traits/mod.rs @@ -1,4 +1,9 @@ //! Ethereum rpc interfaces. + +macro_rules! rpc_unimplemented { + () => (Err(Error::internal_error())) +} + pub mod web3; pub mod eth; pub mod net; diff --git a/rpc/src/v1/traits/net.rs b/rpc/src/v1/traits/net.rs index 4df8d7114..9196503d2 100644 --- a/rpc/src/v1/traits/net.rs +++ b/rpc/src/v1/traits/net.rs @@ -5,10 +5,10 @@ use jsonrpc_core::*; /// Net rpc interface. pub trait Net: Sized + Send + Sync + 'static { /// Returns protocol version. - fn version(&self, _: Params) -> Result { rpcerr!() } + fn version(&self, _: Params) -> Result { rpc_unimplemented!() } /// Returns number of peers connected to node. - fn peer_count(&self, _: Params) -> Result { rpcerr!() } + fn peer_count(&self, _: Params) -> Result { rpc_unimplemented!() } /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { diff --git a/rpc/src/v1/traits/web3.rs b/rpc/src/v1/traits/web3.rs index 8e73d4304..118316155 100644 --- a/rpc/src/v1/traits/web3.rs +++ b/rpc/src/v1/traits/web3.rs @@ -5,7 +5,7 @@ use jsonrpc_core::*; /// Web3 rpc interface. pub trait Web3: Sized + Send + Sync + 'static { /// Returns current client version. - fn client_version(&self, _: Params) -> Result { rpcerr!() } + fn client_version(&self, _: Params) -> Result { rpc_unimplemented!() } /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { From b13d68c7e99319420b0ee500308635442c8594d2 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 19:00:42 +0100 Subject: [PATCH 08/11] missing eth filter interface --- rpc/src/v1/traits/eth.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 1586e7069..3dcdfdf05 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -131,21 +131,33 @@ 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 + /// Returns id of new filter. + fn new_filter(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns id of new block filter. fn new_block_filter(&self, _: Params) -> Result { rpc_unimplemented!() } - /// Returns id of new block filter + /// Returns id of new block filter. fn new_pending_transaction_filter(&self, _: Params) -> Result { rpc_unimplemented!() } - /// Returns filter changes since last poll + /// Returns filter changes since last poll. fn filter_changes(&self, _: Params) -> Result { rpc_unimplemented!() } + /// Returns filter logs. + fn filter_logs(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Uninstalls filter. + fn uninstall_filter(&self, _: Params) -> Result { rpc_unimplemented!() } + /// 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_newFilter", EthFilter::new_filter); 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::filter_changes); + delegate.add_method("eth_getFilterLogs", EthFilter::filter_logs); + delegate.add_method("eth_uninstallFilter", EthFilter::uninstall_filter); delegate } } From f8568e10b7fe4ffbc525188ca360cd8e09fd55e8 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 27 Jan 2016 19:03:12 +0100 Subject: [PATCH 09/11] missing net_ methods --- rpc/src/v1/traits/net.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rpc/src/v1/traits/net.rs b/rpc/src/v1/traits/net.rs index 9196503d2..84877cab7 100644 --- a/rpc/src/v1/traits/net.rs +++ b/rpc/src/v1/traits/net.rs @@ -10,11 +10,16 @@ pub trait Net: Sized + Send + Sync + 'static { /// Returns number of peers connected to node. fn peer_count(&self, _: Params) -> Result { rpc_unimplemented!() } + /// Returns true if client is actively listening for network connections. + /// Otherwise false. + fn is_listening(&self, _: Params) -> Result { rpc_unimplemented!() } + /// 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("net_version", Net::version); delegate.add_method("net_peerCount", Net::peer_count); + delegate.add_method("net_listening", Net::is_listening); delegate } } From 07d6965ce70f9845ed8b577ff7c1dd98640442c9 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 28 Jan 2016 10:54:49 +0100 Subject: [PATCH 10/11] rpc net methods returns real peer count && protocol version --- bin/src/main.rs | 8 ++++---- rpc/src/v1/impls/net.rs | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/bin/src/main.rs b/bin/src/main.rs index 190bab311..3d4199fcf 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -53,19 +53,19 @@ fn setup_log(init: &str) { #[cfg(feature = "rpc")] -fn setup_rpc_server(client: Arc) { +fn setup_rpc_server(client: Arc, sync: Arc) { use rpc::v1::*; 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()); - server.add_delegate(NetClient::new().to_delegate()); + server.add_delegate(NetClient::new(sync).to_delegate()); server.start_async("127.0.0.1:3030"); } #[cfg(not(feature = "rpc"))] -fn setup_rpc_server(_client: Arc) { +fn setup_rpc_server(_client: Arc, _sync: Arc) { } fn main() { @@ -81,7 +81,7 @@ fn main() { let mut net_settings = NetworkConfiguration::new(); net_settings.boot_nodes = init_nodes; let mut service = ClientService::start(spec, net_settings).unwrap(); - setup_rpc_server(service.client()); + setup_rpc_server(service.client(), service.sync()); let io_handler = Arc::new(ClientIoHandler { client: service.client(), info: Default::default(), sync: service.sync() }); service.io().register_handler(io_handler).expect("Error registering IO handler"); diff --git a/rpc/src/v1/impls/net.rs b/rpc/src/v1/impls/net.rs index 7bf9cb248..dff351c33 100644 --- a/rpc/src/v1/impls/net.rs +++ b/rpc/src/v1/impls/net.rs @@ -1,21 +1,29 @@ //! Net rpc implementation. +use std::sync::Arc; use jsonrpc_core::*; +use ethcore::sync::EthSync; use v1::traits::Net; /// Net rpc implementation. -pub struct NetClient; +pub struct NetClient { + sync: Arc +} impl NetClient { /// Creates new NetClient. - pub fn new() -> Self { NetClient } + pub fn new(sync: Arc) -> Self { + NetClient { + sync: sync + } + } } impl Net for NetClient { fn version(&self, _: Params) -> Result { - Ok(Value::U64(63)) + Ok(Value::U64(self.sync.status().protocol_version as u64)) } fn peer_count(&self, _params: Params) -> Result { - Ok(Value::U64(0)) + Ok(Value::U64(self.sync.status().num_peers as u64)) } } From 87edeae078593f9c8511fb0a3ece9e48f0cedd44 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 28 Jan 2016 11:21:06 +0100 Subject: [PATCH 11/11] fixed tests submodule branch --- .gitmodules | 1 + res/ethereum/tests | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 84843f000..4174eb2e1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "res/ethereum/tests"] path = res/ethereum/tests url = git@github.com:ethereum/tests + branch = develop diff --git a/res/ethereum/tests b/res/ethereum/tests index dc86e6359..c670b1d8c 160000 --- a/res/ethereum/tests +++ b/res/ethereum/tests @@ -1 +1 @@ -Subproject commit dc86e6359675440aea59ddb48648a01c799925d8 +Subproject commit c670b1d8c9f09593a6758ab2c099360e16c7c25b