From c20e76105122a4ac5c8095f070b9bf06d5702b30 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 15 Mar 2016 17:13:44 +0100 Subject: [PATCH 01/91] adding check for a sync --- rpc/src/v1/impls/eth.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index fda391304..66339241e 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -321,6 +321,14 @@ impl Eth for EthClient fn work(&self, params: Params) -> Result { match params { Params::None => { + // check if we a still syncing and return empty strings int that case + { + let sync = take_weak!(self.sync); + if sync.status().state != SyncState::Idle { + return to_value(&(String::new(), String::new(), String::new())); + } + } + let miner = take_weak!(self.miner); let client = take_weak!(self.client); let u = miner.sealing_block(client.deref()).lock().unwrap(); From 8add773b12865a6067a25d3801fc80602b0a33c6 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 15 Mar 2016 17:56:35 +0100 Subject: [PATCH 02/91] [ci skip] grammar fix --- rpc/src/v1/impls/eth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 66339241e..0e5d35dca 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -321,7 +321,7 @@ impl Eth for EthClient fn work(&self, params: Params) -> Result { match params { Params::None => { - // check if we a still syncing and return empty strings int that case + // check if we're still syncing and return empty strings int that case { let sync = take_weak!(self.sync); if sync.status().state != SyncState::Idle { From 30ecff395994240e3bb380ea3ec563622a3fa4ac Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 15 Mar 2016 23:58:46 +0100 Subject: [PATCH 03/91] checking queue also --- rpc/src/v1/impls/eth.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 0e5d35dca..32e9b44b1 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -321,10 +321,11 @@ impl Eth for EthClient fn work(&self, params: Params) -> Result { match params { Params::None => { + let client = take_weak!(self.client); // check if we're still syncing and return empty strings int that case { let sync = take_weak!(self.sync); - if sync.status().state != SyncState::Idle { + if sync.status().state != SyncState::Idle && client.queue_info().is_empty() { return to_value(&(String::new(), String::new(), String::new())); } } From 28e4847b59f70cd4188a90583558ade66bbfc813 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 16 Mar 2016 10:37:08 +0100 Subject: [PATCH 04/91] tests --- rpc/src/v1/impls/eth.rs | 2 +- rpc/src/v1/tests/eth.rs | 28 +++++++++++++++++++---- rpc/src/v1/tests/helpers/miner_service.rs | 20 +++++++++++++--- rpc/src/v1/tests/helpers/sync_provider.rs | 9 ++++---- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 32e9b44b1..520b37045 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -340,7 +340,7 @@ impl Eth for EthClient let seed_hash = Ethash::get_seedhash(b.block().header().number()); to_value(&(pow_hash, seed_hash, target)) } - _ => Err(Error::invalid_params()) + _ => Err(Error::internal_error()) } }, _ => Err(Error::invalid_params()) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 6bc929709..280557e4b 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -43,12 +43,12 @@ fn sync_provider() -> Arc { } fn miner_service() -> Arc { - Arc::new(TestMinerService) + Arc::new(TestMinerService::default()) } struct EthTester { - client: Arc, - _sync: Arc, + pub client: Arc, + pub sync: Arc, _accounts_provider: Arc, _miner: Arc, hashrates: Arc>>, @@ -68,7 +68,7 @@ impl Default for EthTester { io.add_delegate(eth); EthTester { client: client, - _sync: sync, + sync: sync, _accounts_provider: ap, _miner: miner, io: io, @@ -346,5 +346,25 @@ fn rpc_eth_compile_serpent() { assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); } +#[test] +fn returns_no_work_if_cant_mine() { + let eth_tester = EthTester::default(); + let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":["","",""],"id":1}"#; + assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); +} + +#[test] +fn returns_error_if_can_mine_and_no_closed_block() { + use ethsync::{SyncState}; + + let eth_tester = EthTester::default(); + eth_tester.sync.status.write().unwrap().state = SyncState::Idle; + + let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":null},"id":1}"#; + + assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 0cddf2a1e..3a60bd136 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -22,7 +22,19 @@ use ethcore::block::ClosedBlock; use ethcore::transaction::SignedTransaction; use ethminer::{MinerService, MinerStatus}; -pub struct TestMinerService; +pub struct TestMinerService { + pub imported_transactions: RwLock>, + pub latest_closed_block: Mutex>, +} + +impl Default for TestMinerService { + fn default() -> TestMinerService { + TestMinerService { + imported_transactions: RwLock::new(Vec::new()), + latest_closed_block: Mutex::new(None), + } + } +} impl MinerService for TestMinerService { @@ -45,9 +57,11 @@ impl MinerService for TestMinerService { fn prepare_sealing(&self, _chain: &BlockChainClient) { unimplemented!(); } /// Grab the `ClosedBlock` that we want to be sealed. Comes as a mutex that you have to lock. - fn sealing_block(&self, _chain: &BlockChainClient) -> &Mutex> { unimplemented!(); } + fn sealing_block(&self, _chain: &BlockChainClient) -> &Mutex> { + &self.latest_closed_block + } /// Submit `seal` as a valid solution for the header of `pow_hash`. /// Will check the seal, but not actually insert the block into the chain. fn submit_seal(&self, _chain: &BlockChainClient, _pow_hash: H256, _seal: Vec) -> Result<(), Error> { unimplemented!(); } -} \ No newline at end of file +} diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index 631752dfc..bfbfad44b 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . use ethsync::{SyncProvider, SyncStatus, SyncState}; +use std::sync::{RwLock}; pub struct Config { pub protocol_version: u8, @@ -22,13 +23,13 @@ pub struct Config { } pub struct TestSyncProvider { - status: SyncStatus, + pub status: RwLock, } impl TestSyncProvider { pub fn new(config: Config) -> Self { TestSyncProvider { - status: SyncStatus { + status: RwLock::new(SyncStatus { state: SyncState::NotSynced, protocol_version: config.protocol_version, start_block_number: 0, @@ -39,14 +40,14 @@ impl TestSyncProvider { num_peers: config.num_peers, num_active_peers: 0, mem_used: 0, - }, + }) } } } impl SyncProvider for TestSyncProvider { fn status(&self) -> SyncStatus { - self.status.clone() + self.status.read().unwrap().clone() } } From 81f8f939b954ca52f97964bce77be117de8ef0a3 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 17 Mar 2016 11:23:30 +0100 Subject: [PATCH 05/91] Update sync_provider.rs --- rpc/src/v1/tests/helpers/sync_provider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index bfbfad44b..5b4b5b099 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -40,7 +40,7 @@ impl TestSyncProvider { num_peers: config.num_peers, num_active_peers: 0, mem_used: 0, - }) + }), } } } From 31f4a214a94d193bff6f089792aebbd9c2d74ec3 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 17 Mar 2016 12:17:53 +0100 Subject: [PATCH 06/91] adding message from client to sync and disabling sending transactions to the queue while syncing --- ethcore/src/client/client.rs | 6 ++++ ethcore/src/service.rs | 2 ++ rpc/src/v1/impls/eth.rs | 2 +- sync/src/chain.rs | 58 ++++++++++++++++++++++++++++++++++-- sync/src/lib.rs | 3 ++ 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index caa92db97..d8c48e696 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -334,6 +334,12 @@ impl Client where V: Verifier { } } + { + if self.queue_info().is_empty() { + io.send(NetworkIoMessage::User(SyncMessage::BlockQueueEmpty)).expect("error sending message to sync module"); + } + } + imported } diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index bcfe7724f..1c2385934 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -40,6 +40,8 @@ pub enum SyncMessage { NewChainHead, /// A block is ready BlockVerified, + /// blocks queue is empty + BlockQueueEmpty, } /// IO Message type used for Network service diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 520b37045..b0e31ba97 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -151,7 +151,7 @@ impl Eth for EthClient Params::None => { let status = take_weak!(self.sync).status(); let res = match status.state { - SyncState::NotSynced | SyncState::Idle => SyncStatus::None, + SyncState::NotSynced | SyncState::Idle | SyncState::FullySynced => SyncStatus::None, SyncState::Waiting | SyncState::Blocks | SyncState::NewBlocks => SyncStatus::Info(SyncInfo { starting_block: U256::from(status.start_block_number), current_block: U256::from(take_weak!(self.client).chain_info().best_block_number), diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 8f0194289..316718571 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -116,6 +116,8 @@ pub enum SyncState { Blocks, /// Downloading blocks learned from NewHashes packet NewBlocks, + /// Once has an event that client finished processing new blocks + FullySynced, } /// Syncing status and statistics @@ -931,6 +933,11 @@ impl ChainSync { } /// Called when peer sends us new transactions fn on_peer_transactions(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { + // accepting transactions once only fully synced + if self.state != SyncState::FullySynced { + return Ok(()); + } + let item_count = r.item_count(); trace!(target: "sync", "{} -> Transactions ({} entries)", peer_id, item_count); @@ -1273,15 +1280,31 @@ impl ChainSync { /// called when block is imported to chain, updates transactions queue and propagates the blocks pub fn chain_new_blocks(&mut self, io: &mut SyncIo, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - // Notify miner - self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); + if self.state == SyncState::FullySynced { + // Notify miner + self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); + } // Propagate latests blocks self.propagate_latest_blocks(io); // TODO [todr] propagate transactions? } pub fn chain_new_head(&mut self, io: &mut SyncIo) { - self.miner.prepare_sealing(io.chain()); + if self.state == SyncState::FullySynced { + self.miner.prepare_sealing(io.chain()); + } + } + + // called once has nothing to download and client reports that all that downloaded is imported + pub fn set_fully_synced(&mut self) { + self.state = SyncState::FullySynced; + } + + // handles event from client about empty blow_queue + pub fn client_block_queue_empty(&mut self) { + if self.state == SyncState::Idle { + self.set_fully_synced(); + } } } @@ -1618,6 +1641,7 @@ mod tests { client.add_blocks(1, EachBlockWith::UncleAndTransaction); client.add_blocks(1, EachBlockWith::Transaction); let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5)); + sync.state = SyncState::FullySynced; let good_blocks = vec![client.block_hash_delta_minus(2)]; let retracted_blocks = vec![client.block_hash_delta_minus(1)]; @@ -1637,6 +1661,34 @@ mod tests { assert_eq!(status.transaction_queue_future, 0); } + #[test] + fn should_not_add_transactions_to_queue_if_not_synced() { + // given + let mut client = TestBlockChainClient::new(); + client.add_blocks(98, EachBlockWith::Uncle); + client.add_blocks(1, EachBlockWith::UncleAndTransaction); + client.add_blocks(1, EachBlockWith::Transaction); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5)); + sync.state = SyncState::Idle; + + let good_blocks = vec![client.block_hash_delta_minus(2)]; + let retracted_blocks = vec![client.block_hash_delta_minus(1)]; + + let mut queue = VecDeque::new(); + let mut io = TestIo::new(&mut client, &mut queue, None); + + // when + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); + assert_eq!(sync.miner.status().transaction_queue_future, 0); + assert_eq!(sync.miner.status().transaction_queue_pending, 0); + sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks); + + // then + let status = sync.miner.status(); + assert_eq!(status.transaction_queue_pending, 0); + assert_eq!(status.transaction_queue_future, 0); + } + #[test] fn returns_requested_block_headers() { let mut client = TestBlockChainClient::new(); diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 1c87da2de..d78ac3b89 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -173,6 +173,9 @@ impl NetworkProtocolHandler for EthSync { SyncMessage::NewChainHead => { let mut sync_io = NetSyncIo::new(io, self.chain.deref()); self.sync.write().unwrap().chain_new_head(&mut sync_io); + }, + SyncMessage::BlockQueueEmpty => { + self.sync.write().unwrap().client_block_queue_empty(); } _ => {/* Ignore other messages */}, } From 9f8a131fa4b6b643e49ea1ebd13d9ed73ca74822 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 16 Mar 2016 18:25:32 +0100 Subject: [PATCH 07/91] restart sync on getting old unknown header --- sync/src/chain.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 316718571..8697c94a7 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -404,6 +404,12 @@ impl ChainSync { debug!(target: "sync", "Mismatched block header {}", number + 1); self.remove_downloaded_blocks(number + 1); } + if self.have_common_block && number < self.current_base_block() + 1 { + // unkown header + debug!(target: "sync", "Old block header {:?} ({}) is unknown, restarting sync", hash, number); + self.restart(io); + return Ok(()); + } } let hdr = Header { data: try!(r.at(i)).as_raw().to_vec(), From 3c8fb60cbd7f865f9cc8042b864d3ec5dcd12139 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 17 Mar 2016 09:54:05 +0100 Subject: [PATCH 08/91] Update install-parity.sh --- install-parity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-parity.sh b/install-parity.sh index 439700306..74387ca7f 100755 --- a/install-parity.sh +++ b/install-parity.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/beta-0.9/parity_linux_0.9.0-0_amd64.deb +PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.0.0-rc1/parity_linux_1.0.0.rc1-0_amd64.deb function run_installer() From 69d89583ca6cedfdbd1f50ad8fbf5f6434cc1749 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 15 Mar 2016 18:17:48 +0100 Subject: [PATCH 09/91] proper blockchain json parsing --- Cargo.lock | 12 +++++ Cargo.toml | 1 + json/Cargo.toml | 21 ++++++++ json/build.rs | 45 ++++++++++++++++ json/src/blockchain/account.rs | 30 +++++++++++ json/src/blockchain/block.rs | 35 +++++++++++++ json/src/blockchain/blockchain.rs | 35 +++++++++++++ json/src/blockchain/header.rs | 51 ++++++++++++++++++ json/src/blockchain/mod.rs | 25 +++++++++ json/src/blockchain/state.rs | 34 ++++++++++++ json/src/blockchain/test.rs | 32 ++++++++++++ json/src/blockchain/transaction.rs | 35 +++++++++++++ json/src/bytes.rs | 81 ++++++++++++++++++++++++++++ json/src/hash.rs | 81 ++++++++++++++++++++++++++++ json/src/lib.rs | 28 ++++++++++ json/src/lib.rs.in | 25 +++++++++ json/src/uint.rs | 84 ++++++++++++++++++++++++++++++ 17 files changed, 655 insertions(+) create mode 100644 json/Cargo.toml create mode 100644 json/build.rs create mode 100644 json/src/blockchain/account.rs create mode 100644 json/src/blockchain/block.rs create mode 100644 json/src/blockchain/blockchain.rs create mode 100644 json/src/blockchain/header.rs create mode 100644 json/src/blockchain/mod.rs create mode 100644 json/src/blockchain/state.rs create mode 100644 json/src/blockchain/test.rs create mode 100644 json/src/blockchain/transaction.rs create mode 100644 json/src/bytes.rs create mode 100644 json/src/hash.rs create mode 100644 json/src/lib.rs create mode 100644 json/src/lib.rs.in create mode 100644 json/src/uint.rs diff --git a/Cargo.lock b/Cargo.lock index 4ed5d1ac2..dbaa92e9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -286,6 +286,18 @@ dependencies = [ "vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethjson" +version = "0.1.0" +dependencies = [ + "ethcore-util 1.1.0", + "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethminer" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index a7abf8921..0e2e0ce8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ ethsync = { path = "sync" } ethminer = { path = "miner" } ethcore-devtools = { path = "devtools" } ethcore-rpc = { path = "rpc", optional = true } +ethjson = { path = "json" } [features] default = ["rpc"] diff --git a/json/Cargo.toml b/json/Cargo.toml new file mode 100644 index 000000000..61599c331 --- /dev/null +++ b/json/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ethjson" +version = "0.1.0" +authors = ["debris "] +build = "build.rs" + +[dependencies] +ethcore-util = { path = "../util" } +rustc-serialize = "0.3" +serde = "0.7.0" +serde_json = "0.7.0" +serde_macros = { version = "0.7.0", optional = true } +clippy = { version = "0.0.50", optional = true } + +[build-dependencies] +serde_codegen = { version = "0.7.0", optional = true } +syntex = "0.29.0" + +[features] +default = ["serde_codegen"] +nightly = ["serde_macros"] diff --git a/json/build.rs b/json/build.rs new file mode 100644 index 000000000..a23790d86 --- /dev/null +++ b/json/build.rs @@ -0,0 +1,45 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#[cfg(not(feature = "serde_macros"))] +mod inner { + extern crate syntex; + extern crate serde_codegen; + + use std::env; + use std::path::Path; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let src = Path::new("src/lib.rs.in"); + let dst = Path::new(&out_dir).join("lib.rs"); + + let mut registry = syntex::Registry::new(); + + serde_codegen::register(&mut registry); + registry.expand("", &src, &dst).unwrap(); + } +} + +#[cfg(feature = "serde_macros")] +mod inner { + pub fn main() {} +} + +fn main() { + inner::main(); +} diff --git a/json/src/blockchain/account.rs b/json/src/blockchain/account.rs new file mode 100644 index 000000000..0d72d7fd7 --- /dev/null +++ b/json/src/blockchain/account.rs @@ -0,0 +1,30 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test account deserializer. + +use std::collections::BTreeMap; +use uint::Uint; +use bytes::Bytes; + +/// Blockchain test account deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Account { + balance: Uint, + code: Bytes, + nonce: Uint, + storage: BTreeMap, +} diff --git a/json/src/blockchain/block.rs b/json/src/blockchain/block.rs new file mode 100644 index 000000000..5dd423e7c --- /dev/null +++ b/json/src/blockchain/block.rs @@ -0,0 +1,35 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test block deserializer. + +use uint::Uint; +use bytes::Bytes; +use blockchain::header::Header; +use blockchain::transaction::Transaction; + +/// Blockchain test block deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Block { + #[serde(rename="blockHeader")] + header: Header, + #[serde(rename="blocknumber")] + number: Uint, + rlp: Bytes, + transactions: Vec, + #[serde(rename="uncleHeaders")] + uncles: Vec
, +} diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs new file mode 100644 index 000000000..675e10718 --- /dev/null +++ b/json/src/blockchain/blockchain.rs @@ -0,0 +1,35 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain deserialization. + +use bytes::Bytes; +use blockchain::state::State; +use blockchain::header::Header; + +/// Blockchain deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct BlockChain { + #[serde(rename="genesisBlockHeader")] + genesis_block: Header, + #[serde(rename="genesisRLP")] + genesis_rlp: Bytes, + blocks: Vec
, + #[serde(rename="postState")] + post_state: State, + #[serde(rename="preState")] + pre_state: State, +} diff --git a/json/src/blockchain/header.rs b/json/src/blockchain/header.rs new file mode 100644 index 000000000..ea58c76a1 --- /dev/null +++ b/json/src/blockchain/header.rs @@ -0,0 +1,51 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test header deserializer. + +use hash::Hash; +use uint::Uint; +use bytes::Bytes; + +/// Blockchain test header deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Header { + bloom: Hash, // TODO Bloom + coinbase: Hash, + difficulty: Uint, + #[serde(rename="extraData")] + extra_data: Bytes, + #[serde(rename="gasLimit")] + gas_limit: Uint, + #[serde(rename="gasUsed")] + gas_used: Uint, + hash: Hash, + #[serde(rename="mixHash")] + mix_hash: Hash, + nonce: Uint, // TODO fix parsing + number: Uint, + #[serde(rename="parentHash")] + parent_hash: Hash, + #[serde(rename="receiptTrie")] + receipt_trie: Hash, + #[serde(rename="stateRoot")] + state_root: Hash, + timestamp: Uint, + #[serde(rename="transactionsTrie")] + transactions_trie: Hash, + #[serde(rename="uncleHash")] + uncle_hash: Hash, +} diff --git a/json/src/blockchain/mod.rs b/json/src/blockchain/mod.rs new file mode 100644 index 000000000..046b2e534 --- /dev/null +++ b/json/src/blockchain/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test deserialization. + +pub mod account; +pub mod block; +pub mod blockchain; +pub mod header; +pub mod state; +pub mod transaction; +pub mod test; diff --git a/json/src/blockchain/state.rs b/json/src/blockchain/state.rs new file mode 100644 index 000000000..c934d7c0a --- /dev/null +++ b/json/src/blockchain/state.rs @@ -0,0 +1,34 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test state deserializer. + +use std::collections::BTreeMap; +use std::ops::Deref; +use hash::Hash; +use blockchain::account::Account; + +/// Blockchain test state deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct State(BTreeMap); + +impl Deref for State { + type Target = BTreeMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/json/src/blockchain/test.rs b/json/src/blockchain/test.rs new file mode 100644 index 000000000..6097a60e6 --- /dev/null +++ b/json/src/blockchain/test.rs @@ -0,0 +1,32 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test deserializer. + +use std::collections::BTreeMap; +use std::ops::Deref; +use blockchain::blockchain::BlockChain; + +/// Blockchain test deserializer. +pub struct Test(BTreeMap); + +impl Deref for Test { + type Target = BTreeMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/json/src/blockchain/transaction.rs b/json/src/blockchain/transaction.rs new file mode 100644 index 000000000..5d04748f5 --- /dev/null +++ b/json/src/blockchain/transaction.rs @@ -0,0 +1,35 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain test transaction deserialization. + +use uint::Uint; +use bytes::Bytes; + +/// Blockchain test transaction deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Transaction { + data: Bytes, + #[serde(rename="gasLimit")] + gas_limit: Uint, + #[serde(rename="gasPrice")] + gas_price: Uint, + nonce: Uint, + r: Uint, + s: Uint, + v: Uint, + value: Uint +} diff --git a/json/src/bytes.rs b/json/src/bytes.rs new file mode 100644 index 000000000..034c90d62 --- /dev/null +++ b/json/src/bytes.rs @@ -0,0 +1,81 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Lenient bytes json deserialization for test json files. + +use rustc_serialize::hex::FromHex; +use serde::{Deserialize, Deserializer, Error}; +use serde::de::Visitor; + +/// Lenient bytes json deserialization for test json files. +#[derive(Default, Debug, PartialEq)] +pub struct Bytes(Vec); + +impl Into> for Bytes { + fn into(self) -> Vec { + self.0 + } +} + +impl Deserialize for Bytes { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(BytesVisitor) + } +} + +struct BytesVisitor; + +impl Visitor for BytesVisitor { + type Value = Bytes; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + let v = match value.len() { + 0 => vec![], + 2 if value.starts_with("0x") => vec![], + _ if value.starts_with("0x") => try!(FromHex::from_hex(&value[2..]).map_err(|_| Error::custom("Invalid hex value."))), + _ => try!(FromHex::from_hex(value).map_err(|_| Error::custom("Invalid hex value"))) + }; + Ok(Bytes(v)) + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +//mod test { + //use std::str::FromStr; + //use serde_json; + //use util::hash::H256; + //use hash::Hash; + + //#[test] + //fn uint_deserialization() { + //let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#; + //let deserialized: Vec = serde_json::from_str(s).unwrap(); + //assert_eq!(deserialized, vec![ + //Hash(H256::from(0)), + //Hash(H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap()) + //]); + //} + + //#[test] + //fn uint_into() { + //assert_eq!(H256::from(0), Hash(H256::from(0)).into()); + //} +//} diff --git a/json/src/hash.rs b/json/src/hash.rs new file mode 100644 index 000000000..e5bbedbfa --- /dev/null +++ b/json/src/hash.rs @@ -0,0 +1,81 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Lenient hash json deserialization for test json files. + +use std::str::FromStr; +use serde::{Deserialize, Deserializer, Error}; +use serde::de::Visitor; +use util::hash::H256; + +/// Lenient hash json deserialization for test json files. +#[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Hash(H256); + +impl Into for Hash { + fn into(self) -> H256 { + self.0 + } +} + +impl Deserialize for Hash { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(HashVisitor) + } +} + +struct HashVisitor; + +impl Visitor for HashVisitor { + type Value = Hash; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + let value = match value.len() { + 0 => H256::from(0), + _ => try!(H256::from_str(value).map_err(|_| Error::custom("invalid hex value."))) + }; + + Ok(Hash(value)) + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +mod test { + use std::str::FromStr; + use serde_json; + use util::hash::H256; + use hash::Hash; + + #[test] + fn uint_deserialization() { + let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#; + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, vec![ + Hash(H256::from(0)), + Hash(H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap()) + ]); + } + + #[test] + fn uint_into() { + assert_eq!(H256::from(0), Hash(H256::from(0)).into()); + } +} diff --git a/json/src/lib.rs b/json/src/lib.rs new file mode 100644 index 000000000..b94e1fa55 --- /dev/null +++ b/json/src/lib.rs @@ -0,0 +1,28 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Json deserialization module. + +#![warn(missing_docs)] +#![cfg_attr(feature="nightly", feature(custom_derive, custom_attribute, plugin))] +#![cfg_attr(feature="nightly", plugin(serde_macros, clippy))] + +#[cfg(feature = "serde_macros")] +include!("lib.rs.in"); + +#[cfg(not(feature = "serde_macros"))] +include!(concat!(env!("OUT_DIR"), "/lib.rs")); + diff --git a/json/src/lib.rs.in b/json/src/lib.rs.in new file mode 100644 index 000000000..6d3437811 --- /dev/null +++ b/json/src/lib.rs.in @@ -0,0 +1,25 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +extern crate rustc_serialize; +extern crate serde; +extern crate serde_json; +extern crate ethcore_util as util; + +pub mod hash; +pub mod uint; +pub mod bytes; +pub mod blockchain; diff --git a/json/src/uint.rs b/json/src/uint.rs new file mode 100644 index 000000000..f7f34f1dd --- /dev/null +++ b/json/src/uint.rs @@ -0,0 +1,84 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Lenient uint json deserialization for test json files. + +use std::str::FromStr; +use serde::{Deserialize, Deserializer, Error}; +use serde::de::Visitor; +use util::numbers::{U256, Uint as U}; + +/// Lenient uint json deserialization for test json files. +#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Uint(U256); + +impl Into for Uint { + fn into(self) -> U256 { + self.0 + } +} + +impl Deserialize for Uint { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(UintVisitor) + } +} + +struct UintVisitor; + +impl Visitor for UintVisitor { + type Value = Uint; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + let value = match value.len() { + 0 => U256::from(0), + 2 if value.starts_with("0x") => U256::from(0), + _ if value.starts_with("0x") => try!(U256::from_str(&value[2..]).map_err(|_| Error::custom("invalid hex value."))), + _ => try!(U256::from_dec_str(value).map_err(|_| Error::custom("invalid decimal value."))) + }; + + Ok(Uint(value)) + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +mod test { + use serde_json; + use util::numbers::U256; + use uint::Uint; + + #[test] + fn uint_deserialization() { + let s = r#"["0xa", "10", "", "0x"]"#; + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, vec![ + Uint(U256::from(10)), + Uint(U256::from(10)), + Uint(U256::from(0)), + Uint(U256::from(0)) + ]); + } + + #[test] + fn uint_into() { + assert_eq!(U256::from(10), Uint(U256::from(10)).into()); + } +} From 24993b8d4e0e15e48dc064a6cd4c5cef8480c405 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 15 Mar 2016 18:23:59 +0100 Subject: [PATCH 10/91] finished blockchain test deserialization --- json/src/blockchain/header.rs | 22 ++++----- json/src/blockchain/state.rs | 6 +-- json/src/bytes.rs | 40 +++++++-------- json/src/hash.rs | 91 ++++++++++++++++++++--------------- 4 files changed, 86 insertions(+), 73 deletions(-) diff --git a/json/src/blockchain/header.rs b/json/src/blockchain/header.rs index ea58c76a1..fc27fc1f5 100644 --- a/json/src/blockchain/header.rs +++ b/json/src/blockchain/header.rs @@ -16,15 +16,15 @@ //! Blockchain test header deserializer. -use hash::Hash; +use hash::{H64, H256, Bloom}; use uint::Uint; use bytes::Bytes; /// Blockchain test header deserializer. #[derive(Debug, PartialEq, Deserialize)] pub struct Header { - bloom: Hash, // TODO Bloom - coinbase: Hash, + bloom: Bloom, + coinbase: H256, difficulty: Uint, #[serde(rename="extraData")] extra_data: Bytes, @@ -32,20 +32,20 @@ pub struct Header { gas_limit: Uint, #[serde(rename="gasUsed")] gas_used: Uint, - hash: Hash, + hash: H256, #[serde(rename="mixHash")] - mix_hash: Hash, - nonce: Uint, // TODO fix parsing + mix_hash: H256, + nonce: H64, number: Uint, #[serde(rename="parentHash")] - parent_hash: Hash, + parent_hash: H256, #[serde(rename="receiptTrie")] - receipt_trie: Hash, + receipt_trie: H256, #[serde(rename="stateRoot")] - state_root: Hash, + state_root: H256, timestamp: Uint, #[serde(rename="transactionsTrie")] - transactions_trie: Hash, + transactions_trie: H256, #[serde(rename="uncleHash")] - uncle_hash: Hash, + uncle_hash: H256, } diff --git a/json/src/blockchain/state.rs b/json/src/blockchain/state.rs index c934d7c0a..2af0dbf21 100644 --- a/json/src/blockchain/state.rs +++ b/json/src/blockchain/state.rs @@ -18,15 +18,15 @@ use std::collections::BTreeMap; use std::ops::Deref; -use hash::Hash; +use hash::Address; use blockchain::account::Account; /// Blockchain test state deserializer. #[derive(Debug, PartialEq, Deserialize)] -pub struct State(BTreeMap); +pub struct State(BTreeMap); impl Deref for State { - type Target = BTreeMap; + type Target = BTreeMap; fn deref(&self) -> &Self::Target { &self.0 diff --git a/json/src/bytes.rs b/json/src/bytes.rs index 034c90d62..c9e31e888 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -58,24 +58,26 @@ impl Visitor for BytesVisitor { } #[cfg(test)] -//mod test { - //use std::str::FromStr; - //use serde_json; - //use util::hash::H256; - //use hash::Hash; +mod test { + use serde_json; + use bytes::Bytes; - //#[test] - //fn uint_deserialization() { - //let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#; - //let deserialized: Vec = serde_json::from_str(s).unwrap(); - //assert_eq!(deserialized, vec![ - //Hash(H256::from(0)), - //Hash(H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap()) - //]); - //} + #[test] + fn bytes_deserialization() { + let s = r#"["", "0x", "0x12", "1234"]"#; + let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized, vec![ + Bytes(vec![]), + Bytes(vec![]), + Bytes(vec![0x12]), + Bytes(vec![0x12, 0x34]) + ]); + } - //#[test] - //fn uint_into() { - //assert_eq!(H256::from(0), Hash(H256::from(0)).into()); - //} -//} + #[test] + fn bytes_into() { + let bytes = Bytes(vec![0xff, 0x11]); + let v: Vec = bytes.into(); + assert_eq!(vec![0xff, 0x11], v); + } +} diff --git a/json/src/hash.rs b/json/src/hash.rs index e5bbedbfa..8ed28c33c 100644 --- a/json/src/hash.rs +++ b/json/src/hash.rs @@ -19,63 +19,74 @@ use std::str::FromStr; use serde::{Deserialize, Deserializer, Error}; use serde::de::Visitor; -use util::hash::H256; +use util::hash::{H64 as Hash64, Address as Hash160, H256 as Hash256, H2048 as Hash2048}; -/// Lenient hash json deserialization for test json files. -#[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct Hash(H256); -impl Into for Hash { - fn into(self) -> H256 { - self.0 +macro_rules! impl_hash { + ($name: ident, $inner: ident) => { + /// Lenient hash json deserialization for test json files. + #[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] + pub struct $name($inner); + + impl Into<$inner> for $name { + fn into(self) -> $inner { + self.0 + } + } + + impl Deserialize for $name { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + + struct HashVisitor; + + impl Visitor for HashVisitor { + type Value = $name; + + fn visit_str(&mut self, value: &str) -> Result where E: Error { + let value = match value.len() { + 0 => $inner::from(0), + _ => try!($inner::from_str(value).map_err(|_| Error::custom("invalid hex value."))) + }; + + Ok($name(value)) + } + + fn visit_string(&mut self, value: String) -> Result where E: Error { + self.visit_str(value.as_ref()) + } + } + + deserializer.deserialize(HashVisitor) + } + } } } -impl Deserialize for Hash { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - deserializer.deserialize(HashVisitor) - } -} - -struct HashVisitor; - -impl Visitor for HashVisitor { - type Value = Hash; - - fn visit_str(&mut self, value: &str) -> Result where E: Error { - let value = match value.len() { - 0 => H256::from(0), - _ => try!(H256::from_str(value).map_err(|_| Error::custom("invalid hex value."))) - }; - - Ok(Hash(value)) - } - - fn visit_string(&mut self, value: String) -> Result where E: Error { - self.visit_str(value.as_ref()) - } -} +impl_hash!(H64, Hash64); +impl_hash!(Address, Hash160); +impl_hash!(H256, Hash256); +impl_hash!(Bloom, Hash2048); #[cfg(test)] mod test { use std::str::FromStr; use serde_json; - use util::hash::H256; - use hash::Hash; + use util::hash; + use hash::H256; #[test] - fn uint_deserialization() { + fn hash_deserialization() { let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#; - let deserialized: Vec = serde_json::from_str(s).unwrap(); + let deserialized: Vec = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, vec![ - Hash(H256::from(0)), - Hash(H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap()) + H256(hash::H256::from(0)), + H256(hash::H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap()) ]); } #[test] - fn uint_into() { - assert_eq!(H256::from(0), Hash(H256::from(0)).into()); + fn hash_into() { + assert_eq!(hash::H256::from(0), H256(hash::H256::from(0)).into()); } } From c15e78cd951a0c00b93beb56847cfb68dc73a55c Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 15 Mar 2016 19:32:07 +0100 Subject: [PATCH 11/91] tests for loading test json files --- json/src/blockchain/account.rs | 20 ++++++ json/src/blockchain/block.rs | 39 +++++++++- json/src/blockchain/blockchain.rs | 114 +++++++++++++++++++++++++++++- json/src/blockchain/header.rs | 34 ++++++++- json/src/bytes.rs | 8 ++- json/src/hash.rs | 4 +- json/src/uint.rs | 8 ++- 7 files changed, 215 insertions(+), 12 deletions(-) diff --git a/json/src/blockchain/account.rs b/json/src/blockchain/account.rs index 0d72d7fd7..eb6f0a1dd 100644 --- a/json/src/blockchain/account.rs +++ b/json/src/blockchain/account.rs @@ -28,3 +28,23 @@ pub struct Account { nonce: Uint, storage: BTreeMap, } + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::account::Account; + + #[test] + fn header_deserialization() { + let s = r#"{ + "balance" : "0x09184e72a078", + "code" : "0x600140600155", + "nonce" : "0x00", + "storage" : { + "0x01" : "0x9a10c2b5bb8f3c602e674006d9b21f09167df57c87a78a5ce96d4159ecb76520" + } + }"#; + let _deserialized: Account= serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/blockchain/block.rs b/json/src/blockchain/block.rs index 5dd423e7c..ed297077c 100644 --- a/json/src/blockchain/block.rs +++ b/json/src/blockchain/block.rs @@ -16,7 +16,6 @@ //! Blockchain test block deserializer. -use uint::Uint; use bytes::Bytes; use blockchain::header::Header; use blockchain::transaction::Transaction; @@ -26,10 +25,44 @@ use blockchain::transaction::Transaction; pub struct Block { #[serde(rename="blockHeader")] header: Header, - #[serde(rename="blocknumber")] - number: Uint, rlp: Bytes, transactions: Vec, #[serde(rename="uncleHeaders")] uncles: Vec
, } + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::block::Block; + + #[test] + fn block_deserialization() { + let s = r#"{ + "blockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x", + "gasLimit" : "0x2fefba", + "gasUsed" : "0x00", + "hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f", + "mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06", + "nonce" : "931dcc53e5edc514", + "number" : "0x01", + "parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3", + "timestamp" : "0x56850b7b", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "blocknumber" : "1", + "rlp" : "0xf901fcf901f7a05a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba808456850b7b80a013735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd0688931dcc53e5edc514c0c0", + "transactions" : [], + "uncleHeaders" : [] + }"#; + let _deserialized: Block = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 675e10718..f6b1259ca 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -19,6 +19,7 @@ use bytes::Bytes; use blockchain::state::State; use blockchain::header::Header; +use blockchain::block::Block; /// Blockchain deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -27,9 +28,118 @@ pub struct BlockChain { genesis_block: Header, #[serde(rename="genesisRLP")] genesis_rlp: Bytes, - blocks: Vec
, + blocks: Vec, #[serde(rename="postState")] post_state: State, - #[serde(rename="preState")] + #[serde(rename="pre")] pre_state: State, } + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::blockchain::BlockChain; + + #[test] + fn blockchain_deserialization() { + let s = r#"{ + "blocks" : [{ + "blockHeader" : { + "bloom" : "00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x0102030405060708091011121314151617181920212223242526272829303132", + "gasLimit" : "0x2fefba", + "gasUsed" : "0x560b", + "hash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a", + "mixHash" : "5266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce2", + "nonce" : "59ba4daed1898e21", + "number" : "0x01", + "parentHash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d", + "receiptTrie" : "c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296", + "stateRoot" : "bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bf", + "timestamp" : "0x56850c2c", + "transactionsTrie" : "498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "rlp" : "0xf90285f90219a0f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefba82560b8456850c2ca00102030405060708091011121314151617181920212223242526272829303132a05266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce28859ba4daed1898e21f866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ca0ee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3a04e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21c0", + "transactions" : [ + { + "data" : "0x", + "gasLimit" : "0xc350", + "gasPrice" : "0x0a", + "nonce" : "0x00", + "r" : "0xee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3", + "s" : "0x4e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "v" : "0x1c", + "value" : "0x012a05f200" + } + ], + "uncleHeaders" : [ + ] + }], + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x42", + "gasLimit" : "0x2fefd8", + "gasUsed" : "0x00", + "hash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d", + "mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "nonce" : "0102030405060708", + "number" : "0x00", + "parentHash" : "0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0", + "lastblockhash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a", + "postState" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0x012a05f264", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1", + "nonce" : "0x00", + "storage" : { + } + }, + "8888f1f195afa192cfee860698584c030f4c9db1" : { + "balance" : "0x4563918244f75c6e", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x012a029592", + "code" : "0x", + "nonce" : "0x01", + "storage" : { + } + } + }, + "pre" : { + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "0x64", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1", + "nonce" : "0x00", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x02540be400", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + } + } + }"#; + let _deserialized: BlockChain = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + //} +} diff --git a/json/src/blockchain/header.rs b/json/src/blockchain/header.rs index fc27fc1f5..e97039213 100644 --- a/json/src/blockchain/header.rs +++ b/json/src/blockchain/header.rs @@ -16,7 +16,7 @@ //! Blockchain test header deserializer. -use hash::{H64, H256, Bloom}; +use hash::{H64, Address, H256, Bloom}; use uint::Uint; use bytes::Bytes; @@ -24,7 +24,7 @@ use bytes::Bytes; #[derive(Debug, PartialEq, Deserialize)] pub struct Header { bloom: Bloom, - coinbase: H256, + coinbase: Address, difficulty: Uint, #[serde(rename="extraData")] extra_data: Bytes, @@ -49,3 +49,33 @@ pub struct Header { #[serde(rename="uncleHash")] uncle_hash: H256, } + +#[cfg(test)] +mod tests { + use serde_json; + use blockchain::header::Header; + + #[test] + fn header_deserialization() { + let s = r#"{ + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x", + "gasLimit" : "0x2fefba", + "gasUsed" : "0x00", + "hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f", + "mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06", + "nonce" : "931dcc53e5edc514", + "number" : "0x01", + "parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae", + "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3", + "timestamp" : "0x56850b7b", + "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }"#; + let _deserialized: Header = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/bytes.rs b/json/src/bytes.rs index c9e31e888..28b7636d4 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -46,8 +46,12 @@ impl Visitor for BytesVisitor { let v = match value.len() { 0 => vec![], 2 if value.starts_with("0x") => vec![], - _ if value.starts_with("0x") => try!(FromHex::from_hex(&value[2..]).map_err(|_| Error::custom("Invalid hex value."))), - _ => try!(FromHex::from_hex(value).map_err(|_| Error::custom("Invalid hex value"))) + _ if value.starts_with("0x") => try!(FromHex::from_hex(&value[2..]).map_err(|_| { + Error::custom(format!("Invalid hex value {}.", value).as_ref()) + })), + _ => try!(FromHex::from_hex(value).map_err(|_| { + Error::custom(format!("Invalid hex value {}.", value).as_ref()) + })) }; Ok(Bytes(v)) } diff --git a/json/src/hash.rs b/json/src/hash.rs index 8ed28c33c..098f2e7a8 100644 --- a/json/src/hash.rs +++ b/json/src/hash.rs @@ -46,7 +46,9 @@ macro_rules! impl_hash { fn visit_str(&mut self, value: &str) -> Result where E: Error { let value = match value.len() { 0 => $inner::from(0), - _ => try!($inner::from_str(value).map_err(|_| Error::custom("invalid hex value."))) + _ => try!($inner::from_str(value).map_err(|_| { + Error::custom(format!("Invalid hex value {}.", value).as_ref()) + })) }; Ok($name(value)) diff --git a/json/src/uint.rs b/json/src/uint.rs index f7f34f1dd..41e717277 100644 --- a/json/src/uint.rs +++ b/json/src/uint.rs @@ -47,8 +47,12 @@ impl Visitor for UintVisitor { let value = match value.len() { 0 => U256::from(0), 2 if value.starts_with("0x") => U256::from(0), - _ if value.starts_with("0x") => try!(U256::from_str(&value[2..]).map_err(|_| Error::custom("invalid hex value."))), - _ => try!(U256::from_dec_str(value).map_err(|_| Error::custom("invalid decimal value."))) + _ if value.starts_with("0x") => try!(U256::from_str(&value[2..]).map_err(|_| { + Error::custom(format!("Invalid hex value {}.", value).as_ref()) + })), + _ => try!(U256::from_dec_str(value).map_err(|_| { + Error::custom(format!("Invalid decimal value {}.", value).as_ref()) + })) }; Ok(Uint(value)) From 13d0d6d006efd8ca5d6881bcd857d911da2d5d9e Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 17 Mar 2016 13:14:06 +0100 Subject: [PATCH 12/91] adding helper can_sync --- sync/src/chain.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 8697c94a7..f7a03a7bd 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -405,7 +405,7 @@ impl ChainSync { self.remove_downloaded_blocks(number + 1); } if self.have_common_block && number < self.current_base_block() + 1 { - // unkown header + // unkown header debug!(target: "sync", "Old block header {:?} ({}) is unknown, restarting sync", hash, number); self.restart(io); return Ok(()); @@ -627,6 +627,13 @@ impl ChainSync { self.state = SyncState::Waiting; } + fn can_sync(&self) -> bool { + match self.state { + SyncState::Idle | SyncState::NotSynced | SyncState::FullySynced => true, + _ => false + } + } + /// Find something to do for a peer. Called for a new peer or when a peer is done with it's task. fn sync_peer(&mut self, io: &mut SyncIo, peer_id: PeerId, force: bool) { let (peer_latest, peer_difficulty) = { @@ -646,7 +653,7 @@ impl ChainSync { if force || peer_difficulty > syncing_difficulty { // start sync self.syncing_difficulty = peer_difficulty; - if self.state == SyncState::Idle || self.state == SyncState::NotSynced { + if self.can_sync() { self.state = SyncState::Blocks; } trace!(target: "sync", "Starting sync with better chain"); From 114bab66c428184aedb662ac79e46288a6e896ae Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 17 Mar 2016 14:11:32 +0100 Subject: [PATCH 13/91] overhaul to flag --- ethcore/src/client/client.rs | 7 +----- ethcore/src/service.rs | 4 ++-- rpc/src/v1/impls/eth.rs | 2 +- sync/src/chain.rs | 41 ++++++++++++------------------------ sync/src/lib.rs | 7 ++---- sync/src/tests/helpers.rs | 2 +- 6 files changed, 21 insertions(+), 42 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d8c48e696..6ee1b88d5 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -324,6 +324,7 @@ impl Client where V: Verifier { invalid: invalid_blocks, enacted: enacted, retracted: retracted, + is_last: self.queue_info().is_empty() })).unwrap(); } } @@ -334,12 +335,6 @@ impl Client where V: Verifier { } } - { - if self.queue_info().is_empty() { - io.send(NetworkIoMessage::User(SyncMessage::BlockQueueEmpty)).expect("error sending message to sync module"); - } - } - imported } diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 1c2385934..a46581e3c 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -35,13 +35,13 @@ pub enum SyncMessage { retracted: Vec, /// Hashes of blocks that are now included in cannonical chain enacted: Vec, + /// Set when blockqueue is empty + is_last: bool, }, /// Best Block Hash in chain has been changed NewChainHead, /// A block is ready BlockVerified, - /// blocks queue is empty - BlockQueueEmpty, } /// IO Message type used for Network service diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index b0e31ba97..520b37045 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -151,7 +151,7 @@ impl Eth for EthClient Params::None => { let status = take_weak!(self.sync).status(); let res = match status.state { - SyncState::NotSynced | SyncState::Idle | SyncState::FullySynced => SyncStatus::None, + SyncState::NotSynced | SyncState::Idle => SyncStatus::None, SyncState::Waiting | SyncState::Blocks | SyncState::NewBlocks => SyncStatus::Info(SyncInfo { starting_block: U256::from(status.start_block_number), current_block: U256::from(take_weak!(self.client).chain_info().best_block_number), diff --git a/sync/src/chain.rs b/sync/src/chain.rs index f7a03a7bd..def9ad7f4 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -116,8 +116,6 @@ pub enum SyncState { Blocks, /// Downloading blocks learned from NewHashes packet NewBlocks, - /// Once has an event that client finished processing new blocks - FullySynced, } /// Syncing status and statistics @@ -217,6 +215,8 @@ pub struct ChainSync { network_id: U256, /// Miner miner: Arc, + /// Fully-synced flag + is_fully_synced: bool, } type RlpResponseResult = Result, PacketDecodeError>; @@ -243,6 +243,7 @@ impl ChainSync { max_download_ahead_blocks: max(MAX_HEADERS_TO_REQUEST, config.max_download_ahead_blocks), network_id: config.network_id, miner: miner, + is_fully_synced: true, } } @@ -629,7 +630,7 @@ impl ChainSync { fn can_sync(&self) -> bool { match self.state { - SyncState::Idle | SyncState::NotSynced | SyncState::FullySynced => true, + SyncState::Idle | SyncState::NotSynced => true, _ => false } } @@ -947,7 +948,7 @@ impl ChainSync { /// Called when peer sends us new transactions fn on_peer_transactions(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { // accepting transactions once only fully synced - if self.state != SyncState::FullySynced { + if !self.is_fully_synced { return Ok(()); } @@ -1292,8 +1293,10 @@ impl ChainSync { } /// called when block is imported to chain, updates transactions queue and propagates the blocks - pub fn chain_new_blocks(&mut self, io: &mut SyncIo, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - if self.state == SyncState::FullySynced { + pub fn chain_new_blocks(&mut self, io: &mut SyncIo, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256], is_last: bool) { + // Set the state in which it can accept transactions from the net + self.is_fully_synced = is_last; + if self.is_fully_synced { // Notify miner self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); } @@ -1303,21 +1306,7 @@ impl ChainSync { } pub fn chain_new_head(&mut self, io: &mut SyncIo) { - if self.state == SyncState::FullySynced { - self.miner.prepare_sealing(io.chain()); - } - } - - // called once has nothing to download and client reports that all that downloaded is imported - pub fn set_fully_synced(&mut self) { - self.state = SyncState::FullySynced; - } - - // handles event from client about empty blow_queue - pub fn client_block_queue_empty(&mut self) { - if self.state == SyncState::Idle { - self.set_fully_synced(); - } + self.miner.prepare_sealing(io.chain()); } } @@ -1654,7 +1643,6 @@ mod tests { client.add_blocks(1, EachBlockWith::UncleAndTransaction); client.add_blocks(1, EachBlockWith::Transaction); let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5)); - sync.state = SyncState::FullySynced; let good_blocks = vec![client.block_hash_delta_minus(2)]; let retracted_blocks = vec![client.block_hash_delta_minus(1)]; @@ -1663,10 +1651,10 @@ mod tests { let mut io = TestIo::new(&mut client, &mut queue, None); // when - sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, true); assert_eq!(sync.miner.status().transaction_queue_future, 0); assert_eq!(sync.miner.status().transaction_queue_pending, 1); - sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks); + sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks, true); // then let status = sync.miner.status(); @@ -1682,7 +1670,6 @@ mod tests { client.add_blocks(1, EachBlockWith::UncleAndTransaction); client.add_blocks(1, EachBlockWith::Transaction); let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5)); - sync.state = SyncState::Idle; let good_blocks = vec![client.block_hash_delta_minus(2)]; let retracted_blocks = vec![client.block_hash_delta_minus(1)]; @@ -1691,10 +1678,10 @@ mod tests { let mut io = TestIo::new(&mut client, &mut queue, None); // when - sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, false); assert_eq!(sync.miner.status().transaction_queue_future, 0); assert_eq!(sync.miner.status().transaction_queue_pending, 0); - sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks); + sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks, false); // then let status = sync.miner.status(); diff --git a/sync/src/lib.rs b/sync/src/lib.rs index d78ac3b89..8ab6a23e9 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -166,17 +166,14 @@ impl NetworkProtocolHandler for EthSync { fn message(&self, io: &NetworkContext, message: &SyncMessage) { match *message { - SyncMessage::NewChainBlocks { ref imported, ref invalid, ref enacted, ref retracted } => { + SyncMessage::NewChainBlocks { ref imported, ref invalid, ref enacted, ref retracted, is_last } => { let mut sync_io = NetSyncIo::new(io, self.chain.deref()); - self.sync.write().unwrap().chain_new_blocks(&mut sync_io, imported, invalid, enacted, retracted); + self.sync.write().unwrap().chain_new_blocks(&mut sync_io, imported, invalid, enacted, retracted, is_last); }, SyncMessage::NewChainHead => { let mut sync_io = NetSyncIo::new(io, self.chain.deref()); self.sync.write().unwrap().chain_new_head(&mut sync_io); }, - SyncMessage::BlockQueueEmpty => { - self.sync.write().unwrap().client_block_queue_empty(); - } _ => {/* Ignore other messages */}, } } diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index b3e62ccc6..42ef728b9 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -168,6 +168,6 @@ impl TestNet { pub fn trigger_chain_new_blocks(&mut self, peer_id: usize) { let mut peer = self.peer_mut(peer_id); - peer.sync.chain_new_blocks(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None), &[], &[], &[], &[]); + peer.sync.chain_new_blocks(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None), &[], &[], &[], &[], true); } } From 42a6954ec94dda00850aeb8acdf09f9d1aa726a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 15 Mar 2016 10:57:09 +0100 Subject: [PATCH 14/91] Speeding up build --- .travis.yml | 67 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 91c50fa13..115bf4ec6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,20 +8,46 @@ branches: - /^stable-.*$/ - /^beta$/ - /^stable$/ +git: + depth: 3 matrix: fast_finish: false allow_failures: - rust: nightly include: - rust: stable - env: FEATURES="--features travis-beta" KCOV_FEATURES="" TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer" ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}" + env: FEATURES="--features travis-beta" RUN_TESTS="true" + - rust: beta + env: FEATURES="--features travis-beta" RUN_TESTS="true" + - rust: stable + env: FEATURES="--features travis-beta" RUN_BUILD="true" + - rust: beta + env: FEATURES="--features travis-beta" RUN_BUILD="true" + - rust: stable + env: FEATURES="--features travis-beta" RUN_COVERAGE="true" + - rust: nightly + env: FEATURES="--features travis-nightly" RUN_BENCHES="true" + - rust: nightly + env: FEATURES="--features travis-nightly" RUN_TESTS="true" +env: + global: + # GH_TOKEN + - secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw= + - CVER=5 + - NUM_JOBS=1 + # - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer" + - TARGETS="-p ethcore-util" + - ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}" + - KCOV_FEATURES="" + - KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov" + - RUN_TESTS="false" + - RUN_COVERAGE="false" + - RUN_BUILD="false" + - RUN_BENCHES="false" cache: apt: true directories: - - target/debug/deps - - target/debug/build - - target/release/deps - - target/release/build + - $TRAVIS_BUILD_DIR/target - $HOME/.cargo addons: apt: @@ -29,22 +55,27 @@ addons: - libcurl4-openssl-dev - libelf-dev - libdw-dev + script: -- cargo build --release --verbose ${FEATURES} -- cargo test --release --verbose ${FEATURES} ${TARGETS} -#- cargo bench --no-run ${FEATURES} ${TARGETS} -- tar cvzf parity${ARCHIVE_SUFFIX}.tar.gz -C target/release parity + - echo "$TRAVIS_BUILD_DIR/target" + - ls "$TRAVIS_BUILD_DIR/target" + - if [ "$RUN_TESTS" = "true" ]; then cargo test --release --verbose ${FEATURES} ${TARGETS}; fi + - if [ "$RUN_BENCHES" = "true" ]; then cargo bench --no-run ${FEATURES} ${TARGETS}; fi + - if [ "$RUN_BUILD" = "true" ]; then cargo build --release --verbose ${FEATURES}; fi + - if [ "$RUN_BUILD" = "true" ]; then tar cvzf parity${ARCHIVE_SUFFIX}.tar.gz -C target/release parity; fi + after_success: | + [ "$RUN_COVERAGE" = "true" ] && wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. && cargo test --no-run ${KCOV_FEATURES} ${TARGETS} && - ./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov target/debug/deps/ethcore_util-* && - ./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov target/debug/deps/ethash-* && - ./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov target/debug/deps/ethcore-* && - ./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov target/debug/deps/ethsync-* && - ./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov target/debug/deps/ethcore_rpc-* && - ./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov target/debug/deps/ethminer-* && - ./kcov-master/tmp/usr/local/bin/kcov --coveralls-id=${TRAVIS_JOB_ID} --exclude-pattern /usr/,/.cargo,/root/.multirust target/kcov target/debug/parity-* && + $KCOV_CMD target/debug/deps/ethcore_util-* && + $KCOV_CMD target/debug/deps/ethash-* && + $KCOV_CMD target/debug/deps/ethcore-* && + $KCOV_CMD target/debug/deps/ethsync-* && + $KCOV_CMD target/debug/deps/ethcore_rpc-* && + $KCOV_CMD target/debug/deps/ethminer-* && + $KCOV_CMD target/debug/parity-* && [ $TRAVIS_BRANCH = master ] && [ $TRAVIS_PULL_REQUEST = false ] && [ $TRAVIS_RUST_VERSION = stable ] && @@ -53,10 +84,6 @@ after_success: | pip install --user ghp-import && /home/travis/.local/bin/ghp-import -n target/doc && git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages -env: - global: - # GH_TOKEN - - secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw= deploy: provider: releases From 2b4640c94c4d4df47f2eb4840db36e91dac411a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 15 Mar 2016 11:04:48 +0100 Subject: [PATCH 15/91] Cleaning --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 115bf4ec6..905f92bbd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,10 +33,7 @@ env: global: # GH_TOKEN - secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw= - - CVER=5 - - NUM_JOBS=1 - # - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer" - - TARGETS="-p ethcore-util" + - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer" - ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}" - KCOV_FEATURES="" - KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov" From 4292e75dcaf1f314d6480f5e55c2d33a934b1f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 15 Mar 2016 11:05:31 +0100 Subject: [PATCH 16/91] More cleaning --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 905f92bbd..7ac668d62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,8 +54,6 @@ addons: - libdw-dev script: - - echo "$TRAVIS_BUILD_DIR/target" - - ls "$TRAVIS_BUILD_DIR/target" - if [ "$RUN_TESTS" = "true" ]; then cargo test --release --verbose ${FEATURES} ${TARGETS}; fi - if [ "$RUN_BENCHES" = "true" ]; then cargo bench --no-run ${FEATURES} ${TARGETS}; fi - if [ "$RUN_BUILD" = "true" ]; then cargo build --release --verbose ${FEATURES}; fi From 69d6f3ed3eafffcd3f50180ae6ebfe2c476a872e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 15 Mar 2016 15:09:12 +0100 Subject: [PATCH 17/91] Enabling fast finish --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7ac668d62..990b4852f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ branches: git: depth: 3 matrix: - fast_finish: false + fast_finish: true allow_failures: - rust: nightly include: From fae7039fda028d7fbe0e05054f2307a1d465028d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 15 Mar 2016 15:55:37 +0100 Subject: [PATCH 18/91] Disabling benches and beta tests --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 990b4852f..5d6de65c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,16 +17,16 @@ matrix: include: - rust: stable env: FEATURES="--features travis-beta" RUN_TESTS="true" - - rust: beta - env: FEATURES="--features travis-beta" RUN_TESTS="true" + # - rust: beta + # env: FEATURES="--features travis-beta" RUN_TESTS="true" - rust: stable env: FEATURES="--features travis-beta" RUN_BUILD="true" - rust: beta env: FEATURES="--features travis-beta" RUN_BUILD="true" - rust: stable env: FEATURES="--features travis-beta" RUN_COVERAGE="true" - - rust: nightly - env: FEATURES="--features travis-nightly" RUN_BENCHES="true" + # - rust: nightly + # env: FEATURES="--features travis-nightly" RUN_BENCHES="true" - rust: nightly env: FEATURES="--features travis-nightly" RUN_TESTS="true" env: From e767fd88f6f1e3f919c06d0f7cb2820d683e655a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 11:19:12 +0100 Subject: [PATCH 19/91] Returning number of transactions pending in block not queue --- miner/src/lib.rs | 2 ++ miner/src/miner.rs | 4 +++- rpc/src/v1/impls/eth.rs | 2 +- rpc/src/v1/tests/eth.rs | 14 ++++++++++++++ rpc/src/v1/tests/helpers/miner_service.rs | 8 +++++++- 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/miner/src/lib.rs b/miner/src/lib.rs index a431bd44e..9d2635bef 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -108,4 +108,6 @@ pub struct MinerStatus { pub transaction_queue_pending: usize, /// Number of transactions in queue with state `future` (not yet ready to be included in block) pub transaction_queue_future: usize, + /// Number of transactions included in currently mined block + pub block_pending: usize, } diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 6d5b3086e..d9fb0a271 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -22,7 +22,7 @@ use std::sync::atomic::AtomicBool; use util::{H256, U256, Address, Bytes, Uint}; use ethcore::views::{BlockView}; use ethcore::client::{BlockChainClient, BlockId}; -use ethcore::block::{ClosedBlock}; +use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::{Error}; use ethcore::transaction::SignedTransaction; use super::{MinerService, MinerStatus, TransactionQueue}; @@ -104,9 +104,11 @@ impl MinerService for Miner { fn status(&self) -> MinerStatus { let status = self.transaction_queue.lock().unwrap().status(); + let block = self.sealing_block.lock().unwrap(); MinerStatus { transaction_queue_pending: status.pending, transaction_queue_future: status.future, + block_pending: block.as_ref().map_or(0, |b| b.transactions().len()), } } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 520b37045..2b975dcf2 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -236,7 +236,7 @@ impl Eth for EthClient fn block_transaction_count_by_number(&self, params: Params) -> Result { from_params::<(BlockNumber,)>(params) .and_then(|(block_number,)| match block_number { - BlockNumber::Pending => to_value(&U256::from(take_weak!(self.miner).status().transaction_queue_pending)), + BlockNumber::Pending => to_value(&U256::from(take_weak!(self.miner).status().block_pending)), _ => to_value(&take_weak!(self.client).block(block_number.into()) .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count()))) }) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 280557e4b..389de103b 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -242,6 +242,20 @@ fn rpc_eth_transaction_count_by_number() { assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); } +#[test] +fn rpc_eth_transaction_count_by_number_pending() { + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_getBlockTransactionCountByNumber", + "params": ["pending"], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":"0x01","id":1}"#; + + assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); +} + + #[test] fn rpc_eth_uncle_count_by_block_hash() { let request = r#"{ diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 3a60bd136..354e6f507 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -39,7 +39,13 @@ impl Default for TestMinerService { impl MinerService for TestMinerService { /// Returns miner's status. - fn status(&self) -> MinerStatus { unimplemented!(); } + fn status(&self) -> MinerStatus { + MinerStatus { + transaction_queue_pending: 0, + transaction_queue_future: 0, + block_pending: 1 + } + } /// Imports transactions to transaction queue. fn import_transactions(&self, _transactions: Vec, _fetch_nonce: T) -> Result<(), Error> where T: Fn(&Address) -> U256 { unimplemented!(); } From 4db397ecb1ca9840b4e46d736b9fd29f6e106c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 11:19:12 +0100 Subject: [PATCH 20/91] Renaming status fields to something more descriptive. --- miner/src/lib.rs | 8 ++++---- miner/src/miner.rs | 6 +++--- rpc/src/v1/impls/eth.rs | 4 +++- rpc/src/v1/tests/helpers/miner_service.rs | 6 +++--- sync/src/chain.rs | 12 ++++++------ 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/miner/src/lib.rs b/miner/src/lib.rs index 9d2635bef..5821c9815 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -42,7 +42,7 @@ //! //! let miner: Miner = Miner::default(); //! // get status -//! assert_eq!(miner.status().transaction_queue_pending, 0); +//! assert_eq!(miner.status().transactions_in_pending_queue, 0); //! //! // Check block for sealing //! miner.prepare_sealing(client.deref()); @@ -105,9 +105,9 @@ pub trait MinerService : Send + Sync { /// Mining status pub struct MinerStatus { /// Number of transactions in queue with state `pending` (ready to be included in block) - pub transaction_queue_pending: usize, + pub transactions_in_pending_queue: usize, /// Number of transactions in queue with state `future` (not yet ready to be included in block) - pub transaction_queue_future: usize, + pub transactions_in_future_queue: usize, /// Number of transactions included in currently mined block - pub block_pending: usize, + pub transactions_in_pending_block: usize, } diff --git a/miner/src/miner.rs b/miner/src/miner.rs index d9fb0a271..ccf45f61a 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -106,9 +106,9 @@ impl MinerService for Miner { let status = self.transaction_queue.lock().unwrap().status(); let block = self.sealing_block.lock().unwrap(); MinerStatus { - transaction_queue_pending: status.pending, - transaction_queue_future: status.future, - block_pending: block.as_ref().map_or(0, |b| b.transactions().len()), + transactions_in_pending_queue: status.pending, + transactions_in_future_queue: status.future, + transactions_in_pending_block: block.as_ref().map_or(0, |b| b.transactions().len()), } } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 2b975dcf2..cc7b8ea45 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -236,7 +236,9 @@ impl Eth for EthClient fn block_transaction_count_by_number(&self, params: Params) -> Result { from_params::<(BlockNumber,)>(params) .and_then(|(block_number,)| match block_number { - BlockNumber::Pending => to_value(&U256::from(take_weak!(self.miner).status().block_pending)), + BlockNumber::Pending =>to_value( + &U256::from(take_weak!(self.miner).status().transactions_in_pending_block) + ), _ => to_value(&take_weak!(self.client).block(block_number.into()) .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count()))) }) diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 354e6f507..b50cdfb3f 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -41,9 +41,9 @@ impl MinerService for TestMinerService { /// Returns miner's status. fn status(&self) -> MinerStatus { MinerStatus { - transaction_queue_pending: 0, - transaction_queue_future: 0, - block_pending: 1 + transactions_in_pending_queue: 0, + transactions_in_future_queue: 0, + transactions_in_pending_block: 1 } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index def9ad7f4..f7195a464 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1651,15 +1651,15 @@ mod tests { let mut io = TestIo::new(&mut client, &mut queue, None); // when - sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, true); - assert_eq!(sync.miner.status().transaction_queue_future, 0); - assert_eq!(sync.miner.status().transaction_queue_pending, 1); - sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks, true); + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); + assert_eq!(sync.miner.status().transactions_in_future_queue, 0); + assert_eq!(sync.miner.status().transactions_in_pending_queue, 1); + sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks); // then let status = sync.miner.status(); - assert_eq!(status.transaction_queue_pending, 1); - assert_eq!(status.transaction_queue_future, 0); + assert_eq!(status.transactions_in_pending_queue, 1); + assert_eq!(status.transactions_in_future_queue, 0); } #[test] From df4b326cb3f895d5ded0d19b7732eab21637b85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 13:18:26 +0100 Subject: [PATCH 21/91] Adding missing space --- rpc/src/v1/impls/eth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index cc7b8ea45..848a093eb 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -236,7 +236,7 @@ impl Eth for EthClient fn block_transaction_count_by_number(&self, params: Params) -> Result { from_params::<(BlockNumber,)>(params) .and_then(|(block_number,)| match block_number { - BlockNumber::Pending =>to_value( + BlockNumber::Pending => to_value( &U256::from(take_weak!(self.miner).status().transactions_in_pending_block) ), _ => to_value(&take_weak!(self.client).block(block_number.into()) From fca8eb58107f19899bf212703715966d23fb6835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 15 Mar 2016 23:01:36 +0100 Subject: [PATCH 22/91] Importing transactions from hashset. Notifying about every block --- ethcore/src/client/client.rs | 2 +- miner/src/miner.rs | 34 +++++++++++++++++++++++----------- miner/src/transaction_queue.rs | 10 ++++++++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6ee1b88d5..71823ca00 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -317,7 +317,7 @@ impl Client where V: Verifier { } { - if !imported_blocks.is_empty() && self.block_queue.queue_info().is_empty() { + if !imported_blocks.is_empty() { let (enacted, retracted) = self.calculate_enacted_retracted(import_results); io.send(NetworkIoMessage::User(SyncMessage::NewChainBlocks { imported: imported_blocks, diff --git a/miner/src/miner.rs b/miner/src/miner.rs index ccf45f61a..8272339b9 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -18,6 +18,7 @@ use rayon::prelude::*; use std::sync::{Mutex, RwLock, Arc}; use std::sync::atomic; use std::sync::atomic::AtomicBool; +use std::collections::HashSet; use util::{H256, U256, Address, Bytes, Uint}; use ethcore::views::{BlockView}; @@ -176,21 +177,10 @@ impl MinerService for Miner { let block = BlockView::new(&block); block.transactions() } - { - let in_chain = vec![imported, enacted, invalid]; - let in_chain = in_chain - .par_iter() - .flat_map(|h| h.par_iter().map(|h| fetch_transactions(chain, h))); let out_of_chain = retracted .par_iter() .map(|h| fetch_transactions(chain, h)); - - in_chain.for_each(|txs| { - let mut transaction_queue = self.transaction_queue.lock().unwrap(); - let hashes = txs.iter().map(|tx| tx.hash()).collect::>(); - transaction_queue.remove_all(&hashes, |a| chain.nonce(a)); - }); out_of_chain.for_each(|txs| { // populate sender for tx in &txs { @@ -200,6 +190,28 @@ impl MinerService for Miner { let _ = transaction_queue.add_all(txs, |a| chain.nonce(a)); }); } + // First import all transactions and after that remove old ones + { + let in_chain = { + let mut in_chain = HashSet::new(); + in_chain.extend(imported); + in_chain.extend(enacted); + in_chain.extend(invalid); + in_chain + .into_iter() + .collect::>() + }; + + let in_chain = in_chain + .par_iter() + .map(|h: &H256| fetch_transactions(chain, h)); + + in_chain.for_each(|txs| { + let hashes = txs.iter().map(|tx| tx.hash()).collect::>(); + let mut transaction_queue = self.transaction_queue.lock().unwrap(); + transaction_queue.remove_all(&hashes, |a| chain.nonce(a)); + }); + } if self.sealing_enabled.load(atomic::Ordering::Relaxed) { self.prepare_sealing(chain); diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 324a46364..04febb84d 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -351,6 +351,8 @@ impl TransactionQueue { /// If gap is introduced marks subsequent transactions as future pub fn remove(&mut self, transaction_hash: &H256, fetch_nonce: &T) where T: Fn(&Address) -> U256 { + + println!("Removing transaction: (hash: {:?})", transaction_hash); let transaction = self.by_hash.remove(transaction_hash); if transaction.is_none() { // We don't know this transaction @@ -362,6 +364,8 @@ impl TransactionQueue { let nonce = transaction.nonce(); let current_nonce = fetch_nonce(&sender); + println!("Removing transaction: ({:?}, {:?}, hash: {:?})", sender, nonce, transaction.hash()); + // Remove from future let order = self.future.drop(&sender, &nonce); if order.is_some() { @@ -489,12 +493,14 @@ impl TransactionQueue { fn import_tx(&mut self, tx: VerifiedTransaction, fetch_nonce: &T) where T: Fn(&Address) -> U256 { + if self.by_hash.get(&tx.hash()).is_some() { // Transaction is already imported. trace!(target: "sync", "Dropping already imported transaction with hash: {:?}", tx.hash()); return; } + let address = tx.sender(); let nonce = tx.nonce(); @@ -506,6 +512,7 @@ impl TransactionQueue { // Check height if nonce > next_nonce { + println!("[F] Importing transaction: ({:?}, {:?}, hash: {:?}, gas: {:?})", tx.sender(), tx.nonce(), tx.hash(), tx.transaction.gas_price); // We have a gap - put to future Self::replace_transaction(tx, next_nonce, &mut self.future, &mut self.by_hash); self.future.enforce_limit(&mut self.by_hash); @@ -515,6 +522,7 @@ impl TransactionQueue { trace!(target: "sync", "Dropping transaction with nonce: {} - expecting: {}", nonce, next_nonce); return; } + println!("[C] Importing transaction: ({:?}, {:?}, hash: {:?}, gas: {:?})", tx.sender(), tx.nonce(), tx.hash(), tx.transaction.gas_price); Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash); self.last_nonces.insert(address, nonce); @@ -540,11 +548,13 @@ impl TransactionQueue { let new_fee = order.gas_price; if old_fee.cmp(&new_fee) == Ordering::Greater { // Put back old transaction since it has greater priority (higher gas_price) + println!("Didn't replace tx (h:{:?}, h:{:?})", hash, old.hash); set.by_address.insert(address, nonce, old); // and remove new one set.by_priority.remove(&order); by_hash.remove(&hash); } else { + println!("Replaced h:{:?} with h:{:?}, ", old.hash, hash); // Make sure we remove old transaction entirely set.by_priority.remove(&old); by_hash.remove(&old.hash); From 2e88183df4ea4e1afdbb8d08a660ae40e9440725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 15 Mar 2016 23:13:53 +0100 Subject: [PATCH 23/91] Removing printlns --- miner/src/transaction_queue.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 04febb84d..4b365bba2 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -352,7 +352,6 @@ impl TransactionQueue { pub fn remove(&mut self, transaction_hash: &H256, fetch_nonce: &T) where T: Fn(&Address) -> U256 { - println!("Removing transaction: (hash: {:?})", transaction_hash); let transaction = self.by_hash.remove(transaction_hash); if transaction.is_none() { // We don't know this transaction @@ -364,7 +363,6 @@ impl TransactionQueue { let nonce = transaction.nonce(); let current_nonce = fetch_nonce(&sender); - println!("Removing transaction: ({:?}, {:?}, hash: {:?})", sender, nonce, transaction.hash()); // Remove from future let order = self.future.drop(&sender, &nonce); @@ -512,7 +510,6 @@ impl TransactionQueue { // Check height if nonce > next_nonce { - println!("[F] Importing transaction: ({:?}, {:?}, hash: {:?}, gas: {:?})", tx.sender(), tx.nonce(), tx.hash(), tx.transaction.gas_price); // We have a gap - put to future Self::replace_transaction(tx, next_nonce, &mut self.future, &mut self.by_hash); self.future.enforce_limit(&mut self.by_hash); @@ -522,7 +519,6 @@ impl TransactionQueue { trace!(target: "sync", "Dropping transaction with nonce: {} - expecting: {}", nonce, next_nonce); return; } - println!("[C] Importing transaction: ({:?}, {:?}, hash: {:?}, gas: {:?})", tx.sender(), tx.nonce(), tx.hash(), tx.transaction.gas_price); Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash); self.last_nonces.insert(address, nonce); @@ -548,13 +544,11 @@ impl TransactionQueue { let new_fee = order.gas_price; if old_fee.cmp(&new_fee) == Ordering::Greater { // Put back old transaction since it has greater priority (higher gas_price) - println!("Didn't replace tx (h:{:?}, h:{:?})", hash, old.hash); set.by_address.insert(address, nonce, old); // and remove new one set.by_priority.remove(&order); by_hash.remove(&hash); } else { - println!("Replaced h:{:?} with h:{:?}, ", old.hash, hash); // Make sure we remove old transaction entirely set.by_priority.remove(&old); by_hash.remove(&old.hash); From 74ea9cc74cda3c28a45621a717420b5392195c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 16 Mar 2016 10:40:33 +0100 Subject: [PATCH 24/91] Validating senders balance before importing transaction to queue --- ethcore/src/error.rs | 9 ++- miner/src/lib.rs | 8 +-- miner/src/miner.rs | 20 ++++-- miner/src/transaction_queue.rs | 81 +++++++++++++++-------- rpc/src/v1/impls/eth.rs | 7 +- rpc/src/v1/tests/helpers/miner_service.rs | 5 +- sync/src/chain.rs | 9 ++- 7 files changed, 93 insertions(+), 46 deletions(-) diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 72127c754..482a8de01 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -70,7 +70,14 @@ pub enum TransactionError { /// Minimal expected gas price minimal: U256, /// Transaction gas price - got: U256 + got: U256, + }, + /// Sender doesn't have enough funds to pay for this transaction + InsufficientBalance { + /// Senders balance + balance: U256, + /// Transaction cost + cost: U256, }, /// Transaction's gas limit (aka gas) is invalid. InvalidGasLimit(OutOfBounds), diff --git a/miner/src/lib.rs b/miner/src/lib.rs index 5821c9815..648e9b3b5 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -62,11 +62,11 @@ extern crate rayon; mod miner; mod transaction_queue; -pub use transaction_queue::TransactionQueue; +pub use transaction_queue::{TransactionQueue, AccountDetails}; pub use miner::{Miner}; use std::sync::Mutex; -use util::{H256, U256, Address, Bytes}; +use util::{H256, Address, Bytes}; use ethcore::client::{BlockChainClient}; use ethcore::block::{ClosedBlock}; use ethcore::error::{Error}; @@ -79,8 +79,8 @@ pub trait MinerService : Send + Sync { fn status(&self) -> MinerStatus; /// Imports transactions to transaction queue. - fn import_transactions(&self, transactions: Vec, fetch_nonce: T) -> Result<(), Error> - where T: Fn(&Address) -> U256; + fn import_transactions(&self, transactions: Vec, fetch_account: T) -> Result<(), Error> + where T: Fn(&Address) -> AccountDetails; /// Returns hashes of transactions currently in pending fn pending_transactions_hashes(&self) -> Vec; diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 8272339b9..832dc5d02 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -26,7 +26,7 @@ use ethcore::client::{BlockChainClient, BlockId}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::{Error}; use ethcore::transaction::SignedTransaction; -use super::{MinerService, MinerStatus, TransactionQueue}; +use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails}; /// Keeps track of transactions using priority queue and holds currently mined block. pub struct Miner { @@ -72,7 +72,7 @@ impl Miner { /// Get the extra_data that we will seal blocks wuth. fn gas_floor_target(&self) -> U256 { - self.gas_floor_target.read().unwrap().clone() + *self.gas_floor_target.read().unwrap() } /// Set the author that we will seal blocks as. @@ -113,10 +113,10 @@ impl MinerService for Miner { } } - fn import_transactions(&self, transactions: Vec, fetch_nonce: T) -> Result<(), Error> - where T: Fn(&Address) -> U256 { + fn import_transactions(&self, transactions: Vec, fetch_account: T) -> Result<(), Error> + where T: Fn(&Address) -> AccountDetails { let mut transaction_queue = self.transaction_queue.lock().unwrap(); - transaction_queue.add_all(transactions, fetch_nonce) + transaction_queue.add_all(transactions, fetch_account) } fn pending_transactions_hashes(&self) -> Vec { @@ -187,7 +187,10 @@ impl MinerService for Miner { let _sender = tx.sender(); } let mut transaction_queue = self.transaction_queue.lock().unwrap(); - let _ = transaction_queue.add_all(txs, |a| chain.nonce(a)); + let _ = transaction_queue.add_all(txs, |a| AccountDetails { + nonce: chain.nonce(a), + balance: chain.balance(a) + }); }); } // First import all transactions and after that remove old ones @@ -209,7 +212,10 @@ impl MinerService for Miner { in_chain.for_each(|txs| { let hashes = txs.iter().map(|tx| tx.hash()).collect::>(); let mut transaction_queue = self.transaction_queue.lock().unwrap(); - transaction_queue.remove_all(&hashes, |a| chain.nonce(a)); + transaction_queue.remove_all(&hashes, |a| AccountDetails { + nonce: chain.nonce(a), + balance: chain.balance(a) + }); }); } diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 4b365bba2..ca4a269ae 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -232,8 +232,6 @@ impl TransactionSet { } } -// Will be used when rpc merged -#[allow(dead_code)] #[derive(Debug)] /// Current status of the queue pub struct TransactionQueueStatus { @@ -243,6 +241,14 @@ pub struct TransactionQueueStatus { pub future: usize, } +/// Details of account +pub struct AccountDetails { + /// Most recent account nonce + pub nonce: U256, + /// Current account balance + pub balance: U256, +} + /// TransactionQueue implementation pub struct TransactionQueue { /// Gas Price threshold for transactions that can be imported to this queue (defaults to 0) @@ -308,49 +314,63 @@ impl TransactionQueue { } /// Adds all signed transactions to queue to be verified and imported - pub fn add_all(&mut self, txs: Vec, fetch_nonce: T) -> Result<(), Error> - where T: Fn(&Address) -> U256 { + pub fn add_all(&mut self, txs: Vec, fetch_account: T) -> Result<(), Error> + where T: Fn(&Address) -> AccountDetails { for tx in txs.into_iter() { - try!(self.add(tx, &fetch_nonce)); + try!(self.add(tx, &fetch_account)); } Ok(()) } /// Add signed transaction to queue to be verified and imported - pub fn add(&mut self, tx: SignedTransaction, fetch_nonce: &T) -> Result<(), Error> - where T: Fn(&Address) -> U256 { + pub fn add(&mut self, tx: SignedTransaction, fetch_account: &T) -> Result<(), Error> + where T: Fn(&Address) -> AccountDetails { + + trace!(target: "miner", "Importing: {:?}", tx.hash()); if tx.gas_price < self.minimal_gas_price { - trace!(target: "sync", + trace!(target: "miner", "Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})", tx.hash(), tx.gas_price, self.minimal_gas_price ); return Err(Error::Transaction(TransactionError::InsufficientGasPrice{ minimal: self.minimal_gas_price, - got: tx.gas_price + got: tx.gas_price, })); } - self.import_tx(try!(VerifiedTransaction::new(tx)), fetch_nonce); + let vtx = try!(VerifiedTransaction::new(tx)); + let account = fetch_account(&vtx.sender()); + + if account.balance < vtx.transaction.value { + trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})", + vtx.hash(), account.balance, vtx.transaction.value); + return Err(Error::Transaction(TransactionError::InsufficientBalance { + cost: vtx.transaction.value, + balance: account.balance + })); + } + + self.import_tx(vtx, account.nonce); Ok(()) } /// Removes all transactions identified by hashes given in slice /// /// If gap is introduced marks subsequent transactions as future - pub fn remove_all(&mut self, transaction_hashes: &[H256], fetch_nonce: T) - where T: Fn(&Address) -> U256 { + pub fn remove_all(&mut self, transaction_hashes: &[H256], fetch_account: T) + where T: Fn(&Address) -> AccountDetails { for hash in transaction_hashes { - self.remove(&hash, &fetch_nonce); + self.remove(&hash, &fetch_account); } } /// Removes transaction identified by hashes from queue. /// /// If gap is introduced marks subsequent transactions as future - pub fn remove(&mut self, transaction_hash: &H256, fetch_nonce: &T) - where T: Fn(&Address) -> U256 { + pub fn remove(&mut self, transaction_hash: &H256, fetch_account: &T) + where T: Fn(&Address) -> AccountDetails { let transaction = self.by_hash.remove(transaction_hash); if transaction.is_none() { @@ -361,7 +381,7 @@ impl TransactionQueue { let transaction = transaction.unwrap(); let sender = transaction.sender(); let nonce = transaction.nonce(); - let current_nonce = fetch_nonce(&sender); + let current_nonce = fetch_account(&sender).nonce; // Remove from future @@ -403,6 +423,7 @@ impl TransactionQueue { if k >= current_nonce { self.future.insert(*sender, k, order.update_height(k, current_nonce)); } else { + trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", order.hash, k, current_nonce); // Remove the transaction completely self.by_hash.remove(&order.hash); } @@ -423,6 +444,7 @@ impl TransactionQueue { if k >= current_nonce { self.future.insert(*sender, k, order.update_height(k, current_nonce)); } else { + trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", order.hash, k, current_nonce); self.by_hash.remove(&order.hash); } } @@ -488,13 +510,11 @@ impl TransactionQueue { /// /// It ignores transactions that has already been imported (same `hash`) and replaces the transaction /// iff `(address, nonce)` is the same but `gas_price` is higher. - fn import_tx(&mut self, tx: VerifiedTransaction, fetch_nonce: &T) - where T: Fn(&Address) -> U256 { - + fn import_tx(&mut self, tx: VerifiedTransaction, state_nonce: U256) { if self.by_hash.get(&tx.hash()).is_some() { // Transaction is already imported. - trace!(target: "sync", "Dropping already imported transaction with hash: {:?}", tx.hash()); + trace!(target: "miner", "Dropping already imported transaction: {:?}", tx.hash()); return; } @@ -502,7 +522,6 @@ impl TransactionQueue { let address = tx.sender(); let nonce = tx.nonce(); - let state_nonce = fetch_nonce(&address); let next_nonce = self.last_nonces .get(&address) .cloned() @@ -516,7 +535,7 @@ impl TransactionQueue { return; } else if nonce < state_nonce { // Droping transaction - trace!(target: "sync", "Dropping transaction with nonce: {} - expecting: {}", nonce, next_nonce); + trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", tx.hash(), nonce, next_nonce); return; } @@ -525,6 +544,8 @@ impl TransactionQueue { // But maybe there are some more items waiting in future? self.move_matching_future_to_current(address, nonce + U256::one(), state_nonce); self.current.enforce_limit(&mut self.by_hash); + + trace!(target: "miner", "status: {:?}", self.status()); } /// Replaces transaction in given set (could be `future` or `current`). @@ -583,8 +604,11 @@ mod test { new_unsigned_tx(U256::from(123)).sign(&keypair.secret()) } - fn default_nonce(_address: &Address) -> U256 { - U256::from(123) + fn default_nonce(_address: &Address) -> AccountDetails { + AccountDetails { + nonce: U256::from(123), + balance: !U256::zero() + } } fn new_txs(second_nonce: U256) -> (SignedTransaction, SignedTransaction) { @@ -953,7 +977,8 @@ mod test { #[test] fn should_not_move_to_future_if_state_nonce_is_higher() { // given - let next_nonce = |a: &Address| default_nonce(a) + U256::one(); + let next_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce + U256::one(), balance: + !U256::zero() }; let mut txq = TransactionQueue::new(); let (tx, tx2) = new_txs(U256::from(1)); let tx3 = new_tx(); @@ -1028,8 +1053,10 @@ mod test { #[test] fn should_recalculate_height_when_removing_from_future() { // given - let previous_nonce = |a: &Address| default_nonce(a) - U256::one(); - let next_nonce = |a: &Address| default_nonce(a) + U256::one(); + let previous_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce - U256::one(), balance: + !U256::zero() }; + let next_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce + U256::one(), balance: + !U256::zero() }; let mut txq = TransactionQueue::new(); let (tx1, tx2) = new_txs(U256::one()); txq.add(tx1.clone(), &previous_nonce).unwrap(); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 848a093eb..24863a281 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -19,7 +19,7 @@ use std::collections::HashSet; use std::sync::{Arc, Weak, Mutex}; use std::ops::Deref; use ethsync::{SyncProvider, SyncState}; -use ethminer::{MinerService}; +use ethminer::{MinerService, AccountDetails}; use jsonrpc_core::*; use util::numbers::*; use util::sha3::*; @@ -381,7 +381,10 @@ impl Eth for EthClient let signed_transaction = transaction.sign(&secret); let hash = signed_transaction.hash(); - let import = miner.import_transactions(vec![signed_transaction], |a: &Address| client.nonce(a)); + let import = miner.import_transactions(vec![signed_transaction], |a: &Address| AccountDetails { + nonce: client.nonce(a), + balance: client.balance(a) + }); match import { Ok(_) => to_value(&hash), Err(e) => { diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index b50cdfb3f..561fcb518 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -20,7 +20,7 @@ use ethcore::error::Error; use ethcore::client::BlockChainClient; use ethcore::block::ClosedBlock; use ethcore::transaction::SignedTransaction; -use ethminer::{MinerService, MinerStatus}; +use ethminer::{MinerService, MinerStatus, AccountDetails}; pub struct TestMinerService { pub imported_transactions: RwLock>, @@ -48,7 +48,8 @@ impl MinerService for TestMinerService { } /// Imports transactions to transaction queue. - fn import_transactions(&self, _transactions: Vec, _fetch_nonce: T) -> Result<(), Error> where T: Fn(&Address) -> U256 { unimplemented!(); } + fn import_transactions(&self, _transactions: Vec, _fetch_account: T) -> Result<(), Error> + where T: Fn(&Address) -> AccountDetails { unimplemented!(); } /// Returns hashes of transactions currently in pending fn pending_transactions_hashes(&self) -> Vec { unimplemented!(); } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index f7195a464..b85a7e986 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -38,7 +38,7 @@ use range_collection::{RangeCollection, ToUsize, FromUsize}; use ethcore::error::*; use ethcore::transaction::SignedTransaction; use ethcore::block::Block; -use ethminer::{Miner, MinerService}; +use ethminer::{Miner, MinerService, AccountDetails}; use io::SyncIo; use time; use super::SyncConfig; @@ -961,8 +961,11 @@ impl ChainSync { transactions.push(tx); } let chain = io.chain(); - let fetch_nonce = |a: &Address| chain.nonce(a); - let _ = self.miner.import_transactions(transactions, fetch_nonce); + let fetch_account = |a: &Address| AccountDetails { + nonce: chain.nonce(a), + balance: chain.balance(a) + }; + let _ = self.miner.import_transactions(transactions, fetch_account); Ok(()) } From 3a16ef19c1ddd34adc532c466627c30797d71a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 16 Mar 2016 10:48:31 +0100 Subject: [PATCH 25/91] Removing unused import --- rpc/src/v1/tests/helpers/miner_service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 561fcb518..44b94ac14 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::{Address, H256, U256, Bytes}; +use util::{Address, H256, Bytes}; use util::standard::*; use ethcore::error::Error; use ethcore::client::BlockChainClient; From 164cd268ad34a71580270771a426d045570e8853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 16 Mar 2016 16:47:36 +0100 Subject: [PATCH 26/91] Fixing build --- miner/src/transaction_queue.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index ca4a269ae..abd862a02 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -777,8 +777,10 @@ mod test { #[test] fn should_correctly_update_futures_when_removing() { // given - let prev_nonce = |a: &Address| default_nonce(a) - U256::one(); - let next2_nonce = |a: &Address| default_nonce(a) + U256::from(2); + let prev_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce - U256::one(), balance: + !U256::zero() }; + let next2_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce + U256::from(2), balance: + !U256::zero() }; let mut txq = TransactionQueue::new(); @@ -923,7 +925,7 @@ mod test { let mut txq = TransactionQueue::new(); let tx = new_tx(); let last_nonce = tx.nonce + U256::one(); - let fetch_last_nonce = |_a: &Address| last_nonce; + let fetch_last_nonce = |_a: &Address| AccountDetails{ nonce: last_nonce, balance: !U256::zero() }; // when txq.add(tx, &fetch_last_nonce).unwrap(); @@ -937,7 +939,8 @@ mod test { #[test] fn should_not_insert_same_transaction_twice() { // given - let nonce = |a: &Address| default_nonce(a) + U256::one(); + let nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce + U256::one(), + balance: !U256::zero() }; let mut txq = TransactionQueue::new(); let (_tx1, tx2) = new_txs(U256::from(1)); txq.add(tx2.clone(), &default_nonce).unwrap(); @@ -977,7 +980,7 @@ mod test { #[test] fn should_not_move_to_future_if_state_nonce_is_higher() { // given - let next_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce + U256::one(), balance: + let next_nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce + U256::one(), balance: !U256::zero() }; let mut txq = TransactionQueue::new(); let (tx, tx2) = new_txs(U256::from(1)); From b0d7d483916ca3e6c8821b2c1a625c0c3b4dd9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 16 Mar 2016 17:17:49 +0100 Subject: [PATCH 27/91] Adding test --- miner/src/transaction_queue.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index abd862a02..480d6550a 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -34,7 +34,7 @@ //! use util::crypto::KeyPair; //! use util::hash::Address; //! use util::numbers::{Uint, U256}; -//! use ethminer::TransactionQueue; +//! use ethminer::{TransactionQueue, AccountDetails}; //! use ethcore::transaction::*; //! use rustc_serialize::hex::FromHex; //! @@ -47,7 +47,10 @@ //! //! let st1 = t1.sign(&key.secret()); //! let st2 = t2.sign(&key.secret()); -//! let default_nonce = |_a: &Address| U256::from(10); +//! let default_nonce = |_a: &Address| AccountDetails { +//! nonce: U256::from(10), +//! balance: U256::from(10_000), +//! }; //! //! let mut txq = TransactionQueue::new(); //! txq.add(st2.clone(), &default_nonce); @@ -677,6 +680,25 @@ mod test { assert_eq!(stats.pending, 1); } + #[test] + fn should_drop_transactions_from_senders_without_balance() { + // given + let mut txq = TransactionQueue::new(); + let tx = new_tx(); + let account = |a: &Address| AccountDetails { + nonce: default_nonce(a).nonce, + balance: U256::one() + }; + + // when + txq.add(tx, &account).unwrap_err(); + + // then + let stats = txq.status(); + assert_eq!(stats.pending, 0); + assert_eq!(stats.future, 0); + } + #[test] fn should_not_import_transaction_below_min_gas_price_threshold() { // given From 4be4a1c151626d3febe240b6bbe1eba09f91a987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 10:20:35 +0100 Subject: [PATCH 28/91] Fixing sync test --- sync/src/chain.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index b85a7e986..11330ec01 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1320,6 +1320,7 @@ mod tests { use ::SyncConfig; use util::*; use super::{PeerInfo, PeerAsking}; + use ethcore::views::BlockView; use ethcore::header::*; use ethcore::client::*; use ethminer::{Miner, MinerService}; @@ -1650,6 +1651,13 @@ mod tests { let good_blocks = vec![client.block_hash_delta_minus(2)]; let retracted_blocks = vec![client.block_hash_delta_minus(1)]; + // Add some balance to clients + for h in vec![good_blocks[0], retracted_blocks[0]] { + let block = client.block(BlockId::Hash(h)).unwrap(); + let view = BlockView::new(&block); + client.set_balance(view.transactions()[0].sender().unwrap(), U256::from(10_000)); + } + let mut queue = VecDeque::new(); let mut io = TestIo::new(&mut client, &mut queue, None); From d17c629b71f0ce6cfed61f77f6a932d6dab9c623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 10:23:09 +0100 Subject: [PATCH 29/91] Full transaction cost --- miner/src/transaction_queue.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 480d6550a..1842f5f35 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -343,14 +343,16 @@ impl TransactionQueue { })); } + let vtx = try!(VerifiedTransaction::new(tx)); let account = fetch_account(&vtx.sender()); - if account.balance < vtx.transaction.value { + let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas; + if account.balance < cost { trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})", - vtx.hash(), account.balance, vtx.transaction.value); + vtx.hash(), account.balance, cost); return Err(Error::Transaction(TransactionError::InsufficientBalance { - cost: vtx.transaction.value, + cost: cost, balance: account.balance })); } From b79c7f05c01d95c0a5e84293ef8d8b85e7727cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 11:27:38 +0100 Subject: [PATCH 30/91] Increasing balance in tests --- sync/src/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 11330ec01..4993c281d 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1655,7 +1655,7 @@ mod tests { for h in vec![good_blocks[0], retracted_blocks[0]] { let block = client.block(BlockId::Hash(h)).unwrap(); let view = BlockView::new(&block); - client.set_balance(view.transactions()[0].sender().unwrap(), U256::from(10_000)); + client.set_balance(view.transactions()[0].sender().unwrap(), U256::from(1_000_000_000)); } let mut queue = VecDeque::new(); From 180debb2600e268288e1977f14c23f8bb7119000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 11:47:41 +0100 Subject: [PATCH 31/91] Reverting check if block queue is empty --- ethcore/src/client/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 71823ca00..6ee1b88d5 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -317,7 +317,7 @@ impl Client where V: Verifier { } { - if !imported_blocks.is_empty() { + if !imported_blocks.is_empty() && self.block_queue.queue_info().is_empty() { let (enacted, retracted) = self.calculate_enacted_retracted(import_results); io.send(NetworkIoMessage::User(SyncMessage::NewChainBlocks { imported: imported_blocks, From 2f8e6be2ea8a4a6f287980906d41d259046fcad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 11:49:56 +0100 Subject: [PATCH 32/91] Adding missing commas --- rpc/src/v1/impls/eth.rs | 2 +- sync/src/chain.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 24863a281..7ecfb86de 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -383,7 +383,7 @@ impl Eth for EthClient let import = miner.import_transactions(vec![signed_transaction], |a: &Address| AccountDetails { nonce: client.nonce(a), - balance: client.balance(a) + balance: client.balance(a), }); match import { Ok(_) => to_value(&hash), diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 4993c281d..238f55e76 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -963,7 +963,7 @@ impl ChainSync { let chain = io.chain(); let fetch_account = |a: &Address| AccountDetails { nonce: chain.nonce(a), - balance: chain.balance(a) + balance: chain.balance(a), }; let _ = self.miner.import_transactions(transactions, fetch_account); Ok(()) From 56e977b425ad953301b9821a22b3c91c002d77f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 12:23:15 +0100 Subject: [PATCH 33/91] Fixing doctest --- miner/src/transaction_queue.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 1842f5f35..a1fc20b0f 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -49,12 +49,12 @@ //! let st2 = t2.sign(&key.secret()); //! let default_nonce = |_a: &Address| AccountDetails { //! nonce: U256::from(10), -//! balance: U256::from(10_000), +//! balance: U256::from(1_000_000), //! }; //! //! let mut txq = TransactionQueue::new(); -//! txq.add(st2.clone(), &default_nonce); -//! txq.add(st1.clone(), &default_nonce); +//! txq.add(st2.clone(), &default_nonce).unwrap(); +//! txq.add(st1.clone(), &default_nonce).unwrap(); //! //! // Check status //! assert_eq!(txq.status().pending, 2); From 3847f8a9fca795647677961de559ed2660c2d34b Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 17 Mar 2016 14:56:19 +0100 Subject: [PATCH 34/91] no flag also --- ethcore/src/client/client.rs | 1 - ethcore/src/service.rs | 2 -- sync/src/chain.rs | 19 +++++++------------ sync/src/io.rs | 4 ++++ sync/src/lib.rs | 4 ++-- sync/src/tests/helpers.rs | 2 +- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6ee1b88d5..caa92db97 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -324,7 +324,6 @@ impl Client where V: Verifier { invalid: invalid_blocks, enacted: enacted, retracted: retracted, - is_last: self.queue_info().is_empty() })).unwrap(); } } diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index a46581e3c..bcfe7724f 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -35,8 +35,6 @@ pub enum SyncMessage { retracted: Vec, /// Hashes of blocks that are now included in cannonical chain enacted: Vec, - /// Set when blockqueue is empty - is_last: bool, }, /// Best Block Hash in chain has been changed NewChainHead, diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 238f55e76..0488ceed6 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -215,8 +215,6 @@ pub struct ChainSync { network_id: U256, /// Miner miner: Arc, - /// Fully-synced flag - is_fully_synced: bool, } type RlpResponseResult = Result, PacketDecodeError>; @@ -243,7 +241,6 @@ impl ChainSync { max_download_ahead_blocks: max(MAX_HEADERS_TO_REQUEST, config.max_download_ahead_blocks), network_id: config.network_id, miner: miner, - is_fully_synced: true, } } @@ -948,7 +945,7 @@ impl ChainSync { /// Called when peer sends us new transactions fn on_peer_transactions(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { // accepting transactions once only fully synced - if !self.is_fully_synced { + if !io.is_chain_queue_empty() { return Ok(()); } @@ -1296,10 +1293,8 @@ impl ChainSync { } /// called when block is imported to chain, updates transactions queue and propagates the blocks - pub fn chain_new_blocks(&mut self, io: &mut SyncIo, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256], is_last: bool) { - // Set the state in which it can accept transactions from the net - self.is_fully_synced = is_last; - if self.is_fully_synced { + pub fn chain_new_blocks(&mut self, io: &mut SyncIo, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]) { + if io.is_chain_queue_empty() { // Notify miner self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); } @@ -1689,10 +1684,10 @@ mod tests { let mut io = TestIo::new(&mut client, &mut queue, None); // when - sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, false); - assert_eq!(sync.miner.status().transaction_queue_future, 0); - assert_eq!(sync.miner.status().transaction_queue_pending, 0); - sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks, false); + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); + assert_eq!(sync.miner.status().transactions_in_future_queue, 0); + assert_eq!(sync.miner.status().transactions_in_pending_queue, 0); + sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks); // then let status = sync.miner.status(); diff --git a/sync/src/io.rs b/sync/src/io.rs index 00ee49be4..84697a021 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -37,6 +37,10 @@ pub trait SyncIo { fn peer_info(&self, peer_id: PeerId) -> String { peer_id.to_string() } + /// Returns if the chain block queue empty + fn is_chain_queue_empty(&self) -> bool { + self.chain().queue_info().is_empty() + } } /// Wraps `NetworkContext` and the blockchain client diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 8ab6a23e9..a4f6eff38 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -166,9 +166,9 @@ impl NetworkProtocolHandler for EthSync { fn message(&self, io: &NetworkContext, message: &SyncMessage) { match *message { - SyncMessage::NewChainBlocks { ref imported, ref invalid, ref enacted, ref retracted, is_last } => { + SyncMessage::NewChainBlocks { ref imported, ref invalid, ref enacted, ref retracted } => { let mut sync_io = NetSyncIo::new(io, self.chain.deref()); - self.sync.write().unwrap().chain_new_blocks(&mut sync_io, imported, invalid, enacted, retracted, is_last); + self.sync.write().unwrap().chain_new_blocks(&mut sync_io, imported, invalid, enacted, retracted); }, SyncMessage::NewChainHead => { let mut sync_io = NetSyncIo::new(io, self.chain.deref()); diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 42ef728b9..b3e62ccc6 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -168,6 +168,6 @@ impl TestNet { pub fn trigger_chain_new_blocks(&mut self, peer_id: usize) { let mut peer = self.peer_mut(peer_id); - peer.sync.chain_new_blocks(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None), &[], &[], &[], &[], true); + peer.sync.chain_new_blocks(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None), &[], &[], &[], &[]); } } From 7acdc80b2753b794729aa512fb28461c624edb27 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 17 Mar 2016 15:02:18 +0100 Subject: [PATCH 35/91] propagation is out --- sync/src/chain.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 0488ceed6..501964251 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1297,9 +1297,9 @@ impl ChainSync { if io.is_chain_queue_empty() { // Notify miner self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); + // Propagate latests blocks + self.propagate_latest_blocks(io); } - // Propagate latests blocks - self.propagate_latest_blocks(io); // TODO [todr] propagate transactions? } From 7371beb26c910344e6342b550ef793f2a8f7a254 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 17 Mar 2016 15:09:08 +0100 Subject: [PATCH 36/91] get rid of the function --- sync/src/chain.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 501964251..8bb0c7c80 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -625,13 +625,6 @@ impl ChainSync { self.state = SyncState::Waiting; } - fn can_sync(&self) -> bool { - match self.state { - SyncState::Idle | SyncState::NotSynced => true, - _ => false - } - } - /// Find something to do for a peer. Called for a new peer or when a peer is done with it's task. fn sync_peer(&mut self, io: &mut SyncIo, peer_id: PeerId, force: bool) { let (peer_latest, peer_difficulty) = { @@ -651,7 +644,7 @@ impl ChainSync { if force || peer_difficulty > syncing_difficulty { // start sync self.syncing_difficulty = peer_difficulty; - if self.can_sync() { + if self.state == SyncState::Idle || self.state == SyncState::NotSynced { self.state = SyncState::Blocks; } trace!(target: "sync", "Starting sync with better chain"); From 6c81f1fb7489ab5c2ff3205e4003f80c68346add Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 17 Mar 2016 18:41:55 +0100 Subject: [PATCH 37/91] Prettier version wo git dir; Use rustc compile time version --- util/build.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/util/build.rs b/util/build.rs index 1ec89f704..f033e52e0 100644 --- a/util/build.rs +++ b/util/build.rs @@ -26,12 +26,12 @@ use std::path::Path; fn main() { vergen(OutputFns::all()).unwrap(); let out_dir = env::var("OUT_DIR").unwrap(); - let dest_path = Path::new(&out_dir).join("rustc_version.rs"); - let mut f = File::create(&dest_path).unwrap(); + let dest_path = Path::new(&out_dir).join("rustc_version.rs"); + let mut f = File::create(&dest_path).unwrap(); f.write_all(format!(" /// Returns compiler version. - pub fn rustc_version() -> &'static str {{ + pub fn rustc_version() -> &'static str {{ \"{}\" - }} - ", rustc_version::version()).as_bytes()).unwrap(); + }} + ", rustc_version::version()).as_bytes()).unwrap(); } From 9b6abb5861386c3e393d7decdd7416cf2d22d44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 13:41:08 +0100 Subject: [PATCH 38/91] Attempting to add all transactions to mined block --- miner/src/miner.rs | 5 +---- miner/src/transaction_queue.rs | 17 ++++++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 832dc5d02..7bbde6294 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -125,10 +125,7 @@ impl MinerService for Miner { } fn prepare_sealing(&self, chain: &BlockChainClient) { - let no_of_transactions = 128; - // TODO: should select transactions orm queue according to gas limit of block. - let transactions = self.transaction_queue.lock().unwrap().top_transactions(no_of_transactions); - + let transactions = self.transaction_queue.lock().unwrap().top_transactions(); let b = chain.prepare_sealing( self.author(), self.gas_floor_target(), diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index a1fc20b0f..71d845e38 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -59,7 +59,7 @@ //! // Check status //! assert_eq!(txq.status().pending, 2); //! // Check top transactions -//! let top = txq.top_transactions(3); +//! let top = txq.top_transactions(); //! assert_eq!(top.len(), 2); //! assert_eq!(top[0], st1); //! assert_eq!(top[1], st2); @@ -69,7 +69,7 @@ //! txq.remove(&st1.hash(), &default_nonce); //! assert_eq!(txq.status().pending, 0); //! assert_eq!(txq.status().future, 1); -//! assert_eq!(txq.top_transactions(3).len(), 0); +//! assert_eq!(txq.top_transactions().len(), 0); //! } //! ``` //! @@ -459,10 +459,9 @@ impl TransactionQueue { // Will be used when mining merged #[allow(dead_code)] /// Returns top transactions from the queue ordered by priority. - pub fn top_transactions(&self, size: usize) -> Vec { + pub fn top_transactions(&self) -> Vec { self.current.by_priority .iter() - .take(size) .map(|t| self.by_hash.get(&t.hash).expect("Transaction Queue Inconsistency")) .map(|t| t.transaction.clone()) .collect() @@ -754,7 +753,7 @@ mod test { txq.add(tx2.clone(), &default_nonce).unwrap(); // then - let top = txq.top_transactions(5); + let top = txq.top_transactions(); assert_eq!(top[0], tx); assert_eq!(top[1], tx2); assert_eq!(top.len(), 2); @@ -793,7 +792,7 @@ mod test { let stats = txq.status(); assert_eq!(stats.pending, 1); assert_eq!(stats.future, 1); - let top = txq.top_transactions(5); + let top = txq.top_transactions(); assert_eq!(top.len(), 1); assert_eq!(top[0], tx); } @@ -920,7 +919,7 @@ mod test { txq.add(tx2.clone(), &default_nonce).unwrap(); // then - let t = txq.top_transactions(2); + let t = txq.top_transactions(); assert_eq!(txq.status().pending, 1); assert_eq!(t.len(), 1); assert_eq!(t[0], tx); @@ -1044,7 +1043,7 @@ mod test { let stats = txq.status(); assert_eq!(stats.pending, 1); assert_eq!(stats.future, 0); - assert_eq!(txq.top_transactions(1)[0].gas_price, U256::from(200)); + assert_eq!(txq.top_transactions()[0].gas_price, U256::from(200)); } #[test] @@ -1074,7 +1073,7 @@ mod test { let stats = txq.status(); assert_eq!(stats.future, 0); assert_eq!(stats.pending, 2); - assert_eq!(txq.top_transactions(2)[1].gas_price, U256::from(200)); + assert_eq!(txq.top_transactions()[1].gas_price, U256::from(200)); } #[test] From 144385e67dc0eed7c27a382b34ecb602baec9f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 09:54:05 +0100 Subject: [PATCH 39/91] Bumping clippy --- Cargo.lock | 29 +++++++++++++++++------------ Cargo.toml | 2 +- ethcore/Cargo.toml | 2 +- json/Cargo.toml | 2 +- miner/Cargo.toml | 2 +- rpc/Cargo.toml | 2 +- sync/Cargo.toml | 2 +- util/Cargo.toml | 2 +- 8 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbaa92e9e..de71889bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ name = "parity" version = "1.0.0" dependencies = [ - "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.54 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/tomusdrw/rust-ctrlc.git)", "daemonize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.78 (registry+https://github.com/rust-lang/crates.io-index)", @@ -95,11 +95,12 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.50" +version = "0.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex-syntax 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -208,7 +209,7 @@ dependencies = [ name = "ethcore" version = "1.0.0" dependencies = [ - "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.54 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.0.0", @@ -235,6 +236,7 @@ name = "ethcore-rpc" version = "1.0.0" dependencies = [ "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.54 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.0.0", "ethcore 1.0.0", "ethcore-util 1.0.0", @@ -258,7 +260,7 @@ dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 0.1.0", "chrono 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.54 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -302,7 +304,7 @@ dependencies = [ name = "ethminer" version = "1.0.0" dependencies = [ - "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.54 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.0.0", "ethcore-util 1.0.0", @@ -316,7 +318,7 @@ dependencies = [ name = "ethsync" version = "1.0.0" dependencies = [ - "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.54 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.0.0", "ethcore-util 1.0.0", @@ -708,11 +710,6 @@ dependencies = [ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex-syntax" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex-syntax" version = "0.3.0" @@ -894,6 +891,14 @@ name = "tiny-keccak" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "toml" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "traitobject" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index 0e2e0ce8a..68cb3a504 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ fdlimit = { path = "util/fdlimit" } daemonize = "0.2" number_prefix = "0.2" rpassword = "0.1" -clippy = { version = "0.0.50", optional = true } +clippy = { version = "0.0.54", optional = true } ethcore = { path = "ethcore" } ethcore-util = { path = "util" } ethsync = { path = "sync" } diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 77fd0e654..21e09655e 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -17,7 +17,7 @@ ethcore-util = { path = "../util" } evmjit = { path = "../evmjit", optional = true } ethash = { path = "../ethash" } num_cpus = "0.2" -clippy = { version = "0.0.50", optional = true } +clippy = { version = "0.0.54", optional = true } crossbeam = "0.1.5" lazy_static = "0.1" ethcore-devtools = { path = "../devtools" } diff --git a/json/Cargo.toml b/json/Cargo.toml index 61599c331..91f8b8431 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -10,7 +10,7 @@ rustc-serialize = "0.3" serde = "0.7.0" serde_json = "0.7.0" serde_macros = { version = "0.7.0", optional = true } -clippy = { version = "0.0.50", optional = true } +clippy = { version = "0.0.54", optional = true } [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } diff --git a/miner/Cargo.toml b/miner/Cargo.toml index 1cee23457..1afa79bae 100644 --- a/miner/Cargo.toml +++ b/miner/Cargo.toml @@ -17,7 +17,7 @@ log = "0.3" env_logger = "0.3" rustc-serialize = "0.3" rayon = "0.3.1" -clippy = { version = "0.0.50", optional = true } +clippy = { version = "0.0.54", optional = true } [features] default = [] diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 6e7efb31c..1e8174660 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -22,7 +22,7 @@ ethminer = { path = "../miner" } rustc-serialize = "0.3" transient-hashmap = "0.1" serde_macros = { version = "0.7.0", optional = true } -clippy = { version = "0.0.50", optional = true } +clippy = { version = "0.0.54", optional = true } [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } diff --git a/sync/Cargo.toml b/sync/Cargo.toml index ae268e010..635916bf3 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Ethcore Date: Fri, 18 Mar 2016 10:14:19 +0100 Subject: [PATCH 40/91] Fixing warnings --- ethcore/src/evm/ext.rs | 1 + ethcore/src/evm/interpreter.rs | 1 + parity/main.rs | 3 ++- util/src/journaldb/archivedb.rs | 4 +++- util/src/journaldb/earlymergedb.rs | 2 ++ util/src/journaldb/overlayrecentdb.rs | 2 ++ util/src/journaldb/refcounteddb.rs | 10 ++++++---- util/src/misc.rs | 2 +- util/src/network/ip_utils.rs | 6 ++++-- 9 files changed, 22 insertions(+), 9 deletions(-) diff --git a/ethcore/src/evm/ext.rs b/ethcore/src/evm/ext.rs index f4172f10a..4986b12c8 100644 --- a/ethcore/src/evm/ext.rs +++ b/ethcore/src/evm/ext.rs @@ -67,6 +67,7 @@ pub trait Ext { /// Returns Err, if we run out of gas. /// Otherwise returns call_result which contains gas left /// and true if subcall was successfull. + #[cfg_attr(feature="dev", allow(too_many_arguments))] fn call(&mut self, gas: &U256, sender_address: &Address, diff --git a/ethcore/src/evm/interpreter.rs b/ethcore/src/evm/interpreter.rs index 7491321cb..b29fc0d41 100644 --- a/ethcore/src/evm/interpreter.rs +++ b/ethcore/src/evm/interpreter.rs @@ -521,6 +521,7 @@ impl Interpreter { Ok(overflowing!(offset.overflowing_add(size.clone()))) } + #[cfg_attr(feature="dev", allow(too_many_arguments))] fn exec_instruction(&self, gas: Gas, params: &ActionParams, diff --git a/parity/main.rs b/parity/main.rs index b8cc2a0f0..c7e534993 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -370,7 +370,7 @@ impl Configuration { fn init_nodes(&self, spec: &Spec) -> Vec { match self.args.flag_bootnodes { - Some(ref x) if x.len() > 0 => x.split(',').map(|s| { + Some(ref x) if !x.is_empty() => x.split(',').map(|s| { Self::normalize_enode(s).unwrap_or_else(|| { die!("{}: Invalid node address format given for a boot node.", s) }) @@ -409,6 +409,7 @@ impl Configuration { ret } + #[cfg_attr(feature="dev", allow(useless_format))] fn client_config(&self) -> ClientConfig { let mut client_config = ClientConfig::default(); match self.args.flag_cache { diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index 83a80b7c2..76f0ecc50 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -175,6 +175,8 @@ impl JournalDB for ArchiveDB { #[cfg(test)] mod tests { + #![cfg_attr(feature="dev", allow(blacklisted_name))] + use common::*; use super::*; use hashdb::*; @@ -371,7 +373,7 @@ mod tests { jdb.commit(5, &b"5".sha3(), Some((4, b"4".sha3()))).unwrap(); } } - + #[test] fn reopen_fork() { let mut dir = ::std::env::temp_dir(); diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index 7cb00b993..15dcacd6a 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -527,6 +527,8 @@ impl JournalDB for EarlyMergeDB { #[cfg(test)] mod tests { + #![cfg_attr(feature="dev", allow(blacklisted_name))] + use common::*; use super::*; use super::super::traits::JournalDB; diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index efbd26c3b..102e23407 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -358,6 +358,8 @@ impl HashDB for OverlayRecentDB { #[cfg(test)] mod tests { + #![cfg_attr(feature="dev", allow(blacklisted_name))] + use common::*; use super::*; use hashdb::*; diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index 590964247..a8c3ff12b 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -28,7 +28,7 @@ use std::env; /// Implementation of the HashDB trait for a disk-backed database with a memory overlay /// and latent-removal semantics. /// -/// Like OverlayDB, there is a memory overlay; `commit()` must be called in order to +/// Like OverlayDB, there is a memory overlay; `commit()` must be called in order to /// write operations out to disk. Unlike OverlayDB, `remove()` operations do not take effect /// immediately. Rather some age (based on a linear but arbitrary metric) must pass before /// the removals actually take effect. @@ -113,7 +113,7 @@ impl JournalDB for RefCountedDB { } fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result { - // journal format: + // journal format: // [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ] // [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ] // [era, n] => [ ... ] @@ -121,7 +121,7 @@ impl JournalDB for RefCountedDB { // TODO: store last_era, reclaim_period. // when we make a new commit, we journal the inserts and removes. - // for each end_era that we journaled that we are no passing by, + // for each end_era that we journaled that we are no passing by, // we remove all of its removes assuming it is canonical and all // of its inserts otherwise. @@ -147,7 +147,7 @@ impl JournalDB for RefCountedDB { r.append(&self.inserts); r.append(&self.removes); try!(batch.put(&last, r.as_raw())); - + trace!(target: "rcdb", "new journal for time #{}.{} => {}: inserts={:?}, removes={:?}", now, index, id, self.inserts, self.removes); self.inserts.clear(); @@ -194,6 +194,8 @@ impl JournalDB for RefCountedDB { #[cfg(test)] mod tests { + #![cfg_attr(feature="dev", allow(blacklisted_name))] + use common::*; use super::*; use super::super::traits::JournalDB; diff --git a/util/src/misc.rs b/util/src/misc.rs index 14fcf522a..190cb4130 100644 --- a/util/src/misc.rs +++ b/util/src/misc.rs @@ -88,7 +88,7 @@ pub fn version_data() -> Bytes { u32::from_str(env!("CARGO_PKG_VERSION_PATCH")).unwrap(); s.append(&v); s.append(&"Parity"); - s.append(&format!("{}", rustc_version())); + s.append(&rustc_version()); s.append(&&Target::os()[0..2]); s.out() } diff --git a/util/src/network/ip_utils.rs b/util/src/network/ip_utils.rs index 9696c601d..b37a47064 100644 --- a/util/src/network/ip_utils.rs +++ b/util/src/network/ip_utils.rs @@ -42,7 +42,7 @@ impl SocketAddrExt for Ipv4Addr { fn is_global_s(&self) -> bool { !self.is_private() && !self.is_loopback() && !self.is_link_local() && - !self.is_broadcast() && !self.is_documentation() + !self.is_broadcast() && !self.is_documentation() } } @@ -216,6 +216,8 @@ fn can_map_external_address_or_fail() { #[test] fn ipv4_properties() { + + #![cfg_attr(feature="dev", allow(too_many_arguments))] fn check(octets: &[u8; 4], unspec: bool, loopback: bool, private: bool, link_local: bool, global: bool, multicast: bool, broadcast: bool, documentation: bool) { @@ -262,7 +264,7 @@ fn ipv6_properties() { assert_eq!(ip.is_global_s(), global); } - // unspec loopbk global + // unspec loopbk global check("::", true, false, true); check("::1", false, true, false); } From 5aed421fa353d468c038cd5ae4b41d4efd1680c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 10:22:00 +0100 Subject: [PATCH 41/91] Removing allow dead_code --- miner/src/transaction_queue.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 71d845e38..0f2ec6ec7 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -306,8 +306,6 @@ impl TransactionQueue { self.minimal_gas_price = min_gas_price; } - // Will be used when rpc merged - #[allow(dead_code)] /// Returns current status for this queue pub fn status(&self) -> TransactionQueueStatus { TransactionQueueStatus { @@ -456,8 +454,6 @@ impl TransactionQueue { self.future.enforce_limit(&mut self.by_hash); } - // Will be used when mining merged - #[allow(dead_code)] /// Returns top transactions from the queue ordered by priority. pub fn top_transactions(&self) -> Vec { self.current.by_priority From 1f363b22fcd61ee5d4540be07f4b500021453cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 12:17:20 +0100 Subject: [PATCH 42/91] Removing invalid transactions from queue --- ethcore/src/client/client.rs | 31 ++++++++++++++++++++++++++----- ethcore/src/client/mod.rs | 4 +++- ethcore/src/client/test_client.rs | 2 +- ethcore/src/tests/client.rs | 2 +- miner/src/miner.rs | 15 ++++++++++++++- 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index caa92db97..7818fcdc8 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -391,7 +391,8 @@ impl BlockChainClient for Client where V: Verifier { } // TODO [todr] Should be moved to miner crate eventually. - fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> Option { + fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) + -> Option<(ClosedBlock, HashSet)> { let engine = self.engine.deref().deref(); let h = self.chain.best_block_hash(); @@ -417,21 +418,41 @@ impl BlockChainClient for Client where V: Verifier { // Add transactions let block_number = b.block().header().number(); + let gas_limit = *b.block().header().gas_limit(); + let mut gas_left = gas_limit; + let mut invalid_transactions = HashSet::new(); + for tx in transactions { + let hash = tx.hash(); + let gas = tx.gas; + // TODO [todr] It seems that calculating gas_left here doesn't really look nice. After moving this function + // to miner crate we should consider rewriting this logic in some better way. + if gas > gas_left { + trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash); + continue; + } + let import = b.push_transaction(tx, None); - if let Err(e) = import { - trace!("Error adding transaction to block: number={}. Error: {:?}", block_number, e); + match import { + Err(e) => { + trace!(target: "miner", "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}", + block_number, hash, e); + invalid_transactions.insert(hash); + }, + Ok(receipt) => { + gas_left = gas_limit - receipt.gas_used; + } } } // And close let b = b.close(); - trace!("Sealing: number={}, hash={}, diff={}", + trace!(target: "miner", "Sealing: number={}, hash={}, diff={}", b.block().header().number(), b.hash(), b.block().header().difficulty() ); - Some(b) + Some((b, invalid_transactions)) } fn block_header(&self, id: BlockId) -> Option { diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 88e07d0b1..198e918f7 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -26,6 +26,7 @@ pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig}; pub use self::ids::{BlockId, TransactionId}; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; +use std::collections::HashSet; use util::bytes::Bytes; use util::hash::{Address, H256, H2048}; use util::numbers::U256; @@ -110,7 +111,8 @@ pub trait BlockChainClient : Sync + Send { // TODO [todr] Should be moved to miner crate eventually. /// Returns ClosedBlock prepared for sealing. - fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> Option; + fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) + -> Option<(ClosedBlock, HashSet)>; // TODO [todr] Should be moved to miner crate eventually. /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 83511b1cc..e351011f2 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -217,7 +217,7 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option { + fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option<(ClosedBlock, HashSet)> { unimplemented!() } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index d9fae0527..64a2222b1 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -144,7 +144,7 @@ fn can_mine() { let client_result = get_test_client_with_blocks(vec![dummy_blocks[0].clone()]); let client = client_result.reference(); - let b = client.prepare_sealing(Address::default(), x!(31415926), vec![], vec![]).unwrap(); + let b = client.prepare_sealing(Address::default(), x!(31415926), vec![], vec![]).unwrap().0; assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3()); assert!(client.try_seal(b, vec![]).is_ok()); diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 7bbde6294..07a5cb8db 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -132,7 +132,20 @@ impl MinerService for Miner { self.extra_data(), transactions, ); - *self.sealing_block.lock().unwrap() = b; + + match b { + None => { + *self.sealing_block.lock().unwrap() = None + }, + Some((block, invalid_transactions)) => { + let mut queue = self.transaction_queue.lock().unwrap(); + queue.remove_all( + &invalid_transactions.into_iter().collect::>(), + |a: &Address| chain.nonce(a) + ); + *self.sealing_block.lock().unwrap() = Some(block) + } + } } fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex> { From 177d26a25e389166ea6f67baf0aaa709fb849b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 14:39:24 +0100 Subject: [PATCH 43/91] Stop adding transactions right after we know that no other will make it to block. --- ethcore/src/client/client.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 7818fcdc8..2c011047d 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -418,26 +418,33 @@ impl BlockChainClient for Client where V: Verifier { // Add transactions let block_number = b.block().header().number(); + let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas); let gas_limit = *b.block().header().gas_limit(); let mut gas_left = gas_limit; let mut invalid_transactions = HashSet::new(); for tx in transactions { - let hash = tx.hash(); - let gas = tx.gas; - // TODO [todr] It seems that calculating gas_left here doesn't really look nice. After moving this function + // Stop early if we are sure that no other transaction will be included + if gas_left < min_tx_gas { + break; + } + + // TODO [todr] It seems that calculating gas_left here doesn't look nice. After moving this function // to miner crate we should consider rewriting this logic in some better way. - if gas > gas_left { - trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash); + if tx.gas > gas_left { + trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", tx.hash()); continue; } + // Push transaction to block + let hash = tx.hash(); let import = b.push_transaction(tx, None); match import { Err(e) => { - trace!(target: "miner", "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}", - block_number, hash, e); invalid_transactions.insert(hash); + trace!(target: "miner", + "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}", + block_number, hash, e); }, Ok(receipt) => { gas_left = gas_limit - receipt.gas_used; From fbc85e31c2d3422e074c55c8e8d3a4d05b930c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 15:30:03 +0100 Subject: [PATCH 44/91] Refactoring removing invalid transactions from queue --- miner/src/miner.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 07a5cb8db..660fc55f9 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -133,19 +133,14 @@ impl MinerService for Miner { transactions, ); - match b { - None => { - *self.sealing_block.lock().unwrap() = None - }, - Some((block, invalid_transactions)) => { - let mut queue = self.transaction_queue.lock().unwrap(); - queue.remove_all( - &invalid_transactions.into_iter().collect::>(), - |a: &Address| chain.nonce(a) - ); - *self.sealing_block.lock().unwrap() = Some(block) - } - } + *self.sealing_block.lock().unwrap() = b.map(|(block, invalid_transactions)| { + let mut queue = self.transaction_queue.lock().unwrap(); + queue.remove_all( + &invalid_transactions.into_iter().collect::>(), + |a: &Address| chain.nonce(a) + ); + block + }); } fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex> { From 4d984ead4f25af96ee2e5b6d87c091ee25ed9397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 09:46:13 +0100 Subject: [PATCH 45/91] Fixing compilation --- miner/src/miner.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 660fc55f9..4448b721b 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -137,7 +137,10 @@ impl MinerService for Miner { let mut queue = self.transaction_queue.lock().unwrap(); queue.remove_all( &invalid_transactions.into_iter().collect::>(), - |a: &Address| chain.nonce(a) + |a: &Address| AccountDetails { + nonce: chain.nonce(a), + balance: chain.balance(a), + } ); block }); From b3dd72ab0ae2ed00bb388d6b6271e3cb59365135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 14:22:25 +0100 Subject: [PATCH 46/91] BlockGasLimit taken from push_transaction result --- ethcore/src/client/client.rs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 2c011047d..c62364dce 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -419,36 +419,28 @@ impl BlockChainClient for Client where V: Verifier { // Add transactions let block_number = b.block().header().number(); let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas); - let gas_limit = *b.block().header().gas_limit(); - let mut gas_left = gas_limit; let mut invalid_transactions = HashSet::new(); for tx in transactions { - // Stop early if we are sure that no other transaction will be included - if gas_left < min_tx_gas { - break; - } - - // TODO [todr] It seems that calculating gas_left here doesn't look nice. After moving this function - // to miner crate we should consider rewriting this logic in some better way. - if tx.gas > gas_left { - trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", tx.hash()); - continue; - } - // Push transaction to block let hash = tx.hash(); let import = b.push_transaction(tx, None); + match import { + Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, .. })) => { + trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash); + // Exit early if gas left is smaller then min_tx_gas + if gas_limit - gas_used < min_tx_gas { + break; + } + }, Err(e) => { invalid_transactions.insert(hash); trace!(target: "miner", "Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}", block_number, hash, e); }, - Ok(receipt) => { - gas_left = gas_limit - receipt.gas_used; - } + _ => {} } } From a0cdf5c420f45129461608b2e3821171c7aa6db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 15:20:33 +0100 Subject: [PATCH 47/91] Ignoring transactions slightly above gas_limit --- ethcore/src/error.rs | 7 ++++ miner/src/miner.rs | 17 ++++++++- miner/src/transaction_queue.rs | 67 +++++++++++++++++++++++++++++++++- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 482a8de01..a3a379463 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -79,6 +79,13 @@ pub enum TransactionError { /// Transaction cost cost: U256, }, + /// Transactions gas is higher then current gas limit + GasLimitExceeded { + /// Current gas limit + limit: U256, + /// Declared transaction gas + got: U256, + }, /// Transaction's gas limit (aka gas) is invalid. InvalidGasLimit(OutOfBounds), } diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 4448b721b..0307c56fc 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -21,7 +21,7 @@ use std::sync::atomic::AtomicBool; use std::collections::HashSet; use util::{H256, U256, Address, Bytes, Uint}; -use ethcore::views::{BlockView}; +use ethcore::views::{BlockView, HeaderView}; use ethcore::client::{BlockChainClient, BlockId}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::{Error}; @@ -94,6 +94,12 @@ impl Miner { pub fn set_minimal_gas_price(&self, min_gas_price: U256) { self.transaction_queue.lock().unwrap().set_minimal_gas_price(min_gas_price); } + + fn update_gas_limit(&self, chain: &BlockChainClient) { + let gas_limit = HeaderView::new(&chain.best_block_header()).gas_limit(); + let mut queue = self.transaction_queue.lock().unwrap(); + queue.set_gas_limit(gas_limit); + } } impl MinerService for Miner { @@ -185,6 +191,11 @@ impl MinerService for Miner { let block = BlockView::new(&block); block.transactions() } + + // First update gas limit in transaction queue + self.update_gas_limit(chain); + + // Then import all transactions... { let out_of_chain = retracted .par_iter() @@ -201,7 +212,8 @@ impl MinerService for Miner { }); }); } - // First import all transactions and after that remove old ones + + // ...and after that remove old ones { let in_chain = { let mut in_chain = HashSet::new(); @@ -227,6 +239,7 @@ impl MinerService for Miner { }); } + // Update mined block if self.sealing_enabled.load(atomic::Ordering::Relaxed) { self.prepare_sealing(chain); } diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 0f2ec6ec7..107904114 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -252,10 +252,16 @@ pub struct AccountDetails { pub balance: U256, } + +/// Transactions with `gas > (gas_limit + gas_limit * Factor(in percents))` are not imported to the queue. +const GAS_LIMIT_HYSTERESIS: usize = 10; // % + /// TransactionQueue implementation pub struct TransactionQueue { /// Gas Price threshold for transactions that can be imported to this queue (defaults to 0) minimal_gas_price: U256, + /// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0) + gas_limit: U256, /// Priority queue for transactions that can go to block current: TransactionSet, /// Priority queue for transactions that has been received but are not yet valid to go to block @@ -293,6 +299,7 @@ impl TransactionQueue { TransactionQueue { minimal_gas_price: U256::zero(), + gas_limit: !U256::zero(), current: current, future: future, by_hash: HashMap::new(), @@ -301,11 +308,24 @@ impl TransactionQueue { } /// Sets new gas price threshold for incoming transactions. - /// Any transactions already imported to the queue are not affected. + /// Any transaction already imported to the queue is not affected. pub fn set_minimal_gas_price(&mut self, min_gas_price: U256) { self.minimal_gas_price = min_gas_price; } + /// Sets new gas limit. Transactions with gas slightly (`GAS_LIMIT_HYSTERESIS`) above the limit won't be imported. + /// Any transaction already imported to the queue is not affected. + pub fn set_gas_limit(&mut self, gas_limit: U256) { + let extra = gas_limit / U256::from(GAS_LIMIT_HYSTERESIS); + + self.gas_limit = match gas_limit.overflowing_add(extra) { + (_, true) => !U256::zero(), + (val, false) => val, + }; + } + + // Will be used when rpc merged + #[allow(dead_code)] /// Returns current status for this queue pub fn status(&self) -> TransactionQueueStatus { TransactionQueueStatus { @@ -335,12 +355,24 @@ impl TransactionQueue { tx.hash(), tx.gas_price, self.minimal_gas_price ); - return Err(Error::Transaction(TransactionError::InsufficientGasPrice{ + return Err(Error::Transaction(TransactionError::InsufficientGasPrice { minimal: self.minimal_gas_price, got: tx.gas_price, })); } + if tx.gas > self.gas_limit { + trace!(target: "miner", + "Dropping transaction above gas limit: {:?} ({} > {})", + tx.hash(), tx.gas, self.gas_limit + ); + + return Err(Error::Transaction(TransactionError::GasLimitExceeded { + limit: self.gas_limit, + got: tx.gas, + })); + } + let vtx = try!(VerifiedTransaction::new(tx)); let account = fetch_account(&vtx.sender()); @@ -677,6 +709,37 @@ mod test { assert_eq!(stats.pending, 1); } + #[test] + fn gas_limit_should_never_overflow() { + // given + let mut txq = TransactionQueue::new(); + txq.set_gas_limit(U256::zero()); + assert_eq!(txq.gas_limit, U256::zero()); + + // when + txq.set_gas_limit(!U256::zero()); + + // then + assert_eq!(txq.gas_limit, !U256::zero()); + } + + #[test] + fn should_not_import_transaction_above_gas_limit() { + // given + let mut txq = TransactionQueue::new(); + let tx = new_tx(); + txq.set_gas_limit(tx.gas / U256::from(2)); + + // when + txq.add(tx, &default_nonce).unwrap_err(); + + // then + let stats = txq.status(); + assert_eq!(stats.pending, 0); + assert_eq!(stats.future, 0); + } + + #[test] fn should_drop_transactions_from_senders_without_balance() { // given From b18a7bde9a821c1830b3d1f24be369db47cc1949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 10:36:01 +0100 Subject: [PATCH 48/91] Updating gas_limit in test_client generated blocks --- ethcore/src/client/test_client.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index e351011f2..9150a5f55 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -111,6 +111,7 @@ impl TestBlockChainClient { header.difficulty = From::from(n); header.parent_hash = self.last_hash.read().unwrap().clone(); header.number = n as BlockNumber; + header.gas_limit = U256::from(1_000_000); let uncles = match with { EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => { let mut uncles = RlpStream::new_list(1); From 2aae86233057741497661503236be0f233dc2bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 12:47:31 +0100 Subject: [PATCH 49/91] Updating sealing when new transactions are received --- miner/src/lib.rs | 2 +- miner/src/miner.rs | 47 +++++++++++------------ rpc/src/v1/tests/helpers/miner_service.rs | 2 +- sync/src/chain.rs | 12 +++--- 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/miner/src/lib.rs b/miner/src/lib.rs index 648e9b3b5..c70caad66 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -92,7 +92,7 @@ pub trait MinerService : Send + Sync { fn chain_new_blocks(&self, chain: &BlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); /// New chain head event. Restart mining operation. - fn prepare_sealing(&self, chain: &BlockChainClient); + fn update_sealing(&self, chain: &BlockChainClient); /// Grab the `ClosedBlock` that we want to be sealed. Comes as a mutex that you have to lock. fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex>; diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 0307c56fc..be90b15af 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -95,10 +95,26 @@ impl Miner { self.transaction_queue.lock().unwrap().set_minimal_gas_price(min_gas_price); } +<<<<<<< HEAD fn update_gas_limit(&self, chain: &BlockChainClient) { let gas_limit = HeaderView::new(&chain.best_block_header()).gas_limit(); let mut queue = self.transaction_queue.lock().unwrap(); queue.set_gas_limit(gas_limit); +======= + /// Prepares new block for sealing including top transactions from queue. + pub fn prepare_sealing(&self, chain: &BlockChainClient) { + let no_of_transactions = 128; + // TODO: should select transactions orm queue according to gas limit of block. + let transactions = self.transaction_queue.lock().unwrap().top_transactions(no_of_transactions); + + let b = chain.prepare_sealing( + self.author(), + self.gas_floor_target(), + self.extra_data(), + transactions, + ); + *self.sealing_block.lock().unwrap() = b; +>>>>>>> b684bc9... Updating sealing when new transactions are received } } @@ -106,7 +122,7 @@ impl MinerService for Miner { fn clear_and_reset(&self, chain: &BlockChainClient) { self.transaction_queue.lock().unwrap().clear(); - self.prepare_sealing(chain); + self.update_sealing(chain); } fn status(&self) -> MinerStatus { @@ -130,26 +146,10 @@ impl MinerService for Miner { transaction_queue.pending_hashes() } - fn prepare_sealing(&self, chain: &BlockChainClient) { - let transactions = self.transaction_queue.lock().unwrap().top_transactions(); - let b = chain.prepare_sealing( - self.author(), - self.gas_floor_target(), - self.extra_data(), - transactions, - ); - - *self.sealing_block.lock().unwrap() = b.map(|(block, invalid_transactions)| { - let mut queue = self.transaction_queue.lock().unwrap(); - queue.remove_all( - &invalid_transactions.into_iter().collect::>(), - |a: &Address| AccountDetails { - nonce: chain.nonce(a), - balance: chain.balance(a), - } - ); - block - }); + fn update_sealing(&self, chain: &BlockChainClient) { + if self.sealing_enabled.load(atomic::Ordering::Relaxed) { + self.prepare_sealing(chain); + } } fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex> { @@ -239,9 +239,6 @@ impl MinerService for Miner { }); } - // Update mined block - if self.sealing_enabled.load(atomic::Ordering::Relaxed) { - self.prepare_sealing(chain); - } + self.update_sealing(chain); } } diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 44b94ac14..ca4151ba7 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -61,7 +61,7 @@ impl MinerService for TestMinerService { fn chain_new_blocks(&self, _chain: &BlockChainClient, _imported: &[H256], _invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) { unimplemented!(); } /// New chain head event. Restart mining operation. - fn prepare_sealing(&self, _chain: &BlockChainClient) { unimplemented!(); } + fn update_sealing(&self, _chain: &BlockChainClient) { unimplemented!(); } /// Grab the `ClosedBlock` that we want to be sealed. Comes as a mutex that you have to lock. fn sealing_block(&self, _chain: &BlockChainClient) -> &Mutex> { diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 8bb0c7c80..d15d1e79c 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -951,11 +951,11 @@ impl ChainSync { transactions.push(tx); } let chain = io.chain(); - let fetch_account = |a: &Address| AccountDetails { - nonce: chain.nonce(a), - balance: chain.balance(a), - }; - let _ = self.miner.import_transactions(transactions, fetch_account); + let fetch_nonce = |a: &Address| chain.nonce(a); + let res = self.miner.import_transactions(transactions, fetch_nonce); + if res.is_ok() { + self.miner.update_sealing(io.chain()); + } Ok(()) } @@ -1297,7 +1297,7 @@ impl ChainSync { } pub fn chain_new_head(&mut self, io: &mut SyncIo) { - self.miner.prepare_sealing(io.chain()); + self.miner.update_sealing(io.chain()); } } From 808f959a9474ba3e5f30b88106aa558d2a1054ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 15:49:29 +0100 Subject: [PATCH 50/91] Common error handling --- ethcore/src/error.rs | 4 ++++ miner/src/lib.rs | 2 +- miner/src/miner.rs | 2 +- miner/src/transaction_queue.rs | 28 +++++++++++++++------------- rpc/src/v1/impls/eth.rs | 2 +- sync/src/chain.rs | 10 +++++++--- 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index a3a379463..02cd6678b 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -65,6 +65,10 @@ pub enum ExecutionError { #[derive(Debug)] /// Errors concerning transaction processing. pub enum TransactionError { + /// Transaction is already imported to the queue + AlreadyImported, + /// Transaction is not valid anymore (state already has higher nonce) + Old, /// Transaction's gas price is below threshold. InsufficientGasPrice { /// Minimal expected gas price diff --git a/miner/src/lib.rs b/miner/src/lib.rs index c70caad66..b79a13e24 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -79,7 +79,7 @@ pub trait MinerService : Send + Sync { fn status(&self) -> MinerStatus; /// Imports transactions to transaction queue. - fn import_transactions(&self, transactions: Vec, fetch_account: T) -> Result<(), Error> + fn import_transactions(&self, transactions: Vec, fetch_account: T) -> Vec> where T: Fn(&Address) -> AccountDetails; /// Returns hashes of transactions currently in pending diff --git a/miner/src/miner.rs b/miner/src/miner.rs index be90b15af..858df7c40 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -135,7 +135,7 @@ impl MinerService for Miner { } } - fn import_transactions(&self, transactions: Vec, fetch_account: T) -> Result<(), Error> + fn import_transactions(&self, transactions: Vec, fetch_account: T) -> Vec> where T: Fn(&Address) -> AccountDetails { let mut transaction_queue = self.transaction_queue.lock().unwrap(); transaction_queue.add_all(transactions, fetch_account) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 107904114..4b76fcbb2 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -335,12 +335,12 @@ impl TransactionQueue { } /// Adds all signed transactions to queue to be verified and imported - pub fn add_all(&mut self, txs: Vec, fetch_account: T) -> Result<(), Error> + pub fn add_all(&mut self, txs: Vec, fetch_account: T) -> Vec> where T: Fn(&Address) -> AccountDetails { - for tx in txs.into_iter() { - try!(self.add(tx, &fetch_account)); - } - Ok(()) + + txs.into_iter() + .map(|tx| self.add(tx, &fetch_account)) + .collect() } /// Add signed transaction to queue to be verified and imported @@ -387,8 +387,7 @@ impl TransactionQueue { })); } - self.import_tx(vtx, account.nonce); - Ok(()) + self.import_tx(vtx, account.nonce).map_err(Error::Transaction) } /// Removes all transactions identified by hashes given in slice @@ -542,12 +541,14 @@ impl TransactionQueue { /// /// It ignores transactions that has already been imported (same `hash`) and replaces the transaction /// iff `(address, nonce)` is the same but `gas_price` is higher. - fn import_tx(&mut self, tx: VerifiedTransaction, state_nonce: U256) { + /// + /// Returns `true` when transaction was imported successfuly + fn import_tx(&mut self, tx: VerifiedTransaction, state_nonce: U256) -> Result<(), TransactionError> { if self.by_hash.get(&tx.hash()).is_some() { // Transaction is already imported. trace!(target: "miner", "Dropping already imported transaction: {:?}", tx.hash()); - return; + return Err(TransactionError::AlreadyImported); } @@ -564,11 +565,11 @@ impl TransactionQueue { // We have a gap - put to future Self::replace_transaction(tx, next_nonce, &mut self.future, &mut self.by_hash); self.future.enforce_limit(&mut self.by_hash); - return; + return Ok(()); } else if nonce < state_nonce { // Droping transaction trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", tx.hash(), nonce, next_nonce); - return; + return Err(TransactionError::Old); } Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash); @@ -578,6 +579,7 @@ impl TransactionQueue { self.current.enforce_limit(&mut self.by_hash); trace!(target: "miner", "status: {:?}", self.status()); + Ok(()) } /// Replaces transaction in given set (could be `future` or `current`). @@ -1010,7 +1012,7 @@ mod test { let fetch_last_nonce = |_a: &Address| AccountDetails{ nonce: last_nonce, balance: !U256::zero() }; // when - txq.add(tx, &fetch_last_nonce).unwrap(); + txq.add(tx, &fetch_last_nonce).unwrap_err(); // then let stats = txq.status(); @@ -1030,7 +1032,7 @@ mod test { assert_eq!(txq.status().pending, 0); // when - txq.add(tx2.clone(), &nonce).unwrap(); + txq.add(tx2.clone(), &nonce).unwrap_err(); // then let stats = txq.status(); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 7ecfb86de..5cd1b2966 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -385,7 +385,7 @@ impl Eth for EthClient nonce: client.nonce(a), balance: client.balance(a), }); - match import { + match import.into_iter().collect::, _>>() { Ok(_) => to_value(&hash), Err(e) => { warn!("Error sending transaction: {:?}", e); diff --git a/sync/src/chain.rs b/sync/src/chain.rs index d15d1e79c..52bfa0878 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -951,9 +951,13 @@ impl ChainSync { transactions.push(tx); } let chain = io.chain(); - let fetch_nonce = |a: &Address| chain.nonce(a); - let res = self.miner.import_transactions(transactions, fetch_nonce); - if res.is_ok() { + let fetch_account = |a: &Address| AccountDetails { + nonce: chain.nonce(a), + balance: chain.balance(a), + }; + let res = self.miner.import_transactions(transactions, fetch_account); + let any_transaction_imported = res.into_iter().any(|r| r.is_ok()); + if any_transaction_imported { self.miner.update_sealing(io.chain()); } Ok(()) From 2f411c93fdc2d887b8eb85570f20b17e6300b5f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 17 Mar 2016 17:19:46 +0100 Subject: [PATCH 51/91] Removing update_seal when new transactions arrives --- rpc/src/v1/tests/helpers/miner_service.rs | 2 +- sync/src/chain.rs | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index ca4151ba7..ad9dcaedd 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -48,7 +48,7 @@ impl MinerService for TestMinerService { } /// Imports transactions to transaction queue. - fn import_transactions(&self, _transactions: Vec, _fetch_account: T) -> Result<(), Error> + fn import_transactions(&self, _transactions: Vec, _fetch_account: T) -> Vec> where T: Fn(&Address) -> AccountDetails { unimplemented!(); } /// Returns hashes of transactions currently in pending diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 52bfa0878..9c756973b 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -955,11 +955,7 @@ impl ChainSync { nonce: chain.nonce(a), balance: chain.balance(a), }; - let res = self.miner.import_transactions(transactions, fetch_account); - let any_transaction_imported = res.into_iter().any(|r| r.is_ok()); - if any_transaction_imported { - self.miner.update_sealing(io.chain()); - } + let _ = self.miner.import_transactions(transactions, fetch_account); Ok(()) } From 7105ed3f612d6905d5d7f7dffcb21eb9dc9603a3 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 17 Mar 2016 11:50:31 +0100 Subject: [PATCH 52/91] rpctest executable --- Cargo.lock | 1 + Cargo.toml | 5 ++ json/src/blockchain/block.rs | 7 +++ json/src/blockchain/blockchain.rs | 12 +++++ json/src/blockchain/mod.rs | 8 ++++ json/src/blockchain/test.rs | 1 + json/src/bytes.rs | 2 +- parity/rpctest.rs | 80 +++++++++++++++++++++++++++++++ 8 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 parity/rpctest.rs diff --git a/Cargo.lock b/Cargo.lock index de71889bb..f14eaac5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,7 @@ dependencies = [ "rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 68cb3a504..e52e1c89b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ ethminer = { path = "miner" } ethcore-devtools = { path = "devtools" } ethcore-rpc = { path = "rpc", optional = true } ethjson = { path = "json" } +serde_json = "0.7.0" [features] default = ["rpc"] @@ -40,6 +41,10 @@ travis-nightly = ["ethcore/json-tests", "dev"] path = "parity/main.rs" name = "parity" +[[bin]] +path = "parity/rpctest.rs" +name = "rpctest" + [profile.release] debug = false lto = false diff --git a/json/src/blockchain/block.rs b/json/src/blockchain/block.rs index ed297077c..190102ae5 100644 --- a/json/src/blockchain/block.rs +++ b/json/src/blockchain/block.rs @@ -31,6 +31,13 @@ pub struct Block { uncles: Vec
, } +impl Block { + /// Returns block rlp. + pub fn rlp(&self) -> Vec { + self.rlp.clone().into() + } +} + #[cfg(test)] mod tests { use serde_json; diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index f6b1259ca..8c67799e1 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -35,6 +35,18 @@ pub struct BlockChain { pre_state: State, } +impl BlockChain { + /// Returns genesis block rlp. + pub fn genesis_rlp(&self) -> Vec { + self.genesis_rlp.clone().into() + } + + /// Returns blocks rlp. + pub fn blocks_rlp(&self) -> Vec> { + self.blocks.iter().map(|block| block.rlp()).collect() + } +} + #[cfg(test)] mod tests { use serde_json; diff --git a/json/src/blockchain/mod.rs b/json/src/blockchain/mod.rs index 046b2e534..727469ea2 100644 --- a/json/src/blockchain/mod.rs +++ b/json/src/blockchain/mod.rs @@ -23,3 +23,11 @@ pub mod header; pub mod state; pub mod transaction; pub mod test; + +pub use self::account::Account; +pub use self::block::Block; +pub use self::blockchain::BlockChain; +pub use self::header::Header; +pub use self::state::State; +pub use self::test::Test; +pub use self::transaction::Transaction; diff --git a/json/src/blockchain/test.rs b/json/src/blockchain/test.rs index 6097a60e6..6f48a8bc6 100644 --- a/json/src/blockchain/test.rs +++ b/json/src/blockchain/test.rs @@ -21,6 +21,7 @@ use std::ops::Deref; use blockchain::blockchain::BlockChain; /// Blockchain test deserializer. +#[derive(Debug, PartialEq, Deserialize)] pub struct Test(BTreeMap); impl Deref for Test { diff --git a/json/src/bytes.rs b/json/src/bytes.rs index 28b7636d4..061795b40 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -21,7 +21,7 @@ use serde::{Deserialize, Deserializer, Error}; use serde::de::Visitor; /// Lenient bytes json deserialization for test json files. -#[derive(Default, Debug, PartialEq)] +#[derive(Default, Debug, PartialEq, Clone)] pub struct Bytes(Vec); impl Into> for Bytes { diff --git a/parity/rpctest.rs b/parity/rpctest.rs new file mode 100644 index 000000000..182f6dfed --- /dev/null +++ b/parity/rpctest.rs @@ -0,0 +1,80 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +extern crate docopt; +extern crate rustc_serialize; +extern crate serde_json; +extern crate ethjson; + +use std::process; +use std::fs::File; +use std::path::Path; +use docopt::Docopt; + +const USAGE: &'static str = r#" +Parity rpctest client. + By Wood/Paronyan/Kotewicz/Drwięga/Volf. + Copyright 2015, 2016 Ethcore (UK) Limited + +Usage: + parity --json --name +"#; + +#[derive(Debug, RustcDecodable)] +struct Args { + arg_test_file: String, + arg_test_name: String, +} + +struct Configuration { + args: Args, +} + +impl Configuration { + fn parse() -> Self { + Configuration { + args: Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit()) + } + } + + fn execute(&self) { + println!("file path: {:?}", self.args.arg_test_file); + println!("test name: {:?}", self.args.arg_test_name); + + let path = Path::new(&self.args.arg_test_file); + let file = File::open(path).unwrap_or_else(|_| { + println!("Cannot open file."); + process::exit(1); + }); + + let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|_| { + println!("Invalid json file."); + process::exit(2); + }); + + let blockchain = tests.get(&self.args.arg_test_name).unwrap_or_else(|| { + println!("Invalid test name."); + process::exit(3); + }); + + + + } +} + +fn main() { + Configuration::parse().execute(); +} From 1fa019d92a7216ccb181fe1de5e63f87a87b71df Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 17 Mar 2016 13:41:11 +0100 Subject: [PATCH 53/91] ethjson spec submodule --- ethcore/res/ethereum/frontier_like_test.json | 2 +- ethcore/res/ethereum/frontier_test.json | 2 +- json/src/hash.rs | 4 + json/src/lib.rs.in | 1 + json/src/spec/account.rs | 44 ++++++++++ json/src/spec/builtin.rs | 47 +++++++++++ json/src/spec/genesis.rs | 67 ++++++++++++++++ json/src/spec/mod.rs | 29 +++++++ json/src/spec/params.rs | 74 +++++++++++++++++ json/src/spec/spec.rs | 84 ++++++++++++++++++++ 10 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 json/src/spec/account.rs create mode 100644 json/src/spec/builtin.rs create mode 100644 json/src/spec/genesis.rs create mode 100644 json/src/spec/mod.rs create mode 100644 json/src/spec/params.rs create mode 100644 json/src/spec/spec.rs diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 3e4108566..ebfbc2383 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -1,5 +1,5 @@ { - "engineName": "Frontier (Test)", + "name": "Frontier (Test)", "engineName": "Ethash", "params": { "accountStartNonce": "0x00", diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index 8ee1cafd9..227ad1bc3 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -1,5 +1,5 @@ { - "engineName": "Frontier (Test)", + "name": "Frontier (Test)", "engineName": "Ethash", "params": { "accountStartNonce": "0x00", diff --git a/json/src/hash.rs b/json/src/hash.rs index 098f2e7a8..bece68011 100644 --- a/json/src/hash.rs +++ b/json/src/hash.rs @@ -46,6 +46,10 @@ macro_rules! impl_hash { fn visit_str(&mut self, value: &str) -> Result where E: Error { let value = match value.len() { 0 => $inner::from(0), + 2 if value == "0x" => $inner::from(0), + _ if value.starts_with("0x") => try!($inner::from_str(&value[2..]).map_err(|_| { + Error::custom(format!("Invalid hex value {}.", value).as_ref()) + })), _ => try!($inner::from_str(value).map_err(|_| { Error::custom(format!("Invalid hex value {}.", value).as_ref()) })) diff --git a/json/src/lib.rs.in b/json/src/lib.rs.in index 6d3437811..0d85ce569 100644 --- a/json/src/lib.rs.in +++ b/json/src/lib.rs.in @@ -23,3 +23,4 @@ pub mod hash; pub mod uint; pub mod bytes; pub mod blockchain; +pub mod spec; diff --git a/json/src/spec/account.rs b/json/src/spec/account.rs new file mode 100644 index 000000000..8c98f89d9 --- /dev/null +++ b/json/src/spec/account.rs @@ -0,0 +1,44 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Spec account deserialization. + +use uint::Uint; +use spec::builtin::Builtin; + +/// Spec account. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Account { + builtin: Option, + balance: Option, + nonce: Option, +} + +#[cfg(test)] +mod tests { + use serde_json; + use spec::account::Account; + + #[test] + fn account_deserialization() { + let s = r#"{ + "balance": "1", + "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } + }"#; + let _deserialized: Account = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs new file mode 100644 index 000000000..f49367ecb --- /dev/null +++ b/json/src/spec/builtin.rs @@ -0,0 +1,47 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Spec builtin deserialization. + +/// Linear builin options. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Linear { + base: u64, + word: u64, +} + +/// Spec builtin. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Builtin { + name: String, + linear: Linear, +} + +#[cfg(test)] +mod tests { + use serde_json; + use spec::builtin::Builtin; + + #[test] + fn builtin_deserialization() { + let s = r#"{ + "name": "ecrecover", + "linear": { "base": 3000, "word": 0 } + }"#; + let _deserialized: Builtin = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/spec/genesis.rs b/json/src/spec/genesis.rs new file mode 100644 index 000000000..4c66a9e35 --- /dev/null +++ b/json/src/spec/genesis.rs @@ -0,0 +1,67 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Spec genesis deserialization. + +use uint::Uint; +use hash::{Address, H256}; +use bytes::Bytes; + +/// Spec genesis. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Genesis { + // old seal + nonce: Option, + #[serde(rename="mixHash")] + mix_hash: Option, + + // new seal // TODO: consider moving it to a separate seal structure + #[serde(rename="sealFields")] + seal_fields: Option, + #[serde(rename="sealRlp")] + seal_rlp: Option, + + difficulty: Uint, + author: Address, + timestamp: Uint, + #[serde(rename="parentHash")] + parent_hash: H256, + #[serde(rename="gasLimit")] + gas_limit: Uint, +} + +#[cfg(test)] +mod tests { + use serde_json; + use spec::genesis::Genesis; + + #[test] + fn genesis_deserialization() { + let s = r#"{ + "nonce": "0x0000000000000042", + "difficulty": "0x400000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388", + "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" + }"#; + let _deserialized: Genesis = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/spec/mod.rs b/json/src/spec/mod.rs new file mode 100644 index 000000000..8783563d1 --- /dev/null +++ b/json/src/spec/mod.rs @@ -0,0 +1,29 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Spec deserialization. + +pub mod account; +pub mod builtin; +pub mod genesis; +pub mod params; +pub mod spec; + +pub use self::account::Account; +pub use self::builtin::Builtin; +pub use self::genesis::Genesis; +pub use self::params::Params; +pub use self::spec::Spec; diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs new file mode 100644 index 000000000..e55f7fc48 --- /dev/null +++ b/json/src/spec/params.rs @@ -0,0 +1,74 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Spec params deserialization. + +use uint::Uint; +use hash::Address; + +/// Spec params. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Params { + #[serde(rename="accountStartNonce")] + account_start_nonce: Uint, + #[serde(rename="frontierCompatibilityModeLimit")] + frontier_compatibility_mode_limit: Uint, + #[serde(rename="maximumExtraDataSize")] + maximum_extra_data_size: Uint, + #[serde(rename="tieBreakingGas")] + tie_breaking_gas: bool, + #[serde(rename="minGasLimit")] + min_gas_limit: Uint, + #[serde(rename="gasLimitBoundDivisor")] + gas_limit_bound_divisor: Uint, + #[serde(rename="minimumDifficulty")] + minimum_difficulty: Uint, + #[serde(rename="difficultyBoundDivisor")] + difficulty_bound_divisor: Uint, + #[serde(rename="durationLimit")] + duration_limit: Uint, + #[serde(rename="blockReward")] + block_reward: Uint, + registrar: Address, + #[serde(rename="networkID")] + network_id: Uint, +} + +#[cfg(test)] +mod tests { + use serde_json; + use spec::params::Params; + + #[test] + fn params_deserialization() { + let s = r#"{ + "accountStartNonce": "0x00", + "frontierCompatibilityModeLimit": "0x118c30", + "maximumExtraDataSize": "0x20", + "tieBreakingGas": false, + "minGasLimit": "0x1388", + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "networkID" : "0x1" + }"#; + let _deserialized: Params = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs new file mode 100644 index 000000000..79662b19a --- /dev/null +++ b/json/src/spec/spec.rs @@ -0,0 +1,84 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Spec deserialization. + +use std::collections::BTreeMap; +use hash::Address; +use spec::account::Account; +use spec::params::Params; +use spec::genesis::Genesis; + +/// Spec deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct Spec { + name: String, + #[serde(rename="engineName")] + engine_name: String, // TODO: consider making it an enum + params: Params, + genesis: Genesis, + accounts: BTreeMap, +} + +#[cfg(test)] +mod tests { + use serde_json; + use spec::spec::Spec; + + #[test] + fn spec_deserialization() { + let s = r#"{ + "name": "Morden", + "engineName": "Ethash", + "params": { + "accountStartNonce": "0x0100000", + "frontierCompatibilityModeLimit": "0x789b0", + "maximumExtraDataSize": "0x20", + "tieBreakingGas": false, + "minGasLimit": "0x1388", + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "registrar": "", + "networkID" : "0x2" + }, + "genesis": { + "nonce": "0x00006d6f7264656e", + "difficulty": "0x20000", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "nodes": [ + "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303" + ], + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } + } + }"#; + let _deserialized: Spec = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} From 7a0dfec115c85c683d10ef166e5f25bd094a6e85 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 17 Mar 2016 14:03:53 +0100 Subject: [PATCH 54/91] added genesis method to ethjson blockchain --- json/src/blockchain/blockchain.rs | 16 ++++++++++ json/src/blockchain/header.rs | 49 +++++++++++++++++++++---------- json/src/hash.rs | 2 +- json/src/spec/genesis.rs | 29 +++++++++++------- json/src/uint.rs | 2 +- 5 files changed, 70 insertions(+), 28 deletions(-) diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 8c67799e1..75d321a4d 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -20,6 +20,7 @@ use bytes::Bytes; use blockchain::state::State; use blockchain::header::Header; use blockchain::block::Block; +use spec::Genesis; /// Blockchain deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -45,6 +46,21 @@ impl BlockChain { pub fn blocks_rlp(&self) -> Vec> { self.blocks.iter().map(|block| block.rlp()).collect() } + + /// Returns spec compatible genesis struct. + pub fn genesis(&self) -> Genesis { + Genesis { + nonce: Some(self.genesis_block.nonce.clone()), + mix_hash: Some(self.genesis_block.mix_hash.clone()), + seal_fields: None, + seal_rlp: None, + difficulty: self.genesis_block.difficulty, + author: self.genesis_block.author.clone(), + timestamp: self.genesis_block.timestamp, + parent_hash: self.genesis_block.parent_hash.clone(), + gas_limit: self.genesis_block.gas_limit, + } + } } #[cfg(test)] diff --git a/json/src/blockchain/header.rs b/json/src/blockchain/header.rs index e97039213..f4ebee01b 100644 --- a/json/src/blockchain/header.rs +++ b/json/src/blockchain/header.rs @@ -23,31 +23,48 @@ use bytes::Bytes; /// Blockchain test header deserializer. #[derive(Debug, PartialEq, Deserialize)] pub struct Header { - bloom: Bloom, - coinbase: Address, - difficulty: Uint, + /// Blocks bloom. + pub bloom: Bloom, + /// Blocks author. + #[serde(rename="coinbase")] + pub author: Address, + /// Difficulty. + pub difficulty: Uint, #[serde(rename="extraData")] - extra_data: Bytes, + /// Extra data. + pub extra_data: Bytes, + /// Gas limit. #[serde(rename="gasLimit")] - gas_limit: Uint, + pub gas_limit: Uint, + /// Gas used. #[serde(rename="gasUsed")] - gas_used: Uint, - hash: H256, + pub gas_used: Uint, + /// Hash. + pub hash: H256, #[serde(rename="mixHash")] - mix_hash: H256, - nonce: H64, - number: Uint, + /// Mix hash. + pub mix_hash: H256, + /// Seal nonce. + pub nonce: H64, + /// Block number. + pub number: Uint, + /// Parent hash. #[serde(rename="parentHash")] - parent_hash: H256, + pub parent_hash: H256, + /// Receipt root. #[serde(rename="receiptTrie")] - receipt_trie: H256, + pub receipt_root: H256, + /// State root. #[serde(rename="stateRoot")] - state_root: H256, - timestamp: Uint, + pub state_root: H256, + /// Timestamp. + pub timestamp: Uint, + /// Transactions root. #[serde(rename="transactionsTrie")] - transactions_trie: H256, + pub transactions_root: H256, + /// Uncles hash. #[serde(rename="uncleHash")] - uncle_hash: H256, + pub uncles_hash: H256, } #[cfg(test)] diff --git a/json/src/hash.rs b/json/src/hash.rs index bece68011..c555b6266 100644 --- a/json/src/hash.rs +++ b/json/src/hash.rs @@ -25,7 +25,7 @@ use util::hash::{H64 as Hash64, Address as Hash160, H256 as Hash256, H2048 as Ha macro_rules! impl_hash { ($name: ident, $inner: ident) => { /// Lenient hash json deserialization for test json files. - #[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] + #[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)] pub struct $name($inner); impl Into<$inner> for $name { diff --git a/json/src/spec/genesis.rs b/json/src/spec/genesis.rs index 4c66a9e35..a8b5b30e3 100644 --- a/json/src/spec/genesis.rs +++ b/json/src/spec/genesis.rs @@ -17,30 +17,39 @@ //! Spec genesis deserialization. use uint::Uint; -use hash::{Address, H256}; +use hash::{H64, Address, H256}; use bytes::Bytes; /// Spec genesis. #[derive(Debug, PartialEq, Deserialize)] pub struct Genesis { // old seal - nonce: Option, + /// Seal nonce. + pub nonce: Option, #[serde(rename="mixHash")] - mix_hash: Option, + /// Seal mix hash. + pub mix_hash: Option, // new seal // TODO: consider moving it to a separate seal structure #[serde(rename="sealFields")] - seal_fields: Option, + /// Number of seal fields. + pub seal_fields: Option, #[serde(rename="sealRlp")] - seal_rlp: Option, + /// Seal rlp. + pub seal_rlp: Option, - difficulty: Uint, - author: Address, - timestamp: Uint, + /// Difficulty. + pub difficulty: Uint, + /// Block author. + pub author: Address, + /// Block timestamp. + pub timestamp: Uint, + /// Parent hash. #[serde(rename="parentHash")] - parent_hash: H256, + pub parent_hash: H256, + /// Gas limit. #[serde(rename="gasLimit")] - gas_limit: Uint, + pub gas_limit: Uint, } #[cfg(test)] diff --git a/json/src/uint.rs b/json/src/uint.rs index 41e717277..2d24c3f7e 100644 --- a/json/src/uint.rs +++ b/json/src/uint.rs @@ -22,7 +22,7 @@ use serde::de::Visitor; use util::numbers::{U256, Uint as U}; /// Lenient uint json deserialization for test json files. -#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub struct Uint(U256); impl Into for Uint { From 39aa02ed260dac95657da6c55c0ce39529867900 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 17 Mar 2016 15:15:10 +0100 Subject: [PATCH 55/91] moved ethcores spec to its own module, added genesis --- Cargo.lock | 1 + ethcore/Cargo.toml | 1 + ethcore/src/lib.rs | 1 + ethcore/src/spec/genesis.rs | 91 +++++++++++++++++++++++++++++++ ethcore/src/spec/mod.rs | 22 ++++++++ ethcore/src/{ => spec}/spec.rs | 32 ++++++++++- json/src/blockchain/blockchain.rs | 5 ++ json/src/blockchain/header.rs | 2 +- json/src/spec/genesis.rs | 17 +++++- json/src/uint.rs | 6 ++ 10 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 ethcore/src/spec/genesis.rs create mode 100644 ethcore/src/spec/mod.rs rename ethcore/src/{ => spec}/spec.rs (92%) diff --git a/Cargo.lock b/Cargo.lock index f14eaac5a..9240a5b36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,6 +216,7 @@ dependencies = [ "ethash 1.0.0", "ethcore-devtools 1.0.0", "ethcore-util 1.0.0", + "ethjson 0.1.0", "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 21e09655e..d2f464607 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -21,6 +21,7 @@ clippy = { version = "0.0.54", optional = true } crossbeam = "0.1.5" lazy_static = "0.1" ethcore-devtools = { path = "../devtools" } +ethjson = { path = "../json" } [features] jit = ["evmjit"] diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 572cda2fa..662dea641 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -83,6 +83,7 @@ extern crate time; extern crate env_logger; extern crate num_cpus; extern crate crossbeam; +extern crate ethjson; #[cfg(test)] extern crate ethcore_devtools as devtools; #[cfg(feature = "jit" )] extern crate evmjit; diff --git a/ethcore/src/spec/genesis.rs b/ethcore/src/spec/genesis.rs new file mode 100644 index 000000000..686e8f6d1 --- /dev/null +++ b/ethcore/src/spec/genesis.rs @@ -0,0 +1,91 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use util::rlp::*; +use util::numbers::{Uint, U256}; +use util::hash::{H64, Address, H256}; +use ethjson; + +/// Genesis seal type. +pub enum Seal { + /// Classic ethereum seal. + Ethereum { + /// Seal nonce. + nonce: H64, + /// Seal mix hash. + mix_hash: H256, + }, + /// Generic seal. + Generic { + /// Number of seal fields. + fields: usize, + /// Seal rlp. + rlp: Vec, + }, +} + +/// Genesis components. +pub struct Genesis { + /// Seal. + pub seal: Seal, + /// Difficulty. + pub difficulty: U256, + /// Author. + pub author: Address, + /// Timestamp. + pub timestamp: u64, + /// Parent hash. + pub parent_hash: H256, + /// Gas limit. + pub gas_limit: U256, + /// Transactions root. + pub transactions_root: H256, + /// Receipts root. + pub receipts_root: H256, + /// State root. + pub state_root: Option, + /// Gas used. + pub gas_used: U256, + /// Extra data. + pub extra_data: Vec, +} + +impl From for Genesis { + fn from(g: ethjson::spec::Genesis) -> Self { + Genesis { + seal: match (g.nonce, g.mix_hash) { + (Some(nonce), Some(mix_hash)) => Seal::Ethereum { + nonce: nonce.into(), + mix_hash: mix_hash.into(), + }, + _ => Seal::Generic { + fields: g.seal_fields.unwrap(), + rlp: g.seal_rlp.unwrap().into(), + } + }, + difficulty: g.difficulty.into(), + author: g.author.into(), + timestamp: g.timestamp.into(), + parent_hash: g.parent_hash.into(), + gas_limit: g.gas_limit.into(), + transactions_root: g.transactions_root.map_or_else(|| SHA3_NULL_RLP.clone(), Into::into), + receipts_root: g.receipts_root.map_or_else(|| SHA3_NULL_RLP.clone(), Into::into), + state_root: g.state_root.map(Into::into), + gas_used: g.gas_used.map_or_else(U256::zero, Into::into), + extra_data: g.extra_data.map_or_else(Vec::new, Into::into), + } + } +} diff --git a/ethcore/src/spec/mod.rs b/ethcore/src/spec/mod.rs new file mode 100644 index 000000000..e9c7a0356 --- /dev/null +++ b/ethcore/src/spec/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blockchain params. + +mod genesis; +pub mod spec; + +pub use self::spec::*; diff --git a/ethcore/src/spec.rs b/ethcore/src/spec/spec.rs similarity index 92% rename from ethcore/src/spec.rs rename to ethcore/src/spec/spec.rs index 2208350cc..c7e2e4e9f 100644 --- a/ethcore/src/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -21,6 +21,8 @@ use engine::*; use pod_state::*; use null_engine::*; use account_db::*; +use ethereum; +use super::genesis::{Seal as GenesisSeal, Genesis}; /// Convert JSON value to equivalent RLP representation. // TODO: handle container types. @@ -106,7 +108,7 @@ impl Spec { pub fn to_engine(self) -> Result, Error> { match self.engine_name.as_ref() { "NullEngine" => Ok(NullEngine::new_boxed(self)), - "Ethash" => Ok(super::ethereum::Ethash::new_boxed(self)), + "Ethash" => Ok(ethereum::Ethash::new_boxed(self)), _ => Err(Error::UnknownEngineName(self.engine_name.clone())) } } @@ -197,6 +199,32 @@ impl Spec { self.state_root_memo = RwLock::new(genesis.find("stateRoot").and_then(|_| Some(H256::from_json(&genesis["stateRoot"])))); } + /// Overwrite the genesis components. + pub fn overwrite_genesis_params(&mut self, g: Genesis) { + let (seal_fields, seal_rlp) = match g.seal { + GenesisSeal::Generic { fields, rlp } => (fields, rlp), + GenesisSeal::Ethereum { nonce, mix_hash } => { + let mut s = RlpStream::new(); + s.append(&mix_hash); + s.append(&nonce); + (2, s.out()) + } + }; + + self.parent_hash = g.parent_hash; + self.transactions_root = g.transactions_root; + self.receipts_root = g.receipts_root; + self.author = g.author; + self.difficulty = g.difficulty; + self.gas_limit = g.gas_limit; + self.gas_used = g.gas_used; + self.timestamp = g.timestamp; + self.extra_data = g.extra_data; + self.seal_fields = seal_fields; + self.seal_rlp = seal_rlp; + self.state_root_memo = RwLock::new(g.state_root); + } + /// Alter the value of the genesis state. pub fn set_genesis_state(&mut self, s: PodState) { self.genesis_state = s; @@ -304,7 +332,7 @@ impl Spec { } /// Create a new Spec which conforms to the Morden chain except that it's a NullEngine consensus. - pub fn new_test() -> Spec { Self::from_json_utf8(include_bytes!("../res/null_morden.json")) } + pub fn new_test() -> Spec { Self::from_json_utf8(include_bytes!("../../res/null_morden.json")) } } #[cfg(test)] diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 75d321a4d..d9e879ae9 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -59,6 +59,11 @@ impl BlockChain { timestamp: self.genesis_block.timestamp, parent_hash: self.genesis_block.parent_hash.clone(), gas_limit: self.genesis_block.gas_limit, + transactions_root: Some(self.genesis_block.transactions_root.clone()), + receipts_root: Some(self.genesis_block.receipts_root.clone()), + state_root: Some(self.genesis_block.state_root.clone()), + gas_used: Some(self.genesis_block.gas_used), + extra_data: Some(self.genesis_block.extra_data.clone()), } } } diff --git a/json/src/blockchain/header.rs b/json/src/blockchain/header.rs index f4ebee01b..ece6d6359 100644 --- a/json/src/blockchain/header.rs +++ b/json/src/blockchain/header.rs @@ -53,7 +53,7 @@ pub struct Header { pub parent_hash: H256, /// Receipt root. #[serde(rename="receiptTrie")] - pub receipt_root: H256, + pub receipts_root: H256, /// State root. #[serde(rename="stateRoot")] pub state_root: H256, diff --git a/json/src/spec/genesis.rs b/json/src/spec/genesis.rs index a8b5b30e3..a2b484397 100644 --- a/json/src/spec/genesis.rs +++ b/json/src/spec/genesis.rs @@ -33,7 +33,7 @@ pub struct Genesis { // new seal // TODO: consider moving it to a separate seal structure #[serde(rename="sealFields")] /// Number of seal fields. - pub seal_fields: Option, + pub seal_fields: Option, #[serde(rename="sealRlp")] /// Seal rlp. pub seal_rlp: Option, @@ -50,6 +50,21 @@ pub struct Genesis { /// Gas limit. #[serde(rename="gasLimit")] pub gas_limit: Uint, + /// Transactions root. + #[serde(rename="transactionsRoot")] + pub transactions_root: Option, + /// Receipts root. + #[serde(rename="receiptsRoot")] + pub receipts_root: Option, + /// State root. + #[serde(rename="stateRoot")] + pub state_root: Option, + /// Gas used. + #[serde(rename="gasUsed")] + pub gas_used: Option, + /// Extra data. + #[serde(rename="extraData")] + pub extra_data: Option, } #[cfg(test)] diff --git a/json/src/uint.rs b/json/src/uint.rs index 2d24c3f7e..f6eae80e4 100644 --- a/json/src/uint.rs +++ b/json/src/uint.rs @@ -31,6 +31,12 @@ impl Into for Uint { } } +impl Into for Uint { + fn into(self) -> u64 { + u64::from(self.0) + } +} + impl Deserialize for Uint { fn deserialize(deserializer: &mut D) -> Result where D: Deserializer { From de21fef868c687fdf00dd0871d13c89fdc7382bb Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 17 Mar 2016 15:51:40 +0100 Subject: [PATCH 56/91] new way of loading PodState --- ethcore/src/lib.rs | 2 +- ethcore/src/pod_account.rs | 16 ++++++++++++++++ ethcore/src/pod_state.rs | 14 +++++++++++++- ethcore/src/spec/mod.rs | 1 + json/src/blockchain/account.rs | 17 +++++++++++------ json/src/blockchain/blockchain.rs | 15 ++++++++++----- json/src/blockchain/state.rs | 4 ++-- parity/rpctest.rs | 12 ++++++++++++ 8 files changed, 66 insertions(+), 15 deletions(-) diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 662dea641..dfa321639 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -101,13 +101,13 @@ pub mod spec; pub mod transaction; pub mod views; pub mod receipt; +pub mod pod_state; mod common; mod basic_types; #[macro_use] mod evm; mod env_info; mod pod_account; -mod pod_state; mod account_diff; mod state_diff; mod engine; diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index d2690051c..8f38326ca 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -17,6 +17,7 @@ use util::*; use account::*; use account_db::*; +use ethjson; #[derive(Debug,Clone,PartialEq,Eq)] /// An account, expressed as Plain-Old-Data (hence the name). @@ -73,6 +74,21 @@ impl PodAccount { } } +impl From for PodAccount { + fn from(a: ethjson::blockchain::Account) -> Self { + PodAccount { + balance: a.balance.into(), + nonce: a.nonce.into(), + code: a.code.into(), + storage: a.storage.into_iter().fold(BTreeMap::new(), |mut acc, (key, value)| { + let key: U256 = key.into(); + acc.insert(H256::from(key), value.into()); + acc + }) + } + } +} + impl fmt::Display for PodAccount { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "(bal={}; nonce={}; code={} bytes, #{}; storage={} items)", self.balance, self.nonce, self.code.len(), self.code.sha3(), self.storage.len()) diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs index b873249ac..5782803ef 100644 --- a/ethcore/src/pod_state.rs +++ b/ethcore/src/pod_state.rs @@ -14,11 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! State of all accounts in the system expressed in Plain Old Data. + use util::*; use pod_account::*; +use ethjson; -#[derive(Debug,Clone,PartialEq,Eq,Default)] /// State of all accounts in the system expressed in Plain Old Data. +#[derive(Debug,Clone,PartialEq,Eq,Default)] pub struct PodState (BTreeMap); impl PodState { @@ -64,6 +67,15 @@ impl FromJson for PodState { } } +impl From for PodState { + fn from(s: ethjson::blockchain::State) -> PodState { + PodState(s.0.into_iter().fold(BTreeMap::new(), |mut acc, (key, value)| { + acc.insert(key.into(), PodAccount::from(value)); + acc + })) + } +} + impl fmt::Display for PodState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (add, acc) in &self.0 { diff --git a/ethcore/src/spec/mod.rs b/ethcore/src/spec/mod.rs index e9c7a0356..b85165d89 100644 --- a/ethcore/src/spec/mod.rs +++ b/ethcore/src/spec/mod.rs @@ -20,3 +20,4 @@ mod genesis; pub mod spec; pub use self::spec::*; +pub use self::genesis::Genesis; diff --git a/json/src/blockchain/account.rs b/json/src/blockchain/account.rs index eb6f0a1dd..990c024c7 100644 --- a/json/src/blockchain/account.rs +++ b/json/src/blockchain/account.rs @@ -19,14 +19,19 @@ use std::collections::BTreeMap; use uint::Uint; use bytes::Bytes; +use hash::H256; /// Blockchain test account deserializer. -#[derive(Debug, PartialEq, Deserialize)] +#[derive(Debug, PartialEq, Deserialize, Clone)] pub struct Account { - balance: Uint, - code: Bytes, - nonce: Uint, - storage: BTreeMap, + /// Balance. + pub balance: Uint, + /// Code. + pub code: Bytes, + /// Nonce. + pub nonce: Uint, + /// Storage. + pub storage: BTreeMap, } #[cfg(test)] @@ -35,7 +40,7 @@ mod tests { use blockchain::account::Account; #[test] - fn header_deserialization() { + fn account_deserialization() { let s = r#"{ "balance" : "0x09184e72a078", "code" : "0x600140600155", diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index d9e879ae9..4783819e5 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -25,15 +25,20 @@ use spec::Genesis; /// Blockchain deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct BlockChain { + /// Genesis block header. #[serde(rename="genesisBlockHeader")] - genesis_block: Header, + pub genesis_block: Header, + /// Genesis block rlp. #[serde(rename="genesisRLP")] - genesis_rlp: Bytes, - blocks: Vec, + pub genesis_rlp: Bytes, + /// Blocks. + pub blocks: Vec, + /// Post state. #[serde(rename="postState")] - post_state: State, + pub post_state: State, + /// Pre state. #[serde(rename="pre")] - pre_state: State, + pub pre_state: State, } impl BlockChain { diff --git a/json/src/blockchain/state.rs b/json/src/blockchain/state.rs index 2af0dbf21..51e77e95e 100644 --- a/json/src/blockchain/state.rs +++ b/json/src/blockchain/state.rs @@ -22,8 +22,8 @@ use hash::Address; use blockchain::account::Account; /// Blockchain test state deserializer. -#[derive(Debug, PartialEq, Deserialize)] -pub struct State(BTreeMap); +#[derive(Debug, PartialEq, Deserialize, Clone)] +pub struct State(pub BTreeMap); impl Deref for State { type Target = BTreeMap; diff --git a/parity/rpctest.rs b/parity/rpctest.rs index 182f6dfed..ca12eed93 100644 --- a/parity/rpctest.rs +++ b/parity/rpctest.rs @@ -18,11 +18,15 @@ extern crate docopt; extern crate rustc_serialize; extern crate serde_json; extern crate ethjson; +extern crate ethcore; use std::process; use std::fs::File; use std::path::Path; use docopt::Docopt; +use ethcore::spec::Genesis; +use ethcore::pod_state::PodState; +use ethcore::ethereum; const USAGE: &'static str = r#" Parity rpctest client. @@ -70,7 +74,15 @@ impl Configuration { process::exit(3); }); + let genesis = Genesis::from(blockchain.genesis()); + let state = PodState::from(blockchain.pre_state.clone()); + let mut spec = ethereum::new_frontier_test(); + spec.set_genesis_state(state); + spec.overwrite_genesis_params(genesis); + assert!(spec.is_state_root_valid()); + //let temp = RandomTempPath::new(); + //spec. } } From 755faf37e3702487099519a724d36006201e12d0 Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 17 Mar 2016 23:58:30 +0100 Subject: [PATCH 57/91] running rpc tests --- parity/rpctest.rs | 57 ++++++++++++++++++++++++++++++++++++++--- rpc/src/v1/mod.rs | 3 +-- rpc/src/v1/tests/mod.rs | 6 ++++- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/parity/rpctest.rs b/parity/rpctest.rs index ca12eed93..d972a779e 100644 --- a/parity/rpctest.rs +++ b/parity/rpctest.rs @@ -14,19 +14,32 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +extern crate ctrlc; extern crate docopt; extern crate rustc_serialize; extern crate serde_json; extern crate ethjson; +extern crate ethcore_util as util; extern crate ethcore; +extern crate ethcore_devtools as devtools; +extern crate ethcore_rpc as rpc; +use std::collections::HashMap; +use std::sync::{Arc, Mutex, Condvar}; use std::process; use std::fs::File; use std::path::Path; use docopt::Docopt; +use ctrlc::CtrlC; use ethcore::spec::Genesis; use ethcore::pod_state::PodState; use ethcore::ethereum; +use ethcore::client::{BlockChainClient, Client, ClientConfig}; +use devtools::RandomTempPath; +use util::io::IoChannel; +use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider}; +use rpc::v1::{Eth, EthClient}; +use util::panics::MayPanic; const USAGE: &'static str = r#" Parity rpctest client. @@ -34,13 +47,22 @@ Parity rpctest client. Copyright 2015, 2016 Ethcore (UK) Limited Usage: - parity --json --name + parity --json --name [options] + parity --help + +Options: + --jsonrpc-addr HOST Specify the hostname portion of the JSONRPC API + server [default: 127.0.0.1]. + --jsonrpc-port PORT Specify the port portion of the JSONRPC API server + [default: 8545]. "#; #[derive(Debug, RustcDecodable)] struct Args { arg_test_file: String, arg_test_name: String, + flag_jsonrpc_addr: String, + flag_jsonrpc_port: u16, } struct Configuration { @@ -81,8 +103,37 @@ impl Configuration { spec.overwrite_genesis_params(genesis); assert!(spec.is_state_root_valid()); - //let temp = RandomTempPath::new(); - //spec. + let temp = RandomTempPath::new(); + { + let client: Arc = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap(); + for b in &blockchain.blocks_rlp() { + let _ = client.import_block(b.clone()); + client.flush_queue(); + client.import_verified_blocks(&IoChannel::disconnected()); + } + let sync = Arc::new(TestSyncProvider::new(SyncConfig { + protocol_version: 65, + num_peers: 120 + })); + + let miner = Arc::new(TestMinerService::default()); + let accounts = Arc::new(TestAccountProvider::new(HashMap::new())); + let server = rpc::RpcServer::new(); + server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner).to_delegate()); + + let url = format!("{}:{}", self.args.flag_jsonrpc_addr, self.args.flag_jsonrpc_port); + let panic_handler = server.start_http(url.as_ref(), "*", 1); + let exit = Arc::new(Condvar::new()); + + let e = exit.clone(); + CtrlC::set_handler(move || { e.notify_all(); }); + + let e = exit.clone(); + panic_handler.on_panic(move |_reason| { e.notify_all(); }); + + let mutex = Mutex::new(()); + let _ = exit.wait(mutex.lock().unwrap()).unwrap(); + } } } diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index b82a20e89..c81f58156 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -23,8 +23,7 @@ mod impls; mod types; mod helpers; -#[cfg(test)] -mod tests; +pub mod tests; pub use self::traits::{Web3, Eth, EthFilter, Personal, Net}; pub use self::impls::*; diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs index 21085a0fd..7a6340ce1 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/rpc/src/v1/tests/mod.rs @@ -16,8 +16,12 @@ //!TODO: load custom blockchain state and test +pub mod helpers; +#[cfg(test)] mod eth; +#[cfg(test)] mod net; +#[cfg(test)] mod web3; -mod helpers; +#[cfg(test)] mod personal; From 9ce75a173ee0b074124b2bc6ffff836270511d89 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 18:08:28 +0100 Subject: [PATCH 58/91] fixed name of rpctest executable in rpctest --help --- parity/rpctest.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parity/rpctest.rs b/parity/rpctest.rs index d972a779e..fc4e2983f 100644 --- a/parity/rpctest.rs +++ b/parity/rpctest.rs @@ -47,8 +47,8 @@ Parity rpctest client. Copyright 2015, 2016 Ethcore (UK) Limited Usage: - parity --json --name [options] - parity --help + rpctest --json --name [options] + rpctest --help Options: --jsonrpc-addr HOST Specify the hostname portion of the JSONRPC API From dffa9bcef6e429636783dc6df7fd94a1e6134db2 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 18:16:22 +0100 Subject: [PATCH 59/91] fixed compilation with --release flag --- parity/rpctest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/rpctest.rs b/parity/rpctest.rs index fc4e2983f..4fd31b134 100644 --- a/parity/rpctest.rs +++ b/parity/rpctest.rs @@ -36,7 +36,7 @@ use ethcore::pod_state::PodState; use ethcore::ethereum; use ethcore::client::{BlockChainClient, Client, ClientConfig}; use devtools::RandomTempPath; -use util::io::IoChannel; +use util::IoChannel; use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider}; use rpc::v1::{Eth, EthClient}; use util::panics::MayPanic; From ac3acdef714dda3e4d17d81edf2d8213879439c4 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 19:08:57 +0100 Subject: [PATCH 60/91] linear -> pricing --- ethcore/res/ethereum/frontier.json | 8 +++---- ethcore/res/ethereum/frontier_like_test.json | 8 +++---- ethcore/res/ethereum/frontier_test.json | 8 +++---- ethcore/res/ethereum/homestead_test.json | 8 +++---- ethcore/res/ethereum/morden.json | 8 +++---- ethcore/res/ethereum/olympic.json | 8 +++---- ethcore/res/null_morden.json | 8 +++---- json/src/spec/account.rs | 2 +- json/src/spec/builtin.rs | 23 +++++++++++++++++--- json/src/spec/spec.rs | 8 +++---- 10 files changed, 53 insertions(+), 36 deletions(-) diff --git a/ethcore/res/ethereum/frontier.json b/ethcore/res/ethereum/frontier.json index cd66ad3f1..7a1662d8c 100644 --- a/ethcore/res/ethereum/frontier.json +++ b/ethcore/res/ethereum/frontier.json @@ -33,10 +33,10 @@ "enode://248f12bc8b18d5289358085520ac78cd8076485211e6d96ab0bc93d6cd25442db0ce3a937dc404f64f207b0b9aed50e25e98ce32af5ac7cb321ff285b97de485@parity-node-zero.ethcore.io:30303" ], "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index ebfbc2383..803e593be 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -26,9 +26,9 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } } } } diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index 227ad1bc3..f1a75881a 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -26,9 +26,9 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } } } } diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index 1fb5dff80..8f13eb042 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -26,9 +26,9 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } } } } diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index e9f8e0e99..a5230acf4 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -29,10 +29,10 @@ "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303" ], "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index b3dfc1ed8..872877429 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -26,10 +26,10 @@ "gasLimit": "0x2fefd8" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "e6716f9544a56c530d868e4bfbacb172315bdead": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "b9c015918bdaba24b4ff057a92a3873d6eb201be": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index 46507ff95..49795c337 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -26,10 +26,10 @@ "gasLimit": "0x2fefd8" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/json/src/spec/account.rs b/json/src/spec/account.rs index 8c98f89d9..f4cce3fc8 100644 --- a/json/src/spec/account.rs +++ b/json/src/spec/account.rs @@ -36,7 +36,7 @@ mod tests { fn account_deserialization() { let s = r#"{ "balance": "1", - "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } + "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }"#; let _deserialized: Account = serde_json::from_str(s).unwrap(); // TODO: validate all fields diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs index f49367ecb..24f83b1d6 100644 --- a/json/src/spec/builtin.rs +++ b/json/src/spec/builtin.rs @@ -16,18 +16,35 @@ //! Spec builtin deserialization. -/// Linear builin options. +use serde::de::{Deserialize, Deserializer}; + +/// Linear pricing. #[derive(Debug, PartialEq, Deserialize)] pub struct Linear { base: u64, word: u64, } +/// Pricing variants. +#[derive(Debug, PartialEq)] +pub enum Pricing { + /// Linear pricing. + Linear(Linear), +} + +impl Deserialize for Pricing { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + Deserialize::deserialize(deserializer).map(Pricing::Linear) + } +} + + /// Spec builtin. #[derive(Debug, PartialEq, Deserialize)] pub struct Builtin { name: String, - linear: Linear, + pricing: Pricing, } #[cfg(test)] @@ -39,7 +56,7 @@ mod tests { fn builtin_deserialization() { let s = r#"{ "name": "ecrecover", - "linear": { "base": 3000, "word": 0 } + "pricing": { "base": 3000, "word": 0 } }"#; let _deserialized: Builtin = serde_json::from_str(s).unwrap(); // TODO: validate all fields diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index 79662b19a..0d17d0829 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -71,10 +71,10 @@ mod tests { "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303" ], "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "linear": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "linear": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "linear": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } }"#; From d87286c5c311dc37034933d9f14da5237c3d44a3 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 19:16:46 +0100 Subject: [PATCH 61/91] updated rpc helpers docs --- rpc/src/v1/tests/helpers/account_provider.rs | 3 +++ rpc/src/v1/tests/helpers/external_miner.rs | 1 + rpc/src/v1/tests/helpers/miner_service.rs | 5 +++++ rpc/src/v1/tests/helpers/sync_provider.rs | 7 +++++++ 4 files changed, 16 insertions(+) diff --git a/rpc/src/v1/tests/helpers/account_provider.rs b/rpc/src/v1/tests/helpers/account_provider.rs index ce5b76b44..9cbf853ae 100644 --- a/rpc/src/v1/tests/helpers/account_provider.rs +++ b/rpc/src/v1/tests/helpers/account_provider.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Test implementation of account provider. + use std::sync::RwLock; use std::collections::HashMap; use std::io; @@ -42,6 +44,7 @@ impl TestAccount { /// Test account provider. pub struct TestAccountProvider { accounts: RwLock>, + /// Added accounts passwords. pub adds: RwLock>, } diff --git a/rpc/src/v1/tests/helpers/external_miner.rs b/rpc/src/v1/tests/helpers/external_miner.rs index a5111b302..ef3714440 100644 --- a/rpc/src/v1/tests/helpers/external_miner.rs +++ b/rpc/src/v1/tests/helpers/external_miner.rs @@ -26,6 +26,7 @@ pub struct TestExternalMiner { } impl TestExternalMiner { + /// Creates new external miner. pub fn new(hashrates: Arc>>) -> Self { TestExternalMiner { hashrates: hashrates, diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index ad9dcaedd..22e210392 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Test implementation of miner service. + use util::{Address, H256, Bytes}; use util::standard::*; use ethcore::error::Error; @@ -22,8 +24,11 @@ use ethcore::block::ClosedBlock; use ethcore::transaction::SignedTransaction; use ethminer::{MinerService, MinerStatus, AccountDetails}; +/// Test miner service. pub struct TestMinerService { + /// Imported transactions. pub imported_transactions: RwLock>, + /// Latest closed block. pub latest_closed_block: Mutex>, } diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index 5b4b5b099..222c4c7b9 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -14,15 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Test implementation of SyncProvider. + use ethsync::{SyncProvider, SyncStatus, SyncState}; use std::sync::{RwLock}; +/// TestSyncProvider config. pub struct Config { + /// Protocol version. pub protocol_version: u8, + /// Number of peers. pub num_peers: usize, } +/// Test sync provider. pub struct TestSyncProvider { + /// Sync status. pub status: RwLock, } From 32cc0bddf6233ef996ba237098afb69a7451f152 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 19:31:31 +0100 Subject: [PATCH 62/91] fixed od builting parsing --- ethcore/src/builtin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 5589a2525..fbf123ec7 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -19,7 +19,7 @@ use crypto::sha2::Sha256; use crypto::ripemd160::Ripemd160; use crypto::digest::Digest; -/// Definition of a contract whose implementation is built-in. +/// Definition of a contract whose implementation is built-in. pub struct Builtin { /// The gas cost of running this built-in for the given size of input data. pub cost: Box U256>, // TODO: U256 should be bignum. @@ -63,11 +63,11 @@ impl Builtin { /// Create a builtin from JSON. /// - /// JSON must be of the form `{ "name": "identity", "linear": {"base": 10, "word": 20} }`. + /// JSON must be of the form `{ "name": "identity", "pricing": {"base": 10, "word": 20} }`. pub fn from_json(json: &Json) -> Option { // NICE: figure out a more convenient means of handing errors here. if let Json::String(ref name) = json["name"] { - if let Json::Object(ref o) = json["linear"] { + if let Json::Object(ref o) = json["pricing"] { if let Json::U64(ref word) = o["word"] { if let Json::U64(ref base) = o["base"] { return Self::from_named_linear(&name[..], *base as usize, *word as usize); From c5a4993e3949995b2de4e4a6366a52c680422eb5 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 20:17:25 +0100 Subject: [PATCH 63/91] fixed failing builin test --- ethcore/src/builtin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index fbf123ec7..0e857335e 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -274,7 +274,7 @@ fn from_named_linear() { #[test] fn from_json() { - let text = "{ \"name\": \"identity\", \"linear\": {\"base\": 10, \"word\": 20} }"; + let text = "{ \"name\": \"identity\", \"pricing\": {\"base\": 10, \"word\": 20} }"; let json = Json::from_str(text).unwrap(); let b = Builtin::from_json(&json).unwrap(); assert_eq!((*b.cost)(0), U256::from(10)); From f3ad643b694663b93a378c53d6d8aeeb29fd3966 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 22:54:36 +0100 Subject: [PATCH 64/91] pricing { linear: {} } --- ethcore/res/ethereum/frontier.json | 8 ++++---- ethcore/res/ethereum/frontier_like_test.json | 8 ++++---- ethcore/res/ethereum/frontier_test.json | 8 ++++---- ethcore/res/ethereum/homestead_test.json | 8 ++++---- ethcore/res/ethereum/morden.json | 8 ++++---- ethcore/res/ethereum/olympic.json | 8 ++++---- ethcore/res/null_morden.json | 8 ++++---- ethcore/src/builtin.rs | 10 ++++++---- json/src/spec/account.rs | 2 +- json/src/spec/builtin.rs | 15 +++------------ json/src/spec/spec.rs | 8 ++++---- 11 files changed, 42 insertions(+), 49 deletions(-) diff --git a/ethcore/res/ethereum/frontier.json b/ethcore/res/ethereum/frontier.json index 7a1662d8c..8f9209179 100644 --- a/ethcore/res/ethereum/frontier.json +++ b/ethcore/res/ethereum/frontier.json @@ -33,10 +33,10 @@ "enode://248f12bc8b18d5289358085520ac78cd8076485211e6d96ab0bc93d6cd25442db0ce3a937dc404f64f207b0b9aed50e25e98ce32af5ac7cb321ff285b97de485@parity-node-zero.ethcore.io:30303" ], "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 803e593be..49b39cde7 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -26,9 +26,9 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, } } diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index f1a75881a..79f47b2e6 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -26,9 +26,9 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, } } diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index 8f13eb042..0f0e630dd 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -26,9 +26,9 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } } + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } } } diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index a5230acf4..2cf4785db 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -29,10 +29,10 @@ "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303" ], "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index 872877429..365a8167c 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -26,10 +26,10 @@ "gasLimit": "0x2fefd8" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "e6716f9544a56c530d868e4bfbacb172315bdead": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "b9c015918bdaba24b4ff057a92a3873d6eb201be": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index 49795c337..70b48fbdb 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -26,10 +26,10 @@ "gasLimit": "0x2fefd8" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 0e857335e..2ee8e24b1 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -68,9 +68,11 @@ impl Builtin { // NICE: figure out a more convenient means of handing errors here. if let Json::String(ref name) = json["name"] { if let Json::Object(ref o) = json["pricing"] { - if let Json::U64(ref word) = o["word"] { - if let Json::U64(ref base) = o["base"] { - return Self::from_named_linear(&name[..], *base as usize, *word as usize); + if let Json::Object(ref o) = o["linear"] { + if let Json::U64(ref word) = o["word"] { + if let Json::U64(ref base) = o["base"] { + return Self::from_named_linear(&name[..], *base as usize, *word as usize); + } } } } @@ -274,7 +276,7 @@ fn from_named_linear() { #[test] fn from_json() { - let text = "{ \"name\": \"identity\", \"pricing\": {\"base\": 10, \"word\": 20} }"; + let text = r#"{"name": "identity", "pricing": {"linear": {"base": 10, "word": 20}}}"#; let json = Json::from_str(text).unwrap(); let b = Builtin::from_json(&json).unwrap(); assert_eq!((*b.cost)(0), U256::from(10)); diff --git a/json/src/spec/account.rs b/json/src/spec/account.rs index f4cce3fc8..1440b1bdc 100644 --- a/json/src/spec/account.rs +++ b/json/src/spec/account.rs @@ -36,7 +36,7 @@ mod tests { fn account_deserialization() { let s = r#"{ "balance": "1", - "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } + "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }"#; let _deserialized: Account = serde_json::from_str(s).unwrap(); // TODO: validate all fields diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs index 24f83b1d6..21f8a2ac1 100644 --- a/json/src/spec/builtin.rs +++ b/json/src/spec/builtin.rs @@ -16,8 +16,6 @@ //! Spec builtin deserialization. -use serde::de::{Deserialize, Deserializer}; - /// Linear pricing. #[derive(Debug, PartialEq, Deserialize)] pub struct Linear { @@ -26,20 +24,13 @@ pub struct Linear { } /// Pricing variants. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Deserialize)] pub enum Pricing { /// Linear pricing. + #[serde(rename="linear")] Linear(Linear), } -impl Deserialize for Pricing { - fn deserialize(deserializer: &mut D) -> Result - where D: Deserializer { - Deserialize::deserialize(deserializer).map(Pricing::Linear) - } -} - - /// Spec builtin. #[derive(Debug, PartialEq, Deserialize)] pub struct Builtin { @@ -56,7 +47,7 @@ mod tests { fn builtin_deserialization() { let s = r#"{ "name": "ecrecover", - "pricing": { "base": 3000, "word": 0 } + "pricing": { "linear": { "base": 3000, "word": 0 } } }"#; let _deserialized: Builtin = serde_json::from_str(s).unwrap(); // TODO: validate all fields diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index 0d17d0829..2dd4ac486 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -71,10 +71,10 @@ mod tests { "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303" ], "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "base": 3000, "word": 0 } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "base": 60, "word": 12 } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "base": 600, "word": 120 } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "base": 15, "word": 3 } } }, + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } }"#; From 086e45671be9c49dccc6f07c1dff97693e8b8562 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 22:57:26 +0100 Subject: [PATCH 65/91] removed warnings by adding missing documentation --- rpc/src/v1/tests/helpers/account_provider.rs | 1 + rpc/src/v1/tests/helpers/external_miner.rs | 1 + rpc/src/v1/tests/helpers/mod.rs | 2 ++ rpc/src/v1/tests/helpers/sync_provider.rs | 1 + 4 files changed, 5 insertions(+) diff --git a/rpc/src/v1/tests/helpers/account_provider.rs b/rpc/src/v1/tests/helpers/account_provider.rs index 9cbf853ae..614aba346 100644 --- a/rpc/src/v1/tests/helpers/account_provider.rs +++ b/rpc/src/v1/tests/helpers/account_provider.rs @@ -33,6 +33,7 @@ pub struct TestAccount { } impl TestAccount { + /// Creates new test account. pub fn new(password: &str) -> Self { TestAccount { unlocked: false, diff --git a/rpc/src/v1/tests/helpers/external_miner.rs b/rpc/src/v1/tests/helpers/external_miner.rs index ef3714440..1799c36c5 100644 --- a/rpc/src/v1/tests/helpers/external_miner.rs +++ b/rpc/src/v1/tests/helpers/external_miner.rs @@ -22,6 +22,7 @@ use v1::helpers::ExternalMinerService; /// Test ExternalMinerService; pub struct TestExternalMiner { + /// External miners hashrates. pub hashrates: Arc>> } diff --git a/rpc/src/v1/tests/helpers/mod.rs b/rpc/src/v1/tests/helpers/mod.rs index fc652e7d6..c9db61f6d 100644 --- a/rpc/src/v1/tests/helpers/mod.rs +++ b/rpc/src/v1/tests/helpers/mod.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Test rpc services. + mod account_provider; mod sync_provider; mod miner_service; diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index 222c4c7b9..48b4f55a9 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -34,6 +34,7 @@ pub struct TestSyncProvider { } impl TestSyncProvider { + /// Creates new sync provider. pub fn new(config: Config) -> Self { TestSyncProvider { status: RwLock::new(SyncStatus { From cb246c26c0cac1afb4557409fe778bf2c5f9fd21 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 18 Mar 2016 23:56:51 +0100 Subject: [PATCH 66/91] fixed invalid json files --- ethcore/res/ethereum/frontier_like_test.json | 2 +- ethcore/res/ethereum/frontier_test.json | 2 +- ethcore/res/ethereum/olympic.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 49b39cde7..376b369c4 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -29,6 +29,6 @@ "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } } } diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index 79f47b2e6..92e8f5877 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -29,6 +29,6 @@ "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } } } diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index 365a8167c..0cc2e6a57 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -29,7 +29,7 @@ "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "e6716f9544a56c530d868e4bfbacb172315bdead": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "b9c015918bdaba24b4ff057a92a3873d6eb201be": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, From 8f1618687c365c01b43d8dd4cfba8f4f16910258 Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 11:02:44 +0100 Subject: [PATCH 67/91] fixed parsing blockchain file, added default account to rpc tests --- ethcore/src/pod_account.rs | 3 ++- json/src/blockchain/account.rs | 2 +- parity/rpctest.rs | 10 +++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 8f38326ca..387679da9 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -82,7 +82,8 @@ impl From for PodAccount { code: a.code.into(), storage: a.storage.into_iter().fold(BTreeMap::new(), |mut acc, (key, value)| { let key: U256 = key.into(); - acc.insert(H256::from(key), value.into()); + let value: U256 = value.into(); + acc.insert(H256::from(key), H256::from(value)); acc }) } diff --git a/json/src/blockchain/account.rs b/json/src/blockchain/account.rs index 990c024c7..1c51f2b74 100644 --- a/json/src/blockchain/account.rs +++ b/json/src/blockchain/account.rs @@ -31,7 +31,7 @@ pub struct Account { /// Nonce. pub nonce: Uint, /// Storage. - pub storage: BTreeMap, + pub storage: BTreeMap, } #[cfg(test)] diff --git a/parity/rpctest.rs b/parity/rpctest.rs index 4fd31b134..dba188474 100644 --- a/parity/rpctest.rs +++ b/parity/rpctest.rs @@ -37,9 +37,10 @@ use ethcore::ethereum; use ethcore::client::{BlockChainClient, Client, ClientConfig}; use devtools::RandomTempPath; use util::IoChannel; -use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider}; +use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider, TestAccount}; use rpc::v1::{Eth, EthClient}; use util::panics::MayPanic; +use util::hash::Address; const USAGE: &'static str = r#" Parity rpctest client. @@ -86,8 +87,9 @@ impl Configuration { process::exit(1); }); - let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|_| { + let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|err| { println!("Invalid json file."); + println!("{:?}", err); process::exit(2); }); @@ -117,7 +119,9 @@ impl Configuration { })); let miner = Arc::new(TestMinerService::default()); - let accounts = Arc::new(TestAccountProvider::new(HashMap::new())); + let mut accs = HashMap::new(); + accs.insert(Address::from(1), TestAccount::new("test")); + let accounts = Arc::new(TestAccountProvider::new(accs)); let server = rpc::RpcServer::new(); server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner).to_delegate()); From 0fc605faceff9d649c855560af4ea0923dd4884f Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 11:44:36 +0100 Subject: [PATCH 68/91] rpc tests, now 421 passing / 116 failing --- rpc/src/v1/impls/eth.rs | 3 ++- rpc/src/v1/types/block.rs | 6 ++++-- rpc/src/v1/types/bytes.rs | 9 +-------- rpc/src/v1/types/transaction.rs | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 5cd1b2966..2306f937d 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -103,6 +103,7 @@ impl EthClient timestamp: U256::from(view.timestamp()), difficulty: view.difficulty(), total_difficulty: total_difficulty, + nonce: view.seal().get(1).map_or_else(H64::zero, |r| H64::from_slice(r)), uncles: vec![], transactions: { if include_txs { @@ -111,7 +112,7 @@ impl EthClient BlockTransactions::Hashes(block_view.transaction_hashes()) } }, - extra_data: Bytes::default() + extra_data: Bytes::new(view.extra_data()) }; to_value(&block) }, diff --git a/rpc/src/v1/types/block.rs b/rpc/src/v1/types/block.rs index 2457efcf8..a7b75a561 100644 --- a/rpc/src/v1/types/block.rs +++ b/rpc/src/v1/types/block.rs @@ -63,6 +63,7 @@ pub struct Block { pub difficulty: U256, #[serde(rename="totalDifficulty")] pub total_difficulty: U256, + pub nonce: H64, pub uncles: Vec, pub transactions: BlockTransactions } @@ -78,7 +79,7 @@ mod tests { fn test_serialize_block_transactions() { let t = BlockTransactions::Full(vec![Transaction::default()]); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}]"#); + assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x"}]"#); let t = BlockTransactions::Hashes(vec![H256::default()]); let serialized = serde_json::to_string(&t).unwrap(); @@ -104,11 +105,12 @@ mod tests { timestamp: U256::default(), difficulty: U256::default(), total_difficulty: U256::default(), + nonce: H64::default(), uncles: vec![], transactions: BlockTransactions::Hashes(vec![]) }; let serialized = serde_json::to_string(&block).unwrap(); - assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","author":"0x0000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x00","gasUsed":"0x00","gasLimit":"0x00","extraData":"0x00","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x00","difficulty":"0x00","totalDifficulty":"0x00","uncles":[],"transactions":[]}"#); + assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","author":"0x0000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x00","gasUsed":"0x00","gasLimit":"0x00","extraData":"0x","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x00","difficulty":"0x00","totalDifficulty":"0x00","nonce":"0x0000000000000000","uncles":[],"transactions":[]}"#); } } diff --git a/rpc/src/v1/types/bytes.rs b/rpc/src/v1/types/bytes.rs index 0b14c30e8..8c47806f8 100644 --- a/rpc/src/v1/types/bytes.rs +++ b/rpc/src/v1/types/bytes.rs @@ -20,7 +20,7 @@ use serde::de::Visitor; use util::common::FromHex; /// Wrapper structure around vector of bytes. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Default)] pub struct Bytes(Vec); impl Bytes { @@ -31,13 +31,6 @@ impl Bytes { pub fn to_vec(self) -> Vec { let Bytes(x) = self; x } } -impl Default for Bytes { - fn default() -> Self { - // default serialized value is 0x00 - Bytes(vec![0]) - } -} - impl Serialize for Bytes { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 232cf0bf3..d809d19b4 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -67,7 +67,7 @@ mod tests { fn test_transaction_serialize() { let t = Transaction::default(); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}"#); + assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x"}"#); } } From 9bcc6c9e69930274e499245ce2ab9356d0ea75db Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 12:23:48 +0100 Subject: [PATCH 69/91] next batch of rpc fixes, 103 still failing --- parity/rpctest.rs | 3 ++- rpc/src/v1/impls/eth.rs | 18 +++++++++--------- rpc/src/v1/tests/helpers/miner_service.rs | 2 +- rpc/src/v1/types/block.rs | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/parity/rpctest.rs b/parity/rpctest.rs index dba188474..6cc747959 100644 --- a/parity/rpctest.rs +++ b/parity/rpctest.rs @@ -38,7 +38,7 @@ use ethcore::client::{BlockChainClient, Client, ClientConfig}; use devtools::RandomTempPath; use util::IoChannel; use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider, TestAccount}; -use rpc::v1::{Eth, EthClient}; +use rpc::v1::{Eth, EthClient, EthFilter, EthFilterClient}; use util::panics::MayPanic; use util::hash::Address; @@ -124,6 +124,7 @@ impl Configuration { let accounts = Arc::new(TestAccountProvider::new(accs)); let server = rpc::RpcServer::new(); server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner).to_delegate()); + server.add_delegate(EthFilterClient::new(&client, &miner).to_delegate()); let url = format!("{}:{}", self.args.flag_jsonrpc_addr, self.args.flag_jsonrpc_port); let panic_handler = server.start_http(url.as_ref(), "*", 1); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 2306f937d..9b2588670 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -104,7 +104,7 @@ impl EthClient difficulty: view.difficulty(), total_difficulty: total_difficulty, nonce: view.seal().get(1).map_or_else(H64::zero, |r| H64::from_slice(r)), - uncles: vec![], + uncles: block_view.uncle_hashes(), transactions: { if include_txs { BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect()) @@ -230,8 +230,8 @@ impl Eth for EthClient fn block_transaction_count_by_hash(&self, params: Params) -> Result { from_params::<(H256,)>(params) .and_then(|(hash,)| // match - to_value(&take_weak!(self.client).block(BlockId::Hash(hash)) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count())))) + take_weak!(self.client).block(BlockId::Hash(hash)) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).transactions_count())))) } fn block_transaction_count_by_number(&self, params: Params) -> Result { @@ -240,24 +240,24 @@ impl Eth for EthClient BlockNumber::Pending => to_value( &U256::from(take_weak!(self.miner).status().transactions_in_pending_block) ), - _ => to_value(&take_weak!(self.client).block(block_number.into()) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count()))) + _ => take_weak!(self.client).block(block_number.into()) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).transactions_count()))) }) } fn block_uncles_count_by_hash(&self, params: Params) -> Result { from_params::<(H256,)>(params) .and_then(|(hash,)| - to_value(&take_weak!(self.client).block(BlockId::Hash(hash)) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).uncles_count())))) + take_weak!(self.client).block(BlockId::Hash(hash)) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).uncles_count())))) } fn block_uncles_count_by_number(&self, params: Params) -> Result { from_params::<(BlockNumber,)>(params) .and_then(|(block_number,)| match block_number { BlockNumber::Pending => to_value(&U256::from(0)), - _ => to_value(&take_weak!(self.client).block(block_number.into()) - .map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).uncles_count()))) + _ => take_weak!(self.client).block(block_number.into()) + .map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).uncles_count()))) }) } diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 22e210392..7f07341bf 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -57,7 +57,7 @@ impl MinerService for TestMinerService { where T: Fn(&Address) -> AccountDetails { unimplemented!(); } /// Returns hashes of transactions currently in pending - fn pending_transactions_hashes(&self) -> Vec { unimplemented!(); } + fn pending_transactions_hashes(&self) -> Vec { vec![] } /// Removes all transactions from the queue and restart mining operation. fn clear_and_reset(&self, _chain: &BlockChainClient) { unimplemented!(); } diff --git a/rpc/src/v1/types/block.rs b/rpc/src/v1/types/block.rs index a7b75a561..ac334dd2b 100644 --- a/rpc/src/v1/types/block.rs +++ b/rpc/src/v1/types/block.rs @@ -64,7 +64,7 @@ pub struct Block { #[serde(rename="totalDifficulty")] pub total_difficulty: U256, pub nonce: H64, - pub uncles: Vec, + pub uncles: Vec, pub transactions: BlockTransactions } From 2b8a151b8222b7b50e000f817da4e12531e16e4c Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 12:55:36 +0100 Subject: [PATCH 70/91] fixed failing eth rpc tests --- rpc/src/v1/tests/eth.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 389de103b..a5f318350 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -224,7 +224,7 @@ fn rpc_eth_block_transaction_count_by_hash() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); } @@ -264,7 +264,7 @@ fn rpc_eth_uncle_count_by_block_hash() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); } From 49be60e9848d57960fef9d504a58deef163536ee Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 18:46:28 +0100 Subject: [PATCH 71/91] test ethjson module on travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5d6de65c2..f7ac723e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ env: global: # GH_TOKEN - secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw= - - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer" + - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer -p ethjson" - ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}" - KCOV_FEATURES="" - KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov" @@ -70,6 +70,7 @@ after_success: | $KCOV_CMD target/debug/deps/ethsync-* && $KCOV_CMD target/debug/deps/ethcore_rpc-* && $KCOV_CMD target/debug/deps/ethminer-* && + $KCOV_CMD target/debug/deps/ethjson-* && $KCOV_CMD target/debug/parity-* && [ $TRAVIS_BRANCH = master ] && [ $TRAVIS_PULL_REQUEST = false ] && From a10160bd56b1b097e4604604a4000cd855aef01d Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 18:13:14 +0100 Subject: [PATCH 72/91] use ethjson module to load chain json tests --- ethcore/src/block.rs | 2 +- ethcore/src/json_tests/chain.rs | 29 ++++++++++++++--------------- ethcore/src/pod_state.rs | 2 +- json/src/blockchain/account.rs | 1 - json/src/blockchain/block.rs | 6 +++--- json/src/blockchain/blockchain.rs | 11 +++++------ json/src/blockchain/test.rs | 10 ++++++++++ json/src/bytes.rs | 8 ++------ 8 files changed, 36 insertions(+), 33 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index d4aa35445..e53cbfd61 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -438,7 +438,7 @@ mod tests { open_block.push_uncle(uncle1_header).unwrap(); open_block.push_uncle(uncle2_header).unwrap(); let b = open_block.close().seal(engine.deref(), vec![]).unwrap(); - + let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 89bd5da2b..5e2d51594 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -16,18 +16,18 @@ use super::test_common::*; use client::{BlockChainClient, Client, ClientConfig}; -use pod_state::*; use block::Block; use ethereum; use tests::helpers::*; use devtools::*; +use spec::Genesis; pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { init_log(); - let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); + let tests = ethjson::blockchain::Test.load(json_data).unwrap(); let mut failed = Vec::new(); - for (name, test) in json.as_object().unwrap() { + for (name, blockchain) in tests.deref() { let mut fail = false; { let mut fail_unless = |cond: bool| if !cond && !fail { @@ -39,37 +39,36 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { flush!(" - {}...", 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 = 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()); + + let genesis = Genesis::from(blockchain.genesis()); + let state = From::from(blockchain.pre_state.clone()); + spec.set_genesis_state(state); + spec.overwrite_genesis_params(genesis); assert!(spec.is_state_root_valid()); - let genesis_hash = spec.genesis_header().hash(); - assert_eq!(genesis_hash, H256::from_json(&test.find("genesisBlockHeader").unwrap()["hash"])); let temp = RandomTempPath::new(); { let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap(); - assert_eq!(client.chain_info().best_block_hash, genesis_hash); - for (b, is_valid) in blocks.into_iter() { + for b in &blockchain.blocks_rlp() { if Block::is_good(&b) { let _ = client.import_block(b.clone()); + client.flush_queue(); + client.import_verified_blocks(&IoChannel::disconnected()); } - 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"])); + fail_unless(client.chain_info().best_block_hash == blockchain.best_block.clone().into()); } } + if !fail { flushln!("ok"); } } + println!("!!! {:?} tests from failed.", failed.len()); failed } diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs index 5782803ef..7ebfed78b 100644 --- a/ethcore/src/pod_state.rs +++ b/ethcore/src/pod_state.rs @@ -21,7 +21,7 @@ use pod_account::*; use ethjson; /// State of all accounts in the system expressed in Plain Old Data. -#[derive(Debug,Clone,PartialEq,Eq,Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct PodState (BTreeMap); impl PodState { diff --git a/json/src/blockchain/account.rs b/json/src/blockchain/account.rs index 1c51f2b74..ca69409fc 100644 --- a/json/src/blockchain/account.rs +++ b/json/src/blockchain/account.rs @@ -19,7 +19,6 @@ use std::collections::BTreeMap; use uint::Uint; use bytes::Bytes; -use hash::H256; /// Blockchain test account deserializer. #[derive(Debug, PartialEq, Deserialize, Clone)] diff --git a/json/src/blockchain/block.rs b/json/src/blockchain/block.rs index 190102ae5..03522a2c9 100644 --- a/json/src/blockchain/block.rs +++ b/json/src/blockchain/block.rs @@ -24,11 +24,11 @@ use blockchain::transaction::Transaction; #[derive(Debug, PartialEq, Deserialize)] pub struct Block { #[serde(rename="blockHeader")] - header: Header, + header: Option
, rlp: Bytes, - transactions: Vec, + transactions: Option>, #[serde(rename="uncleHeaders")] - uncles: Vec
, + uncles: Option>, } impl Block { diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 4783819e5..98392b983 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -17,6 +17,7 @@ //! Blockchain deserialization. use bytes::Bytes; +use hash::H256; use blockchain::state::State; use blockchain::header::Header; use blockchain::block::Block; @@ -30,7 +31,7 @@ pub struct BlockChain { pub genesis_block: Header, /// Genesis block rlp. #[serde(rename="genesisRLP")] - pub genesis_rlp: Bytes, + pub genesis_rlp: Option, /// Blocks. pub blocks: Vec, /// Post state. @@ -39,14 +40,12 @@ pub struct BlockChain { /// Pre state. #[serde(rename="pre")] pub pre_state: State, + /// Hash of best block. + #[serde(rename="lastblockhash")] + pub best_block: H256 } impl BlockChain { - /// Returns genesis block rlp. - pub fn genesis_rlp(&self) -> Vec { - self.genesis_rlp.clone().into() - } - /// Returns blocks rlp. pub fn blocks_rlp(&self) -> Vec> { self.blocks.iter().map(|block| block.rlp()).collect() diff --git a/json/src/blockchain/test.rs b/json/src/blockchain/test.rs index 6f48a8bc6..1a6a63a71 100644 --- a/json/src/blockchain/test.rs +++ b/json/src/blockchain/test.rs @@ -18,6 +18,9 @@ use std::collections::BTreeMap; use std::ops::Deref; +use std::io::Read; +use serde_json; +use serde_json::Error; use blockchain::blockchain::BlockChain; /// Blockchain test deserializer. @@ -31,3 +34,10 @@ impl Deref for Test { &self.0 } } + +impl Test { + /// Loads test from json. + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } +} diff --git a/json/src/bytes.rs b/json/src/bytes.rs index 061795b40..6ccae51d7 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -46,12 +46,8 @@ impl Visitor for BytesVisitor { let v = match value.len() { 0 => vec![], 2 if value.starts_with("0x") => vec![], - _ if value.starts_with("0x") => try!(FromHex::from_hex(&value[2..]).map_err(|_| { - Error::custom(format!("Invalid hex value {}.", value).as_ref()) - })), - _ => try!(FromHex::from_hex(value).map_err(|_| { - Error::custom(format!("Invalid hex value {}.", value).as_ref()) - })) + _ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]), + _ => FromHex::from_hex(value).unwrap_or(vec![]), }; Ok(Bytes(v)) } From ddab958e615eae32bacb3a4994e4051a470da8e4 Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 18:38:02 +0100 Subject: [PATCH 73/91] fixed missing import --- ethcore/src/json_tests/chain.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 5e2d51594..a2e6a5659 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -21,10 +21,11 @@ use ethereum; use tests::helpers::*; use devtools::*; use spec::Genesis; +use ethjson; pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { init_log(); - let tests = ethjson::blockchain::Test.load(json_data).unwrap(); + let tests = ethjson::blockchain::Test::load(json_data).unwrap(); let mut failed = Vec::new(); for (name, blockchain) in tests.deref() { From c2cffd1e06409b6eef33b8127c1203ee1a00f4f3 Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 23:27:50 +0100 Subject: [PATCH 74/91] improvements to build, updated dependencies, moved rpctest to its own submodule --- Cargo.lock | 130 ++++++++++--------- Cargo.toml | 6 - json/Cargo.toml | 2 +- rpc/Cargo.toml | 2 +- rpc/rpctest/Cargo.toml | 17 +++ parity/rpctest.rs => rpc/rpctest/src/main.rs | 0 6 files changed, 87 insertions(+), 70 deletions(-) create mode 100644 rpc/rpctest/Cargo.toml rename parity/rpctest.rs => rpc/rpctest/src/main.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 9240a5b36..13787c22f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,7 +19,6 @@ dependencies = [ "rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -42,10 +41,10 @@ dependencies = [ [[package]] name = "aster" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -53,7 +52,7 @@ name = "bigint" version = "0.1.0" dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -140,7 +139,7 @@ source = "git+https://github.com/tomusdrw/rust-ctrlc.git#f4927770f89eca80ec25091 dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -164,7 +163,7 @@ name = "docopt" version = "0.6.78" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -180,7 +179,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -217,7 +216,7 @@ dependencies = [ "ethcore-devtools 1.0.0", "ethcore-util 1.0.0", "ethjson 0.1.0", - "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -244,14 +243,14 @@ dependencies = [ "ethcore-util 1.0.0", "ethminer 1.0.0", "ethsync 1.0.0", - "jsonrpc-core 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-http-server 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-http-server 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -268,7 +267,7 @@ dependencies = [ "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)", "ethcore-devtools 1.0.0", - "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "igd 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "json-tests 0.1.0", @@ -297,9 +296,9 @@ dependencies = [ "ethcore-util 1.1.0", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -325,7 +324,7 @@ dependencies = [ "ethcore 1.0.0", "ethcore-util 1.0.0", "ethminer 1.0.0", - "heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", @@ -355,11 +354,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "heapsize" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -391,27 +389,27 @@ dependencies = [ "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cookie 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -422,7 +420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "xmltree 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -442,23 +440,23 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-http-server" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -466,7 +464,7 @@ name = "kernel32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -498,7 +496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "librocksdb-sys" version = "0.2.3" -source = "git+https://github.com/arkpar/rust-rocksdb.git#ebb602fc74b4067f9f51310bdc0401b8e59b7156" +source = "git+https://github.com/arkpar/rust-rocksdb.git#ae44ef33ed1358ffc79aa05ed77839d555daba33" dependencies = [ "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -533,6 +531,14 @@ dependencies = [ "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mime" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.5.0" @@ -542,11 +548,11 @@ dependencies = [ "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -555,20 +561,20 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "net2" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -667,20 +673,20 @@ dependencies = [ [[package]] name = "quasi" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quasi_codegen" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aster 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aster 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -703,7 +709,7 @@ dependencies = [ [[package]] name = "regex" -version = "0.1.56" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -720,7 +726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rocksdb" version = "0.4.3" -source = "git+https://github.com/arkpar/rust-rocksdb.git#ebb602fc74b4067f9f51310bdc0401b8e59b7156" +source = "git+https://github.com/arkpar/rust-rocksdb.git#ae44ef33ed1358ffc79aa05ed77839d555daba33" dependencies = [ "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "librocksdb-sys 0.2.3 (git+https://github.com/arkpar/rust-rocksdb.git)", @@ -734,7 +740,7 @@ dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -790,14 +796,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_codegen" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aster 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aster 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -837,18 +843,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syntex" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_syntax" -version = "0.29.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -867,7 +873,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -885,7 +891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -921,7 +927,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicase" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -992,7 +998,7 @@ dependencies = [ [[package]] name = "winapi" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1005,7 +1011,7 @@ name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index e52e1c89b..e9a25f730 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,8 +27,6 @@ ethsync = { path = "sync" } ethminer = { path = "miner" } ethcore-devtools = { path = "devtools" } ethcore-rpc = { path = "rpc", optional = true } -ethjson = { path = "json" } -serde_json = "0.7.0" [features] default = ["rpc"] @@ -41,10 +39,6 @@ travis-nightly = ["ethcore/json-tests", "dev"] path = "parity/main.rs" name = "parity" -[[bin]] -path = "parity/rpctest.rs" -name = "rpctest" - [profile.release] debug = false lto = false diff --git a/json/Cargo.toml b/json/Cargo.toml index 91f8b8431..7887f2cea 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -14,7 +14,7 @@ clippy = { version = "0.0.54", optional = true } [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } -syntex = "0.29.0" +syntex = "0.30.0" [features] default = ["serde_codegen"] diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 1e8174660..56eeb7d83 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -26,7 +26,7 @@ clippy = { version = "0.0.54", optional = true } [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } -syntex = "0.29.0" +syntex = "0.30.0" [features] default = ["serde_codegen"] diff --git a/rpc/rpctest/Cargo.toml b/rpc/rpctest/Cargo.toml new file mode 100644 index 000000000..5b8f7f845 --- /dev/null +++ b/rpc/rpctest/Cargo.toml @@ -0,0 +1,17 @@ +[package] +description = "Rpc test client." +name = "rpctest" +version = "1.1.0" +license = "GPL-3.0" +authors = ["Ethcore "] + +[dependencies] +ctrlc = { git = "https://github.com/tomusdrw/rust-ctrlc.git" } +docopt = "0.6" +rustc-serialize = "0.3" +ethcore = { path = "../../ethcore" } +ethcore-devtools = { path = "../../devtools" } +ethcore-rpc = { path = ".." } +ethcore-util = { path = "../../util" } +ethjson = { path = "../../json" } +serde_json = "0.7.0" diff --git a/parity/rpctest.rs b/rpc/rpctest/src/main.rs similarity index 100% rename from parity/rpctest.rs rename to rpc/rpctest/src/main.rs From 245ef854dd70d8a4d801be16241d895447c33fa5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 19 Mar 2016 23:51:24 +0100 Subject: [PATCH 75/91] Allow 0x prefix for --author. --- parity/main.rs | 4 ++-- util/src/hash.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index c7e534993..56e70cf2a 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -46,6 +46,7 @@ use env_logger::LogBuilder; use ctrlc::CtrlC; use util::*; use util::panics::{MayPanic, ForwardPanic, PanicHandler}; +use util::keys::store::*; use ethcore::spec::*; use ethcore::client::*; use ethcore::service::{ClientService, NetSyncMessage}; @@ -55,7 +56,6 @@ use ethminer::{Miner, MinerService}; use docopt::Docopt; use daemonize::Daemonize; use number_prefix::{binary_prefix, Standalone, Prefixed}; -use util::keys::store::*; fn die_with_message(msg: &str) -> ! { println!("ERROR: {}", msg); @@ -315,7 +315,7 @@ impl Configuration { fn author(&self) -> Address { let d = self.args.flag_etherbase.as_ref().unwrap_or(&self.args.flag_author); - Address::from_str(d).unwrap_or_else(|_| { + Address::from_str(clean_0x(d)).unwrap_or_else(|_| { die!("{}: Invalid address for --author. Must be 40 hex characters, without the 0x at the beginning.", d) }) } diff --git a/util/src/hash.rs b/util/src/hash.rs index fce0720d1..b7fddbe8b 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -63,7 +63,8 @@ pub trait FixedHash: Sized + BytesConvertable + Populatable + FromStr + Default fn low_u64(&self) -> u64; } -fn clean_0x(s: &str) -> &str { +/// Return `s` without the `0x` at the beginning of it, if any. +pub fn clean_0x(s: &str) -> &str { if s.len() >= 2 && &s[0..2] == "0x" { &s[2..] } else { From aa6b6e477c645ef02de945517d0abb7b0aa1bd7f Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 14:29:09 +0100 Subject: [PATCH 76/91] added output to execution result --- ethcore/src/executive.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 782063cb2..a00d9a85d 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -60,7 +60,9 @@ pub struct Executed { /// eg. sender creates contract A and A in constructor creates contract B /// /// B creation ends first, and it will be the first element of the vector. - pub contracts_created: Vec
+ pub contracts_created: Vec
, + /// Transaction output. + pub output: Bytes, } /// Transaction execution result. @@ -145,7 +147,7 @@ impl<'a> Executive<'a> { let mut substate = Substate::new(); - let res = match t.action { + let (gas_left, output) = match t.action { Action::Create => { let new_address = contract_address(&sender, &nonce); let params = ActionParams { @@ -159,7 +161,7 @@ impl<'a> Executive<'a> { code: Some(t.data.clone()), data: None, }; - self.create(params, &mut substate) + (self.create(params, &mut substate), vec![]) }, Action::Call(ref address) => { let params = ActionParams { @@ -175,12 +177,12 @@ impl<'a> Executive<'a> { }; // TODO: move output upstream let mut out = vec![]; - self.call(params, &mut substate, BytesRef::Flexible(&mut out)) + (self.call(params, &mut substate, BytesRef::Flexible(&mut out)), out) } }; // finalize here! - Ok(try!(self.finalize(t, substate, res))) + Ok(try!(self.finalize(t, substate, gas_left, output))) } fn exec_vm(&mut self, params: ActionParams, unconfirmed_substate: &mut Substate, output_policy: OutputPolicy) -> evm::Result { @@ -286,7 +288,7 @@ impl<'a> Executive<'a> { } /// Finalizes the transaction (does refunds and suicides). - fn finalize(&mut self, t: &SignedTransaction, substate: Substate, result: evm::Result) -> ExecutionResult { + fn finalize(&mut self, t: &SignedTransaction, substate: Substate, result: evm::Result, output: Bytes) -> ExecutionResult { let schedule = self.engine.schedule(self.info); // refunds from SSTORE nonzero -> zero @@ -326,7 +328,8 @@ impl<'a> Executive<'a> { refunded: U256::zero(), cumulative_gas_used: self.info.gas_used + t.gas, logs: vec![], - contracts_created: vec![] + contracts_created: vec![], + output: output, }) }, _ => { @@ -337,6 +340,7 @@ impl<'a> Executive<'a> { cumulative_gas_used: self.info.gas_used + gas_used, logs: substate.logs, contracts_created: substate.contracts_created, + output: output, }) }, } From 5c72e60b14a0b500005daba9ebd2b623f0c98b96 Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 19 Mar 2016 21:37:11 +0100 Subject: [PATCH 77/91] implemented eth_call --- ethcore/src/client/client.rs | 25 +++++++++++++++++++++++++ ethcore/src/client/mod.rs | 5 ++++- ethcore/src/client/test_client.rs | 6 ++++++ ethcore/src/views.rs | 3 +++ rpc/src/v1/impls/eth.rs | 20 ++++++++++++++++++++ util/bigint/src/uint.rs | 11 +++++++++++ 6 files changed, 69 insertions(+), 1 deletion(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index c62364dce..a0538d8de 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -37,6 +37,8 @@ use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; use client::{BlockId, TransactionId, ClientConfig, BlockChainClient}; +use env_info::EnvInfo; +use executive::{Executive, Executed}; pub use blockchain::CacheSize as BlockChainCacheSize; /// General block status @@ -385,6 +387,29 @@ impl Client where V: Verifier { } impl BlockChainClient for Client where V: Verifier { + fn call(&self, t: &SignedTransaction) -> Result { + let header = self.block_header(BlockId::Latest).unwrap(); + let view = HeaderView::new(&header); + let last_hashes = self.build_last_hashes(view.hash()); + let env_info = EnvInfo { + number: view.number(), + author: view.author(), + timestamp: view.timestamp(), + difficulty: view.difficulty(), + last_hashes: last_hashes, + gas_used: U256::zero(), + gas_limit: U256::max_value(), + }; + // that's just a copy of the state. + let mut state = self.state(); + let sender = try!(t.sender()); + let balance = state.balance(&sender); + // give the sender max balance + state.sub_balance(&sender, &balance); + state.add_balance(&sender, &U256::max_value()); + Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t) + } + // TODO [todr] Should be moved to miner crate eventually. fn try_seal(&self, block: ClosedBlock, seal: Vec) -> Result { block.try_seal(self.engine.deref().deref(), seal) diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 198e918f7..4a3208eb8 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -37,7 +37,8 @@ use header::BlockNumber; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; -use error::{ImportResult}; +use error::{ImportResult, Error}; +use executive::Executed; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -118,5 +119,7 @@ pub trait BlockChainClient : Sync + Send { /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. fn try_seal(&self, block: ClosedBlock, seal: Vec) -> Result; + /// Makes a non-persistent transaction call. + fn call(&self, t: &SignedTransaction) -> Result; } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 9150a5f55..5d51368de 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -29,6 +29,8 @@ use error::{ImportResult}; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock}; +use executive::Executed; +use error::Error; /// Test client. pub struct TestBlockChainClient { @@ -182,6 +184,10 @@ impl TestBlockChainClient { } impl BlockChainClient for TestBlockChainClient { + fn call(&self, t: &SignedTransaction) -> Result { + unimplemented!() + } + fn block_total_difficulty(&self, _id: BlockId) -> Option { Some(U256::zero()) } diff --git a/ethcore/src/views.rs b/ethcore/src/views.rs index 745cbff2c..11e26eb5f 100644 --- a/ethcore/src/views.rs +++ b/ethcore/src/views.rs @@ -256,6 +256,9 @@ impl<'a> HeaderView<'a> { } } + /// Returns header hash. + pub fn hash(&self) -> H256 { self.sha3() } + /// Returns raw rlp. pub fn rlp(&self) -> &Rlp<'a> { &self.rlp } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 9b2588670..3daa6275c 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -398,6 +398,26 @@ impl Eth for EthClient } }) } + + fn call(&self, params: Params) -> Result { + from_params::<(TransactionRequest, BlockNumber)>(params) + .and_then(|(transaction_request, _block_number)| { + let accounts = take_weak!(self.accounts); + match accounts.account_secret(&transaction_request.from) { + Ok(secret) => { + let client = take_weak!(self.client); + + let transaction: EthTransaction = transaction_request.into(); + let signed_transaction = transaction.sign(&secret); + + to_value(&client.call(&signed_transaction) + .map(|e| Bytes::new(e.output)) + .unwrap_or(Bytes::default())) + }, + Err(_) => { to_value(&Bytes::default()) } + } + }) + } } /// Eth filter rpc implementation. diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index d185750c2..7bc6007ed 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -490,6 +490,8 @@ pub trait Uint: Sized + Default + FromStr + From + fmt::Debug + fmt::Displa fn zero() -> Self; /// Returns new instance equalling one. fn one() -> Self; + /// Returns the largest value that can be represented by this integer type. + fn max_value() -> Self; /// Error type for converting from a decimal string. type FromDecStrErr; @@ -647,6 +649,15 @@ macro_rules! construct_uint { From::from(1u64) } + #[inline] + fn max_value() -> Self { + let mut result = [0; $n_words]; + for i in 0..$n_words { + result[i] = u64::max_value(); + } + $name(result) + } + /// Fast exponentation by squaring /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring fn pow(self, expon: Self) -> Self { From 1257ad29932b3f6f52c57365d1821620008b3b53 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 20 Mar 2016 10:07:50 +0100 Subject: [PATCH 78/91] fixes after merge --- ethcore/src/client/client.rs | 2 +- ethcore/src/client/test_client.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index a0538d8de..d588156f0 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -407,7 +407,7 @@ impl BlockChainClient for Client where V: Verifier { // give the sender max balance state.sub_balance(&sender, &balance); state.add_balance(&sender, &U256::max_value()); - Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t) + Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t, false) } // TODO [todr] Should be moved to miner crate eventually. diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 5d51368de..db4be61bc 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -184,7 +184,7 @@ impl TestBlockChainClient { } impl BlockChainClient for TestBlockChainClient { - fn call(&self, t: &SignedTransaction) -> Result { + fn call(&self, _t: &SignedTransaction) -> Result { unimplemented!() } From 280c5e8a9940f4c06c5f68eedb1761d8f6773fc7 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 20 Mar 2016 10:29:21 +0100 Subject: [PATCH 79/91] implementation of eth_estimateGas --- rpc/src/v1/impls/eth.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 3daa6275c..c66f04355 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -418,6 +418,26 @@ impl Eth for EthClient } }) } + + fn estimate_gas(&self, params: Params) -> Result { + from_params::<(TransactionRequest, BlockNumber)>(params) + .and_then(|(transaction_request, _block_number)| { + let accounts = take_weak!(self.accounts); + match accounts.account_secret(&transaction_request.from) { + Ok(secret) => { + let client = take_weak!(self.client); + + let transaction: EthTransaction = transaction_request.into(); + let signed_transaction = transaction.sign(&secret); + + to_value(&client.call(&signed_transaction) + .map(|e| e.gas_used) + .unwrap_or(U256::zero())) + }, + Err(_) => { to_value(&U256::zero()) } + } + }) + } } /// Eth filter rpc implementation. From 048dba7ef30ecc4c73c282e57f7dd985d21499c7 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 20 Mar 2016 10:36:44 +0100 Subject: [PATCH 80/91] fixed indentation --- rpc/src/v1/impls/eth.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index c66f04355..01625e9f9 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -410,9 +410,11 @@ impl Eth for EthClient let transaction: EthTransaction = transaction_request.into(); let signed_transaction = transaction.sign(&secret); - to_value(&client.call(&signed_transaction) - .map(|e| Bytes::new(e.output)) - .unwrap_or(Bytes::default())) + let output = client.call(&signed_transaction) + .map(|e| Bytes::new(e.output)) + .unwrap_or(Bytes::default()); + + to_value(&output) }, Err(_) => { to_value(&Bytes::default()) } } From d5cc2c9e6792fd5ddd385e7cf0fd1de90f89af56 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 20 Mar 2016 11:34:19 +0100 Subject: [PATCH 81/91] implemented rpc eth_estimateGas method, added tests for rpc eth_call and eth_estimateGas --- ethcore/src/client/mod.rs | 2 +- ethcore/src/client/test_client.rs | 10 ++- ethcore/src/executive.rs | 2 +- rpc/src/v1/impls/eth.rs | 8 ++- rpc/src/v1/tests/eth.rs | 74 +++++++++++++++++--- rpc/src/v1/tests/helpers/account_provider.rs | 4 +- rpc/src/v1/types/transaction_request.rs | 25 +++++++ 7 files changed, 107 insertions(+), 18 deletions(-) diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 4a3208eb8..9663ab62b 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -25,6 +25,7 @@ pub use self::client::*; pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig}; pub use self::ids::{BlockId, TransactionId}; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; +pub use executive::Executed; use std::collections::HashSet; use util::bytes::Bytes; @@ -38,7 +39,6 @@ use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; use error::{ImportResult, Error}; -use executive::Executed; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index db4be61bc..ad73234b3 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -50,6 +50,8 @@ pub struct TestBlockChainClient { pub storage: RwLock>, /// Code. pub code: RwLock>, + /// Execution result. + pub execution_result: RwLock>, } #[derive(Clone)] @@ -84,12 +86,18 @@ impl TestBlockChainClient { balances: RwLock::new(HashMap::new()), storage: RwLock::new(HashMap::new()), code: RwLock::new(HashMap::new()), + execution_result: RwLock::new(None), }; client.add_blocks(1, EachBlockWith::Nothing); // add genesis block client.genesis_hash = client.last_hash.read().unwrap().clone(); client } + /// Set the execution result. + pub fn set_execution_result(&self, result: Executed) { + *self.execution_result.write().unwrap() = Some(result); + } + /// Set the balance of account `address` to `balance`. pub fn set_balance(&self, address: Address, balance: U256) { self.balances.write().unwrap().insert(address, balance); @@ -185,7 +193,7 @@ impl TestBlockChainClient { impl BlockChainClient for TestBlockChainClient { fn call(&self, _t: &SignedTransaction) -> Result { - unimplemented!() + Ok(self.execution_result.read().unwrap().clone().unwrap()) } fn block_total_difficulty(&self, _id: BlockId) -> Option { diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index a00d9a85d..9aa3bcf9b 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -37,7 +37,7 @@ pub fn contract_address(address: &Address, nonce: &U256) -> Address { } /// Transaction execution receipt. -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub struct Executed { /// Gas paid up front for execution of transaction. pub gas: U256, diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 01625e9f9..a99a912f8 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -432,9 +432,11 @@ impl Eth for EthClient let transaction: EthTransaction = transaction_request.into(); let signed_transaction = transaction.sign(&secret); - to_value(&client.call(&signed_transaction) - .map(|e| e.gas_used) - .unwrap_or(U256::zero())) + let gas_used = client.call(&signed_transaction) + .map(|e| e.gas_used + e.refunded) + .unwrap_or(U256::zero()); + + to_value(&gas_used) }, Err(_) => { to_value(&U256::zero()) } } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index a5f318350..72235b390 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -18,8 +18,8 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; use jsonrpc_core::IoHandler; use util::hash::{Address, H256}; -use util::numbers::U256; -use ethcore::client::{TestBlockChainClient, EachBlockWith}; +use util::numbers::{Uint, U256}; +use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed}; use v1::{Eth, EthClient}; use v1::tests::helpers::{TestAccount, TestAccountProvider, TestSyncProvider, Config, TestMinerService, TestExternalMiner}; @@ -299,9 +299,69 @@ fn rpc_eth_code() { } #[test] -#[ignore] fn rpc_eth_call() { - unimplemented!() + let tester = EthTester::default(); + tester.client.set_execution_result(Executed { + gas: U256::zero(), + gas_used: U256::from(0xff30), + refunded: U256::from(0x5), + cumulative_gas_used: U256::zero(), + logs: vec![], + contracts_created: vec![], + output: vec![0x12, 0x34, 0xff], + trace: None, + }); + + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_call", + "params": [{ + "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }, + "latest"], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":"0x1234ff","id":1}"#; + + assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); +} + +#[test] +fn rpc_eth_estimate_gas() { + let tester = EthTester::default(); + tester.client.set_execution_result(Executed { + gas: U256::zero(), + gas_used: U256::from(0xff30), + refunded: U256::from(0x5), + cumulative_gas_used: U256::zero(), + logs: vec![], + contracts_created: vec![], + output: vec![0x12, 0x34, 0xff], + trace: None, + }); + + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_estimateGas", + "params": [{ + "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }, + "latest"], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":"0xff35","id":1}"#; + + assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); } #[test] @@ -322,12 +382,6 @@ fn rpc_eth_sign() { unimplemented!() } -#[test] -#[ignore] -fn rpc_eth_estimate_gas() { - unimplemented!() -} - #[test] fn rpc_eth_compilers() { let request = r#"{"jsonrpc": "2.0", "method": "eth_getCompilers", "params": [], "id": 1}"#; diff --git a/rpc/src/v1/tests/helpers/account_provider.rs b/rpc/src/v1/tests/helpers/account_provider.rs index 614aba346..6ef6e2b59 100644 --- a/rpc/src/v1/tests/helpers/account_provider.rs +++ b/rpc/src/v1/tests/helpers/account_provider.rs @@ -19,7 +19,7 @@ use std::sync::RwLock; use std::collections::HashMap; use std::io; -use util::hash::{Address, H256}; +use util::hash::{Address, H256, FixedHash}; use util::crypto::{Secret, Signature}; use util::keys::store::{AccountProvider, SigningError, EncryptedHashMapError}; @@ -83,7 +83,7 @@ impl AccountProvider for TestAccountProvider { } fn account_secret(&self, _account: &Address) -> Result { - unimplemented!() + Ok(Secret::random()) } fn sign(&self, _account: &Address, _message: &H256) -> Result { diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index d40402ab5..ed4dc19a2 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -46,6 +46,8 @@ impl Into for TransactionRequest { #[cfg(test)] mod tests { + use std::str::FromStr; + use rustc_serialize::hex::FromHex; use serde_json; use util::numbers::{Uint, U256}; use util::hash::Address; @@ -121,6 +123,29 @@ mod tests { }); } + #[test] + fn transaction_request_deserialize2() { + let s = r#"{ + "from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a", + "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675" + }"#; + let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); + + assert_eq!(deserialized, TransactionRequest { + from: Address::from_str("b60e8dd61c5d32be8058bb8eb970870f07233155").unwrap(), + to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + gas_price: Some(U256::from_str("9184e72a000").unwrap()), + gas: Some(U256::from_str("76c0").unwrap()), + value: Some(U256::from_str("9184e72a").unwrap()), + data: Some(Bytes::new("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675".from_hex().unwrap())), + nonce: None + }); + } + #[test] fn transaction_request_deserialize_empty() { let s = r#"{"from":"0x0000000000000000000000000000000000000001"}"#; From 6d1ae888ca53953dd9fa11618983bad9ae4bcab8 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 20 Mar 2016 10:19:21 +0100 Subject: [PATCH 82/91] Listen on all interfaces for JSONRPC by default. --- parity/main.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 56e70cf2a..39f5dcc82 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -105,8 +105,9 @@ Networking Options: API and Console Options: -j --jsonrpc Enable the JSON-RPC API sever. - --jsonrpc-addr HOST Specify the hostname portion of the JSONRPC API - server [default: 127.0.0.1]. + --jsonrpc-interface IP Specify the hostname portion of the JSONRPC API + server, IP should be an interface's IP address, or + all (all interfaces) or local [default: all]. --jsonrpc-port PORT Specify the port portion of the JSONRPC API server [default: 8545]. --jsonrpc-cors URL Specify CORS header for JSON-RPC API responses @@ -149,7 +150,7 @@ Geth-compatibility Options: --nodekey KEY Equivalent to --node-key KEY. --nodiscover Equivalent to --no-discovery. --rpc Equivalent to --jsonrpc. - --rpcaddr HOST Equivalent to --jsonrpc-addr HOST. + --rpcaddr IP Equivalent to --jsonrpc-interface IP. --rpcport PORT Equivalent to --jsonrpc-port PORT. --rpcapi APIS Equivalent to --jsonrpc-apis APIS. --rpccorsdomain URL Equivalent to --jsonrpc-cors URL. @@ -188,7 +189,7 @@ struct Args { flag_cache_max_size: usize, flag_queue_max_size: usize, flag_jsonrpc: bool, - flag_jsonrpc_addr: String, + flag_jsonrpc_interface: String, flag_jsonrpc_port: u16, flag_jsonrpc_cors: String, flag_jsonrpc_apis: String, @@ -523,7 +524,11 @@ impl Configuration { // Setup rpc if self.args.flag_jsonrpc || self.args.flag_rpc { let url = format!("{}:{}", - self.args.flag_rpcaddr.as_ref().unwrap_or(&self.args.flag_jsonrpc_addr), + match self.args.flag_rpcaddr.as_ref().unwrap_or(&self.args.flag_jsonrpc_interface).as_str() { + "all" => "0.0.0.0", + "local" => "127.0.0.1", + x => x, + }, self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port) ); SocketAddr::from_str(&url).unwrap_or_else(|_| die!("{}: Invalid JSONRPC listen host/port given.", url)); From bff142828d58539d238e5c8d467de80e2a05b0eb Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 20 Mar 2016 10:34:34 +0100 Subject: [PATCH 83/91] JSONRPC interface defaults to local. Please enter the commit message for your changes. Lines starting --- parity/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/main.rs b/parity/main.rs index 39f5dcc82..e029124c4 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -107,7 +107,7 @@ API and Console Options: -j --jsonrpc Enable the JSON-RPC API sever. --jsonrpc-interface IP Specify the hostname portion of the JSONRPC API server, IP should be an interface's IP address, or - all (all interfaces) or local [default: all]. + all (all interfaces) or local [default: local]. --jsonrpc-port PORT Specify the port portion of the JSONRPC API server [default: 8545]. --jsonrpc-cors URL Specify CORS header for JSON-RPC API responses From 08dc83205cb668e5aebb1615f633ec300001abd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 13:59:11 +0100 Subject: [PATCH 84/91] Flipping sealing_enabled flag after no requests for sealing_block for some time --- ethcore/src/client/test_client.rs | 8 ++--- miner/src/miner.rs | 58 +++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index ad73234b3..ebeb77414 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -232,12 +232,12 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option<(ClosedBlock, HashSet)> { - unimplemented!() + fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option { + None } - fn try_seal(&self, _block: ClosedBlock, _seal: Vec) -> Result { - unimplemented!() + fn try_seal(&self, block: ClosedBlock, _seal: Vec) -> Result { + Err(block) } fn block_header(&self, id: BlockId) -> Option { diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 858df7c40..504d02e17 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -34,6 +34,7 @@ pub struct Miner { // for sealing... sealing_enabled: AtomicBool, + sealing_block_last_request: Mutex, sealing_block: Mutex>, gas_floor_target: RwLock, author: RwLock
, @@ -46,6 +47,7 @@ impl Default for Miner { Miner { transaction_queue: Mutex::new(TransactionQueue::new()), sealing_enabled: AtomicBool::new(false), + sealing_block_last_request: Mutex::new(0), sealing_block: Mutex::new(None), gas_floor_target: RwLock::new(U256::zero()), author: RwLock::new(Address::default()), @@ -118,6 +120,8 @@ impl Miner { } } +const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; + impl MinerService for Miner { fn clear_and_reset(&self, chain: &BlockChainClient) { @@ -147,7 +151,17 @@ impl MinerService for Miner { } fn update_sealing(&self, chain: &BlockChainClient) { - if self.sealing_enabled.load(atomic::Ordering::Relaxed) { + let should_disable_sealing = { + let current_no = chain.chain_info().best_block_number; + let last_request = self.sealing_block_last_request.lock().unwrap(); + + current_no - *last_request > SEALING_TIMEOUT_IN_BLOCKS + }; + + if should_disable_sealing { + self.sealing_enabled.store(false, atomic::Ordering::Relaxed); + *self.sealing_block.lock().unwrap() = None; + } else if self.sealing_enabled.load(atomic::Ordering::Relaxed) { self.prepare_sealing(chain); } } @@ -155,9 +169,10 @@ impl MinerService for Miner { fn sealing_block(&self, chain: &BlockChainClient) -> &Mutex> { if self.sealing_block.lock().unwrap().is_none() { self.sealing_enabled.store(true, atomic::Ordering::Relaxed); - // TODO: Above should be on a timer that resets after two blocks have arrived without being asked for. + self.prepare_sealing(chain); } + *self.sealing_block_last_request.lock().unwrap() = chain.chain_info().best_block_number; &self.sealing_block } @@ -242,3 +257,42 @@ impl MinerService for Miner { self.update_sealing(chain); } } + +#[cfg(test)] +mod tests { + + use MinerService; + use super::{Miner}; + use ethcore::client::{TestBlockChainClient, EachBlockWith}; + + // TODO [ToDr] To uncomment client is cleaned from mining stuff. + #[ignore] + #[test] + fn should_prepare_block_to_seal() { + // given + let client = TestBlockChainClient::default(); + let miner = Miner::default(); + + // when + let res = miner.sealing_block(&client); + + // then + assert!(res.lock().unwrap().is_some(), "Expected closed block"); + } + + #[test] + fn should_reset_seal_after_couple_of_blocks() { + // given + let client = TestBlockChainClient::default(); + let miner = Miner::default(); + let res = miner.sealing_block(&client); + // TODO [ToDr] Uncomment after fixing TestBlockChainClient + // assert!(res.lock().unwrap().is_some(), "Expected closed block"); + + // when + client.add_blocks(10, EachBlockWith::Uncle); + + // then + assert!(res.lock().unwrap().is_none(), "Expected to remove sealed block"); + } +} From 6e666ecac7343e5fae37eb32cffcb8c2800c78ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 18 Mar 2016 20:45:07 +0100 Subject: [PATCH 85/91] Fixing ethminer doctest --- miner/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/miner/src/lib.rs b/miner/src/lib.rs index b79a13e24..ca25e3993 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -45,7 +45,6 @@ //! assert_eq!(miner.status().transactions_in_pending_queue, 0); //! //! // Check block for sealing -//! miner.prepare_sealing(client.deref()); //! assert!(miner.sealing_block(client.deref()).lock().unwrap().is_some()); //! } //! ``` From a36ac996a07891ffb086a872c29d85bebeee8f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 20 Mar 2016 12:18:41 +0100 Subject: [PATCH 86/91] Avoiding possible overflow when block number gets smaller. --- miner/src/miner.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 504d02e17..478005d4b 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -154,8 +154,8 @@ impl MinerService for Miner { let should_disable_sealing = { let current_no = chain.chain_info().best_block_number; let last_request = self.sealing_block_last_request.lock().unwrap(); - - current_no - *last_request > SEALING_TIMEOUT_IN_BLOCKS + let is_greater = current_no > *last_request; + is_greater && current_no - *last_request > SEALING_TIMEOUT_IN_BLOCKS }; if should_disable_sealing { From 85fa07728cc57acb699e8d07886369c3f0336382 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 20 Mar 2016 17:29:39 +0100 Subject: [PATCH 87/91] LocalizedReceipt --- ethcore/src/blockchain/blockchain.rs | 5 +++ ethcore/src/client/client.rs | 23 ++++++++---- ethcore/src/client/mod.rs | 4 ++ ethcore/src/client/test_client.rs | 4 ++ ethcore/src/receipt.rs | 23 +++++++++++- rpc/src/v1/impls/eth.rs | 6 +++ rpc/src/v1/types/mod.rs.in | 2 + rpc/src/v1/types/receipt.rs | 56 ++++++++++++++++++++++++++++ 8 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 rpc/src/v1/types/receipt.rs diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 40b01c6f9..edbd96458 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -100,6 +100,11 @@ pub trait BlockProvider { self.block(&address.block_hash).and_then(|bytes| BlockView::new(&bytes).localized_transaction_at(address.index)) } + /// Get transaction receipt. + fn transaction_receipt(&self, address: &TransactionAddress) -> Option { + self.block_receipts(&address.block_hash).and_then(|br| br.receipts.into_iter().nth(address.index)) + } + /// Get a list of transactions for a given block. /// Returns None if block does not exist. fn transactions(&self, hash: &H256) -> Option> { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d588156f0..551a714ba 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -39,6 +39,7 @@ use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; use client::{BlockId, TransactionId, ClientConfig, BlockChainClient}; use env_info::EnvInfo; use executive::{Executive, Executed}; +use receipt::Receipt; pub use blockchain::CacheSize as BlockChainCacheSize; /// General block status @@ -384,6 +385,16 @@ impl Client where V: Verifier { BlockId::Latest => Some(self.chain.best_block_number()) } } + + fn transaction_address(&self, id: TransactionId) -> Option { + match id { + TransactionId::Hash(ref hash) => self.chain.transaction_address(hash), + TransactionId::Location(id, index) => Self::block_hash(&self.chain, id).map(|hash| TransactionAddress { + block_hash: hash, + index: index + }) + } + } } impl BlockChainClient for Client where V: Verifier { @@ -534,13 +545,11 @@ impl BlockChainClient for Client where V: Verifier { } fn transaction(&self, id: TransactionId) -> Option { - match id { - TransactionId::Hash(ref hash) => self.chain.transaction_address(hash), - TransactionId::Location(id, index) => Self::block_hash(&self.chain, id).map(|hash| TransactionAddress { - block_hash: hash, - index: index - }) - }.and_then(|address| self.chain.transaction(&address)) + self.transaction_address(id).and_then(|address| self.chain.transaction(&address)) + } + + fn transaction_receipt(&self, id: TransactionId) -> Option { + self.transaction_address(id).and_then(|address| self.chain.transaction_receipt(&address)) } fn tree_route(&self, from: &H256, to: &H256) -> Option { diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 9663ab62b..420fcf75e 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -39,6 +39,7 @@ use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; use error::{ImportResult, Error}; +use receipt::Receipt; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -76,6 +77,9 @@ pub trait BlockChainClient : Sync + Send { /// Get transaction with given hash. fn transaction(&self, id: TransactionId) -> Option; + /// Get transaction receipt with given hash. + fn transaction_receipt(&self, id: TransactionId) -> Option; + /// Get a tree route between `from` and `to`. /// See `BlockChain::tree_route`. fn tree_route(&self, from: &H256, to: &H256) -> Option; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index ebeb77414..4dcf16c83 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -224,6 +224,10 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } + fn transaction_receipt(&self, _id: TransactionId) -> Option { + unimplemented!(); + } + fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockId, _to_block: BlockId) -> Option> { unimplemented!(); } diff --git a/ethcore/src/receipt.rs b/ethcore/src/receipt.rs index ae83a174a..7f0b0d8dd 100644 --- a/ethcore/src/receipt.rs +++ b/ethcore/src/receipt.rs @@ -18,7 +18,8 @@ use util::*; use basic_types::LogBloom; -use log_entry::LogEntry; +use header::BlockNumber; +use log_entry::{LogEntry, LocalizedLogEntry}; /// Information describing execution of a transaction. #[derive(Default, Debug, Clone)] @@ -74,6 +75,26 @@ impl HeapSizeOf for Receipt { } } +/// Receipt with additional info. +pub struct LocalizedReceipt { + /// Transaction hash. + pub transaction_hash: H256, + /// Transaction index. + pub transaction_index: usize, + /// Block hash. + pub block_hash: H256, + /// Block number. + pub block_number: BlockNumber, + /// Cumulative gas used. + pub cumulative_gas_used: U256, + /// Gas used. + pub gas_used: U256, + /// Contract address. + pub contract_address: Option
, + /// Logs + pub logs: Vec, +} + #[test] fn test_basic() { let expected = FromHex::from_hex("f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a99a912f8..950cdb783 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -293,6 +293,12 @@ impl Eth for EthClient .and_then(|(number, index)| self.transaction(TransactionId::Location(number.into(), index.value()))) } + fn transaction_receipt(&self, params: Params) -> Result { + unimplemented!(); + //from_params::<(H256,)>(params) + //.and_then(|(hash,)| self.transaction_receipt(TransactionId::Hash(hash))) + } + fn uncle_by_block_hash_and_index(&self, params: Params) -> Result { from_params::<(H256, Index)>(params) .and_then(|(hash, index)| self.uncle(BlockId::Hash(hash), index.value())) diff --git a/rpc/src/v1/types/mod.rs.in b/rpc/src/v1/types/mod.rs.in index ebc3bc0ff..0121e4aea 100644 --- a/rpc/src/v1/types/mod.rs.in +++ b/rpc/src/v1/types/mod.rs.in @@ -24,6 +24,7 @@ mod optionals; mod sync; mod transaction; mod transaction_request; +mod receipt; pub use self::block::{Block, BlockTransactions}; pub use self::block_number::BlockNumber; @@ -35,4 +36,5 @@ pub use self::optionals::OptionalValue; pub use self::sync::{SyncStatus, SyncInfo}; pub use self::transaction::Transaction; pub use self::transaction_request::TransactionRequest; +pub use self::receipt::Receipt; diff --git a/rpc/src/v1/types/receipt.rs b/rpc/src/v1/types/receipt.rs new file mode 100644 index 000000000..fa34d5df5 --- /dev/null +++ b/rpc/src/v1/types/receipt.rs @@ -0,0 +1,56 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use util::numbers::U256; +use util::hash::{Address, H256}; +use v1::types::Log; +use ethcore::receipt::LocalizedReceipt; + +#[derive(Debug, Serialize)] +pub struct Receipt { + #[serde(rename="transactionHash")] + pub transaction_hash: H256, + #[serde(rename="transactionIndex")] + pub transaction_index: U256, + #[serde(rename="blockHash")] + pub block_hash: H256, + #[serde(rename="blockNumber")] + pub block_number: U256, + #[serde(rename="cumulativeGasUsed")] + pub cumulative_gas_used: U256, + #[serde(rename="gasUsed")] + pub gas_used: U256, + #[serde(rename="contractAddress")] + pub contract_address: Option
, + pub logs: Vec, +} + +impl From for Receipt { + fn from(r: LocalizedReceipt) -> Self { + Receipt { + transaction_hash: r.transaction_hash, + transaction_index: U256::from(r.transaction_index), + block_hash: r.block_hash, + block_number: U256::from(r.block_number), + cumulative_gas_used: r.cumulative_gas_used, + gas_used: r.gas_used, + contract_address: r.contract_address, + logs: r.logs.into_iter().map(From::from).collect(), + } + } +} + + From 04082d15149db9b5c9d85d7d540c63ea151e6056 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 20 Mar 2016 18:44:57 +0100 Subject: [PATCH 88/91] client implementation of transaction receipt --- ethcore/src/client/client.rs | 40 +++++++++++++++++++++++++++---- ethcore/src/client/mod.rs | 4 ++-- ethcore/src/client/test_client.rs | 4 ++-- ethcore/src/log_entry.rs | 3 ++- rpc/src/v1/impls/eth.rs | 11 +++++---- 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 551a714ba..9737fc982 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -39,7 +39,7 @@ use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; use client::{BlockId, TransactionId, ClientConfig, BlockChainClient}; use env_info::EnvInfo; use executive::{Executive, Executed}; -use receipt::Receipt; +use receipt::LocalizedReceipt; pub use blockchain::CacheSize as BlockChainCacheSize; /// General block status @@ -548,8 +548,40 @@ impl BlockChainClient for Client where V: Verifier { self.transaction_address(id).and_then(|address| self.chain.transaction(&address)) } - fn transaction_receipt(&self, id: TransactionId) -> Option { - self.transaction_address(id).and_then(|address| self.chain.transaction_receipt(&address)) + fn transaction_receipt(&self, id: TransactionId) -> Option { + self.transaction_address(id).and_then(|address| { + let t = self.chain.block(&address.block_hash) + .and_then(|block| BlockView::new(&block).localized_transaction_at(address.index)); + + match (t, self.chain.transaction_receipt(&address)) { + (Some(tx), Some(receipt)) => { + let block_hash = tx.block_hash.clone(); + let block_number = tx.block_number.clone(); + let transaction_hash = tx.hash(); + let transaction_index = tx.transaction_index; + Some(LocalizedReceipt { + transaction_hash: tx.hash(), + transaction_index: tx.transaction_index, + block_hash: tx.block_hash, + block_number: tx.block_number, + // TODO: to fix this, query all previous transaction receipts and retrieve their gas usage + cumulative_gas_used: receipt.gas_used, + gas_used: receipt.gas_used, + // TODO: to fix this, store created contract address in db + contract_address: None, + logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry { + entry: log, + block_hash: block_hash.clone(), + block_number: block_number, + transaction_hash: transaction_hash.clone(), + transaction_index: transaction_index, + log_index: i + }).collect() + }) + }, + _ => None + } + }) } fn tree_route(&self, from: &H256, to: &H256) -> Option { @@ -634,7 +666,7 @@ impl BlockChainClient for Client where V: Verifier { .map(|(i, log)| LocalizedLogEntry { entry: log, block_hash: hash.clone(), - block_number: number as usize, + block_number: number, transaction_hash: hashes.get(index).cloned().unwrap_or_else(H256::new), transaction_index: index, log_index: log_index + i diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 420fcf75e..74b05652f 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -39,7 +39,7 @@ use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; use error::{ImportResult, Error}; -use receipt::Receipt; +use receipt::LocalizedReceipt; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -78,7 +78,7 @@ pub trait BlockChainClient : Sync + Send { fn transaction(&self, id: TransactionId) -> Option; /// Get transaction receipt with given hash. - fn transaction_receipt(&self, id: TransactionId) -> Option; + fn transaction_receipt(&self, id: TransactionId) -> Option; /// Get a tree route between `from` and `to`. /// See `BlockChain::tree_route`. diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 4dcf16c83..27e4eefe8 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -23,7 +23,7 @@ use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockId, Transaction use header::{Header as BlockHeader, BlockNumber}; use filter::Filter; use log_entry::LocalizedLogEntry; -use receipt::Receipt; +use receipt::{Receipt, LocalizedReceipt}; use extras::BlockReceipts; use error::{ImportResult}; @@ -224,7 +224,7 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn transaction_receipt(&self, _id: TransactionId) -> Option { + fn transaction_receipt(&self, _id: TransactionId) -> Option { unimplemented!(); } diff --git a/ethcore/src/log_entry.rs b/ethcore/src/log_entry.rs index 63d09b4f0..cf74a6df9 100644 --- a/ethcore/src/log_entry.rs +++ b/ethcore/src/log_entry.rs @@ -18,6 +18,7 @@ use util::*; use basic_types::LogBloom; +use header::BlockNumber; /// A record of execution for a `LOG` operation. #[derive(Default, Debug, Clone, PartialEq, Eq)] @@ -84,7 +85,7 @@ pub struct LocalizedLogEntry { /// Block in which this log was created. pub block_hash: H256, /// Block number. - pub block_number: usize, + pub block_number: BlockNumber, /// Hash of transaction in which this log was created. pub transaction_hash: H256, /// Index of transaction within block. diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 950cdb783..d7ee478bf 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -31,7 +31,7 @@ use ethcore::ethereum::Ethash; use ethcore::ethereum::denominations::shannon; use ethcore::transaction::Transaction as EthTransaction; use v1::traits::{Eth, EthFilter}; -use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, TransactionRequest, OptionalValue, Index, Filter, Log}; +use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, TransactionRequest, OptionalValue, Index, Filter, Log, Receipt}; use v1::helpers::{PollFilter, PollManager, ExternalMinerService, ExternalMiner}; use util::keys::store::AccountProvider; @@ -294,9 +294,12 @@ impl Eth for EthClient } fn transaction_receipt(&self, params: Params) -> Result { - unimplemented!(); - //from_params::<(H256,)>(params) - //.and_then(|(hash,)| self.transaction_receipt(TransactionId::Hash(hash))) + from_params::<(H256,)>(params) + .and_then(|(hash,)| { + let client = take_weak!(self.client); + let receipt = client.transaction_receipt(TransactionId::Hash(hash)); + to_value(&receipt.map(Receipt::from)) + }) } fn uncle_by_block_hash_and_index(&self, params: Params) -> Result { From 2aa3864d6747ea94349fa9cc4a9ed679fc93a68a Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 21 Mar 2016 15:55:46 +0100 Subject: [PATCH 89/91] Merge with master --- Cargo.lock | 3 +-- ethcore/src/client/client.rs | 3 ++- ethcore/src/client/test_client.rs | 2 +- miner/src/miner.rs | 33 +++++++++++++++++++------------ 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13787c22f..51b4b2740 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,7 +236,6 @@ dependencies = [ name = "ethcore-rpc" version = "1.0.0" dependencies = [ - "clippy 0.0.50 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.54 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.0.0", "ethcore 1.0.0", @@ -293,7 +292,7 @@ dependencies = [ name = "ethjson" version = "0.1.0" dependencies = [ - "ethcore-util 1.1.0", + "ethcore-util 1.0.0", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 9737fc982..76ee769cf 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -214,6 +214,7 @@ impl Client where V: Verifier { let last_hashes = self.build_last_hashes(header.parent_hash.clone()); let db = self.state_db.lock().unwrap().spawn(); + let enact_result = enact_verified(&block, engine, db, &parent, last_hashes); if let Err(e) = enact_result { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); @@ -418,7 +419,7 @@ impl BlockChainClient for Client where V: Verifier { // give the sender max balance state.sub_balance(&sender, &balance); state.add_balance(&sender, &U256::max_value()); - Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t, false) + Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t) } // TODO [todr] Should be moved to miner crate eventually. diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 27e4eefe8..48c16ac10 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -236,7 +236,7 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option { + fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> Option<(ClosedBlock, HashSet)> { None } diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 478005d4b..e1b314d57 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -97,26 +97,33 @@ impl Miner { self.transaction_queue.lock().unwrap().set_minimal_gas_price(min_gas_price); } -<<<<<<< HEAD - fn update_gas_limit(&self, chain: &BlockChainClient) { - let gas_limit = HeaderView::new(&chain.best_block_header()).gas_limit(); - let mut queue = self.transaction_queue.lock().unwrap(); - queue.set_gas_limit(gas_limit); -======= /// Prepares new block for sealing including top transactions from queue. - pub fn prepare_sealing(&self, chain: &BlockChainClient) { - let no_of_transactions = 128; - // TODO: should select transactions orm queue according to gas limit of block. - let transactions = self.transaction_queue.lock().unwrap().top_transactions(no_of_transactions); - + fn prepare_sealing(&self, chain: &BlockChainClient) { + let transactions = self.transaction_queue.lock().unwrap().top_transactions(); let b = chain.prepare_sealing( self.author(), self.gas_floor_target(), self.extra_data(), transactions, ); - *self.sealing_block.lock().unwrap() = b; ->>>>>>> b684bc9... Updating sealing when new transactions are received + + *self.sealing_block.lock().unwrap() = b.map(|(block, invalid_transactions)| { + let mut queue = self.transaction_queue.lock().unwrap(); + queue.remove_all( + &invalid_transactions.into_iter().collect::>(), + |a: &Address| AccountDetails { + nonce: chain.nonce(a), + balance: chain.balance(a), + } + ); + block + }); + } + + fn update_gas_limit(&self, chain: &BlockChainClient) { + let gas_limit = HeaderView::new(&chain.best_block_header()).gas_limit(); + let mut queue = self.transaction_queue.lock().unwrap(); + queue.set_gas_limit(gas_limit); } } From 3b766f01f2e33a26ef1d23393dfbfd306885e6fb Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 21 Mar 2016 18:07:07 +0100 Subject: [PATCH 90/91] Fixed rpc tests --- rpc/src/v1/tests/eth.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 72235b390..db18a853e 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -309,7 +309,6 @@ fn rpc_eth_call() { logs: vec![], contracts_created: vec![], output: vec![0x12, 0x34, 0xff], - trace: None, }); let request = r#"{ @@ -342,7 +341,6 @@ fn rpc_eth_estimate_gas() { logs: vec![], contracts_created: vec![], output: vec![0x12, 0x34, 0xff], - trace: None, }); let request = r#"{ From bf4e4df4c883580edd3194fb2e4d1ca8406e8913 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 21 Mar 2016 18:51:22 +0100 Subject: [PATCH 91/91] Fixed sync tests --- sync/src/chain.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 9c756973b..4fd386333 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1684,8 +1684,8 @@ mod tests { // then let status = sync.miner.status(); - assert_eq!(status.transaction_queue_pending, 0); - assert_eq!(status.transaction_queue_future, 0); + assert_eq!(status.transactions_in_pending_queue, 0); + assert_eq!(status.transactions_in_future_queue, 0); } #[test]