From 0c4cd00c1f821eae546f6f6fb925380f5f126300 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 22 May 2016 12:42:22 +0200 Subject: [PATCH 1/9] Fix styling - don't mix spaces with tabs!!! --- rpc/src/v1/impls/eth.rs | 58 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 9a542ea2b..21f89eee6 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -41,12 +41,13 @@ use util::keys::store::AccountProvider; use serde; /// Eth rpc implementation. -pub struct EthClient - where C: BlockChainClient, - S: SyncProvider, - A: AccountProvider, - M: MinerService, - EM: ExternalMinerService { +pub struct EthClient where + C: BlockChainClient, + S: SyncProvider, + A: AccountProvider, + M: MinerService, + EM: ExternalMinerService { + client: Weak, sync: Weak, accounts: Weak, @@ -55,12 +56,12 @@ pub struct EthClient seed_compute: Mutex, } -impl EthClient - where C: BlockChainClient, - S: SyncProvider, - A: AccountProvider, - M: MinerService, - EM: ExternalMinerService { +impl EthClient where + C: BlockChainClient, + S: SyncProvider, + A: AccountProvider, + M: MinerService, + EM: ExternalMinerService { /// Creates new EthClient. pub fn new(client: &Arc, sync: &Arc, accounts: &Arc, miner: &Arc, em: &Arc) @@ -214,12 +215,12 @@ fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNum } } -impl Eth for EthClient - where C: BlockChainClient + 'static, - S: SyncProvider + 'static, - A: AccountProvider + 'static, - M: MinerService + 'static, - EM: ExternalMinerService + 'static { +impl Eth for EthClient where + C: BlockChainClient + 'static, + S: SyncProvider + 'static, + A: AccountProvider + 'static, + M: MinerService + 'static, + EM: ExternalMinerService + 'static { fn protocol_version(&self, params: Params) -> Result { match params { @@ -252,7 +253,6 @@ impl Eth for EthClient } } - // TODO: do not hardcode author. fn author(&self, params: Params) -> Result { match params { Params::None => to_value(&take_weak!(self.miner).author()), @@ -260,7 +260,6 @@ impl Eth for EthClient } } - // TODO: return real value of mining once it's implemented. fn is_mining(&self, params: Params) -> Result { match params { Params::None => to_value(&self.external_miner.is_mining()), @@ -268,7 +267,6 @@ impl Eth for EthClient } } - // TODO: return real hashrate once we have mining fn hashrate(&self, params: Params) -> Result { match params { Params::None => to_value(&self.external_miner.hashrate()), @@ -550,18 +548,18 @@ impl Eth for EthClient } /// Eth filter rpc implementation. -pub struct EthFilterClient - where C: BlockChainClient, - M: MinerService { +pub struct EthFilterClient where + C: BlockChainClient, + M: MinerService { client: Weak, miner: Weak, polls: Mutex>, } -impl EthFilterClient - where C: BlockChainClient, - M: MinerService { +impl EthFilterClient where + C: BlockChainClient, + M: MinerService { /// Creates new Eth filter client. pub fn new(client: &Arc, miner: &Arc) -> Self { @@ -573,9 +571,9 @@ impl EthFilterClient } } -impl EthFilter for EthFilterClient - where C: BlockChainClient + 'static, - M: MinerService + 'static { +impl EthFilter for EthFilterClient where + C: BlockChainClient + 'static, + M: MinerService + 'static { fn new_filter(&self, params: Params) -> Result { from_params::<(Filter,)>(params) From 564a996620a53d8cf861837d50d776ee373ba3b2 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 23 May 2016 09:51:36 +0200 Subject: [PATCH 2/9] Basic hex block exporting. --- ethcore/src/client/client.rs | 19 ++++++------ parity/cli.rs | 17 ++++++++-- parity/main.rs | 60 ++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 56048382a..83b77b774 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -374,6 +374,16 @@ impl Client where V: Verifier { self.chain.configure_cache(pref_cache_size, max_cache_size); } + /// Look up the block number for the given block ID. + pub fn block_number(&self, id: BlockID) -> Option { + match id { + BlockID::Number(number) => Some(number), + BlockID::Hash(ref hash) => self.chain.block_number(hash), + BlockID::Earliest => Some(0), + BlockID::Latest => Some(self.chain.best_block_number()) + } + } + fn block_hash(chain: &BlockChain, id: BlockID) -> Option { match id { BlockID::Hash(hash) => Some(hash), @@ -383,15 +393,6 @@ impl Client where V: Verifier { } } - fn block_number(&self, id: BlockID) -> Option { - match id { - BlockID::Number(number) => Some(number), - BlockID::Hash(ref hash) => self.chain.block_number(hash), - BlockID::Earliest => Some(0), - 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), diff --git a/parity/cli.rs b/parity/cli.rs index e09c4b7f4..d5b650d2e 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -24,6 +24,7 @@ Parity. Ethereum Client. Usage: parity daemon [options] parity account (new | list) [options] + parity export [ ] [options] parity [options] Protocol Options: @@ -42,9 +43,9 @@ Account Options: ACCOUNTS is a comma-delimited list of addresses. --password FILE Provide a file containing a password for unlocking an account. - --keys-iterations NUM Specify the number of iterations to use when deriving key - from the password (bigger is more secure) - [default: 10240]. + --keys-iterations NUM Specify the number of iterations to use when + deriving key from the password (bigger is more + secure) [default: 10240]. --no-import-keys Do not import keys from legacy clients. Networking Options: @@ -142,6 +143,12 @@ Footprint Options: the entire system, overrides other cache and queue options. +Export Options: + --from BLOCK Export from block BLOCK, which may be an index or + hash [default: 0]. + --to BLOCK Export to (including) block NUMBER, which may be an + index, hash or 'latest' [default: latest]. + Virtual Machine Options: --jitvm Enable the JIT VM. @@ -186,7 +193,9 @@ pub struct Args { pub cmd_account: bool, pub cmd_new: bool, pub cmd_list: bool, + pub cmd_export: bool, pub arg_pid_file: String, + pub arg_file: Option, pub flag_chain: String, pub flag_db_path: String, pub flag_identity: String, @@ -230,6 +239,8 @@ pub struct Args { pub flag_tx_limit: usize, pub flag_logging: Option, pub flag_version: bool, + pub flag_from: String, + pub flag_to: String, pub flag_jitvm: bool, // legacy... pub flag_geth: bool, diff --git a/parity/main.rs b/parity/main.rs index a2750dff4..7035bddbd 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -66,6 +66,7 @@ mod configuration; use ctrlc::CtrlC; use util::*; use util::panics::{MayPanic, ForwardPanic, PanicHandler}; +use ethcore::client::{BlockID, BlockChainClient}; use ethcore::service::ClientService; use ethsync::EthSync; use ethminer::{Miner, MinerService, ExternalMiner}; @@ -104,6 +105,11 @@ fn execute(conf: Configuration) { return; } + if conf.args.cmd_export { + execute_export(conf); + return; + } + execute_client(conf); } @@ -216,6 +222,60 @@ fn flush_stdout() { ::std::io::stdout().flush().expect("stdout is flushable; qed"); } +fn execute_export(conf: Configuration) { + println!("Exporting to {:?} from {}, to {}", conf.args.arg_file, conf.args.flag_from, conf.args.flag_to); + + // Setup panic handler + let panic_handler = PanicHandler::new_in_arc(); + + // Raise fdlimit + unsafe { ::fdlimit::raise_fd_limit(); } + + let spec = conf.spec(); + let net_settings = NetworkConfiguration { + config_path: None, + listen_address: None, + public_address: None, + udp_port: None, + nat_enabled: false, + discovery_enabled: false, + pin: true, + boot_nodes: Vec::new(), + use_secret: None, + ideal_peers: 0, + }; + let client_config = conf.client_config(&spec); + + // Build client + let service = ClientService::start( + client_config, spec, net_settings, Path::new(&conf.path()) + ).unwrap_or_else(|e| die_with_error("Client", e)); + + panic_handler.forward_from(&service); + let client = service.client(); + + // we have a client! + let parse_block_id = |s: &str| -> u64 { + if s == "latest" { + client.chain_info().best_block_number + } else if let Ok(n) = s.parse::() { + n + } else if let Ok(h) = H256::from_str(s) { + client.block_number(BlockID::Hash(h)).unwrap_or_else(|| { + die!("Unknown block hash passed to --to parameter: {:?}", s); + }) + } else { + die!("Invalid --to parameter given: {:?}", s); + } + }; + let from = parse_block_id(&conf.args.flag_from); + let to = parse_block_id(&conf.args.flag_to); + + for i in from..to { + println!("{}", client.deref().block(BlockID::Number(i)).unwrap().pretty()); + } +} + fn execute_account_cli(conf: Configuration) { use util::keys::store::SecretStore; use rpassword::read_password; From 5579582a52c5628fcc22f26fe6f063601c9205bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 May 2016 11:30:11 +0200 Subject: [PATCH 3/9] Sign and send transaction --- rpc/src/v1/impls/eth.rs | 57 ++++++++++++-------- rpc/src/v1/tests/eth.rs | 75 ++++++++++++++++++++++++++ rpc/src/v1/traits/eth.rs | 4 ++ util/src/keys/store.rs | 45 +++++++++++++++- util/src/keys/test_account_provider.rs | 11 ++++ 5 files changed, 168 insertions(+), 24 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 21f89eee6..f6543ec04 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -47,7 +47,7 @@ pub struct EthClient where A: AccountProvider, M: MinerService, EM: ExternalMinerService { - + client: Weak, sync: Weak, accounts: Weak, @@ -153,6 +153,27 @@ impl EthClient where } } + fn sign_and_dispatch(&self, request: TransactionRequest, secret: H256) -> Result { + let signed_transaction = { + let client = take_weak!(self.client); + let miner = take_weak!(self.miner); + EthTransaction { + nonce: request.nonce + .or_else(|| miner + .last_nonce(&request.from) + .map(|nonce| nonce + U256::one())) + .unwrap_or_else(|| client.nonce(&request.from)), + action: request.to.map_or(Action::Create, Action::Call), + gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), + gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), + value: request.value.unwrap_or_else(U256::zero), + data: request.data.map_or_else(Vec::new, |d| d.to_vec()), + }.sign(&secret) + }; + trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); + self.dispatch_transaction(signed_transaction) + } + fn sign_call(&self, request: CallRequest) -> Result { let client = take_weak!(self.client); let miner = take_weak!(self.miner); @@ -483,27 +504,19 @@ impl Eth for EthClient where .and_then(|(request, )| { let accounts = take_weak!(self.accounts); match accounts.account_secret(&request.from) { - Ok(secret) => { - let signed_transaction = { - let client = take_weak!(self.client); - let miner = take_weak!(self.miner); - EthTransaction { - nonce: request.nonce - .or_else(|| miner - .last_nonce(&request.from) - .map(|nonce| nonce + U256::one())) - .unwrap_or_else(|| client.nonce(&request.from)), - action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), - gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), - value: request.value.unwrap_or_else(U256::zero), - data: request.data.map_or_else(Vec::new, |d| d.to_vec()), - }.sign(&secret) - }; - trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); - self.dispatch_transaction(signed_transaction) - }, - Err(_) => { to_value(&H256::zero()) } + Ok(secret) => self.sign_and_dispatch(request, secret), + Err(_) => to_value(&H256::zero()) + } + }) + } + + fn sign_and_send_transaction(&self, params: Params) -> Result { + from_params::<(TransactionRequest, String)>(params) + .and_then(|(request, password)| { + let accounts = take_weak!(self.accounts); + match accounts.locked_account_secret(&request.from, &password) { + Ok(secret) => self.sign_and_dispatch(request, secret), + Err(_) => to_value(&H256::zero()), } }) } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 1e6aa05b2..cb2911b21 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -521,6 +521,81 @@ fn rpc_eth_send_transaction() { assert_eq!(tester.io.handle_request(request.as_ref()), Some(response)); } +#[test] +fn rpc_eth_sign_and_send_transaction_with_invalid_password() { + let account = TestAccount::new("password123"); + let address = account.address(); + + let tester = EthTester::default(); + tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account); + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_signAndSendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }, "password321"], + "id": 1 + }"#; + + let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#; + + assert_eq!(tester.io.handle_request(request.as_ref()), Some(response.into())); +} + +#[test] +fn rpc_eth_sign_and_send_transaction() { + let account = TestAccount::new("password123"); + let address = account.address(); + let secret = account.secret.clone(); + + let tester = EthTester::default(); + tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account); + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_signAndSendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }, "password123"], + "id": 1 + }"#; + + let t = Transaction { + nonce: U256::zero(), + gas_price: U256::from(0x9184e72a000u64), + gas: U256::from(0x76c0), + action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + value: U256::from(0x9184e72au64), + data: vec![] + }.sign(&secret); + + let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; + + assert_eq!(tester.io.handle_request(request.as_ref()), Some(response)); + + tester.miner.last_nonces.write().unwrap().insert(address.clone(), U256::zero()); + + let t = Transaction { + nonce: U256::one(), + gas_price: U256::from(0x9184e72a000u64), + gas: U256::from(0x76c0), + action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + value: U256::from(0x9184e72au64), + data: vec![] + }.sign(&secret); + + let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; + + assert_eq!(tester.io.handle_request(request.as_ref()), Some(response)); +} + #[test] #[ignore] fn rpc_eth_send_raw_transaction() { diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index a28f72c5c..9cded5eb9 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -80,6 +80,9 @@ pub trait Eth: Sized + Send + Sync + 'static { /// Sends transaction. fn send_transaction(&self, _: Params) -> Result { rpc_unimplemented!() } + /// Sends transaction and signs it in single call. The account is not unlocked in such case. + fn sign_and_send_transaction(&self, _: Params) -> Result { rpc_unimplemented!() } + /// Sends signed transaction. fn send_raw_transaction(&self, _: Params) -> Result { rpc_unimplemented!() } @@ -152,6 +155,7 @@ pub trait Eth: Sized + Send + Sync + 'static { delegate.add_method("eth_getCode", Eth::code_at); delegate.add_method("eth_sign", Eth::sign); delegate.add_method("eth_sendTransaction", Eth::send_transaction); + delegate.add_method("eth_signAndSendTransaction", Eth::sign_and_send_transaction); delegate.add_method("eth_sendRawTransaction", Eth::send_raw_transaction); delegate.add_method("eth_call", Eth::call); delegate.add_method("eth_estimateGas", Eth::estimate_gas); diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index 13e53bdb5..3ecabc07c 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -58,13 +58,15 @@ pub enum EncryptedHashMapError { InvalidValueFormat(FromBytesError), } -/// Error retrieving value from encrypted hashmap +/// Error while signing a message #[derive(Debug)] pub enum SigningError { /// Account passed does not exist NoAccount, /// Account passed is not unlocked AccountNotUnlocked, + /// Invalid passphrase + InvalidPassword, /// Invalid secret in store InvalidSecret } @@ -96,6 +98,8 @@ pub trait AccountProvider : Send + Sync { fn new_account(&self, pass: &str) -> Result; /// Returns secret for unlocked `account`. fn account_secret(&self, account: &Address) -> Result; + /// Returns secret for locked account given passphrase. + fn locked_account_secret(&self, account: &Address, pass: &str) -> Result; /// Returns signature when unlocked `account` signs `message`. fn sign(&self, account: &Address, message: &H256) -> Result { self.account_secret(account).and_then(|s| crypto::ec::sign(&s, message).map_err(|_| SigningError::InvalidSecret)) @@ -127,7 +131,11 @@ impl AccountProvider for AccountService { fn account_secret(&self, account: &Address) -> Result { self.secret_store.read().unwrap().account_secret(account) } - /// Returns secret for unlocked account + /// Returns secret for locked account given passphrase. + fn locked_account_secret(&self, account: &Address, pass: &str) -> Result { + self.secret_store.read().unwrap().locked_account_secret(account, pass) + } + /// Signs a message using key of given unlocked account address. fn sign(&self, account: &Address, message: &H256) -> Result { self.secret_store.read().unwrap().sign(account, message) } @@ -317,6 +325,16 @@ impl SecretStore { ret } + /// Returns secret for unlocked account. + pub fn locked_account_secret(&self, account: &Address, pass: &str) -> Result { + let secret_id = try!(self.account(&account).ok_or(SigningError::NoAccount)); + self.get(&secret_id, pass).or_else(|e| Err(match e { + EncryptedHashMapError::InvalidPassword => SigningError::InvalidPassword, + EncryptedHashMapError::UnknownIdentifier => SigningError::NoAccount, + EncryptedHashMapError::InvalidValueFormat(_) => SigningError::InvalidSecret, + })) + } + /// Makes account unlocks expire and removes unused key files from memory pub fn collect_garbage(&mut self) { let mut garbage_lock = self.unlocks.write().unwrap(); @@ -679,6 +697,29 @@ mod tests { assert_eq!(Address::from(kp.public().sha3()), addr); } + + #[test] + fn secret_for_locked_account() { + // given + let temp = RandomTempPath::create_dir(); + let mut sstore = SecretStore::new_test(&temp); + let addr = sstore.new_account("test-pass").unwrap(); + + // when + // Invalid pass + let secret1 = sstore.locked_account_secret(&addr, "test-pass123"); + // Valid pass + let secret2 = sstore.locked_account_secret(&addr, "test-pass"); + // Account not unlocked + let secret3 = sstore.account_secret(&addr); + + + assert!(secret1.is_err(), "Invalid password should not return secret."); + assert!(secret2.is_ok(), "Should return secret provided valid passphrase."); + assert!(secret3.is_err(), "Account should still be locked."); + } + + #[test] fn can_create_service() { let temp = RandomTempPath::create_dir(); diff --git a/util/src/keys/test_account_provider.rs b/util/src/keys/test_account_provider.rs index b8aed85ce..539c6ca8c 100644 --- a/util/src/keys/test_account_provider.rs +++ b/util/src/keys/test_account_provider.rs @@ -103,5 +103,16 @@ impl AccountProvider for TestAccountProvider { .ok_or(SigningError::NoAccount) .map(|acc| acc.secret.clone()) } + + fn locked_account_secret(&self, address: &Address, pass: &str) -> Result { + let accounts = self.accounts.read().unwrap(); + match accounts.get(address) { + Some(ref acc) if acc.password == pass => { + Ok(acc.secret.clone()) + }, + Some(ref _acc) => Err(SigningError::InvalidPassword), + _ => Err(SigningError::NoAccount), + } + } } From 256557d3ccb721840e17c7a439a6ab00cae79f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 May 2016 11:46:01 +0200 Subject: [PATCH 4/9] Removing warnings --- ipc/codegen/src/serialization.rs | 1 - json/src/spec/engine.rs | 2 -- util/src/io/service.rs | 3 --- util/src/keys/test_account_provider.rs | 2 +- util/src/network/discovery.rs | 1 - util/src/network/host.rs | 3 +-- util/src/network/session.rs | 9 ++++----- util/src/trie/node.rs | 9 ++++----- util/src/trie/sectriedb.rs | 1 - util/src/trie/sectriedbmut.rs | 1 - 10 files changed, 10 insertions(+), 22 deletions(-) diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index 9854993c5..a249b3830 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -24,7 +24,6 @@ use syntax::ast::{ use syntax::ast; use syntax::codemap::Span; use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; use syntax::ptr::P; pub struct Error; diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs index 7d81aaa5a..e877e37a8 100644 --- a/json/src/spec/engine.rs +++ b/json/src/spec/engine.rs @@ -16,8 +16,6 @@ //! Engine deserialization. -use serde::Deserializer; -use serde::de::Visitor; use spec::Ethash; use spec::BasicAuthority; diff --git a/util/src/io/service.rs b/util/src/io/service.rs index 95aa19e47..d946463f5 100644 --- a/util/src/io/service.rs +++ b/util/src/io/service.rs @@ -18,11 +18,8 @@ use std::sync::*; use std::thread::{self, JoinHandle}; use std::collections::HashMap; use mio::*; -use hash::*; -use rlp::*; use error::*; use io::{IoError, IoHandler}; -use arrayvec::*; use crossbeam::sync::chase_lev; use io::worker::{Worker, Work, WorkType}; use panics::*; diff --git a/util/src/keys/test_account_provider.rs b/util/src/keys/test_account_provider.rs index b8aed85ce..34aa41a1a 100644 --- a/util/src/keys/test_account_provider.rs +++ b/util/src/keys/test_account_provider.rs @@ -19,7 +19,7 @@ use std::sync::RwLock; use std::collections::HashMap; use std::io; -use hash::{Address, FixedHash}; +use hash::Address; use crypto::{Secret, KeyPair}; use super::store::{AccountProvider, SigningError, EncryptedHashMapError}; diff --git a/util/src/network/discovery.rs b/util/src/network/discovery.rs index d755c58e7..d65309246 100644 --- a/util/src/network/discovery.rs +++ b/util/src/network/discovery.rs @@ -512,7 +512,6 @@ mod tests { use crypto::KeyPair; use std::str::FromStr; use rustc_serialize::hex::FromHex; - use rlp::*; #[test] fn find_node() { diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 971f3a424..13b64eb3c 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -16,7 +16,6 @@ use std::net::{SocketAddr}; use std::collections::{HashMap}; -use std::hash::{Hasher}; use std::str::{FromStr}; use std::sync::*; use std::ops::*; @@ -897,7 +896,7 @@ impl IoHandler> for Host where Messa fn timeout(&self, io: &IoContext>, token: TimerToken) { match token { IDLE => self.maintain_network(io), - INIT_PUBLIC => self.init_public_interface(io).unwrap_or_else(|e| + INIT_PUBLIC => self.init_public_interface(io).unwrap_or_else(|e| warn!("Error initializing public interface: {:?}", e)), FIRST_SESSION ... LAST_SESSION => self.connection_timeout(token, io), FIRST_HANDSHAKE ... LAST_HANDSHAKE => self.connection_timeout(token, io), diff --git a/util/src/network/session.rs b/util/src/network/session.rs index 614b7eeb6..6c0a20a14 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -17,7 +17,6 @@ use std::net::SocketAddr; use std::io; use mio::*; -use hash::*; use rlp::*; use network::connection::{EncryptedConnection, Packet}; use network::handshake::Handshake; @@ -58,7 +57,7 @@ pub enum SessionData { data: Vec, /// Packet protocol ID protocol: &'static str, - /// Zero based packet ID + /// Zero based packet ID packet_id: u8, }, } @@ -111,7 +110,7 @@ const PACKET_USER: u8 = 0x10; const PACKET_LAST: u8 = 0x7f; impl Session { - /// Create a new session out of comepleted handshake. This clones the handshake connection object + /// Create a new session out of comepleted handshake. This clones the handshake connection object /// and leaves the handhsake in limbo to be deregistered from the event loop. pub fn new(h: &mut Handshake, host: &HostInfo) -> Result { let id = h.id.clone(); @@ -159,7 +158,7 @@ impl Session { pub fn done(&self) -> bool { self.expired() && !self.connection.is_sending() } - /// Replace socket token + /// Replace socket token pub fn set_token(&mut self, token: StreamToken) { self.connection.set_token(token); } @@ -172,7 +171,7 @@ impl Session { /// Readable IO handler. Returns packet data if available. pub fn readable(&mut self, io: &IoContext, host: &HostInfo) -> Result where Message: Send + Sync + Clone { if self.expired() { - return Ok(SessionData::None) + return Ok(SessionData::None) } match try!(self.connection.readable(io)) { Some(data) => Ok(try!(self.read_packet(data, host))), diff --git a/util/src/trie/node.rs b/util/src/trie/node.rs index 2ebcd0ef0..8f9351d05 100644 --- a/util/src/trie/node.rs +++ b/util/src/trie/node.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use hash::*; use nibbleslice::*; use bytes::*; use rlp::*; @@ -34,14 +33,14 @@ pub enum Node<'a> { } impl<'a> Node<'a> { - /// Decode the `node_rlp` and return the Node. + /// Decode the `node_rlp` and return the Node. pub fn decoded(node_rlp: &'a [u8]) -> Node<'a> { let r = Rlp::new(node_rlp); match r.prototype() { - // either leaf or extension - decode first item with NibbleSlice::??? + // either leaf or extension - decode first item with NibbleSlice::??? // and use is_leaf return to figure out which. // if leaf, second item is a value (is_data()) - // if extension, second item is a node (either SHA3 to be looked up and + // if extension, second item is a node (either SHA3 to be looked up and // fed back into this function or inline RLP which can be fed back into this function). Prototype::List(2) => match NibbleSlice::from_encoded(r.at(0).data()) { (slice, true) => Node::Leaf(slice, r.at(1).data()), @@ -100,7 +99,7 @@ impl<'a> Node<'a> { } /// Encode the node, adding it to `journal` if necessary and return the RLP valid for - /// insertion into a parent node. + /// insertion into a parent node. pub fn encoded_and_added(&self, journal: &mut Journal) -> Bytes { let mut stream = RlpStream::new(); match *self { diff --git a/util/src/trie/sectriedb.rs b/util/src/trie/sectriedb.rs index 3e74f8655..685af335b 100644 --- a/util/src/trie/sectriedb.rs +++ b/util/src/trie/sectriedb.rs @@ -17,7 +17,6 @@ use hash::*; use sha3::*; use hashdb::*; -use rlp::*; use super::triedb::*; use super::trietraits::*; diff --git a/util/src/trie/sectriedbmut.rs b/util/src/trie/sectriedbmut.rs index 7e17610f8..895a821c9 100644 --- a/util/src/trie/sectriedbmut.rs +++ b/util/src/trie/sectriedbmut.rs @@ -17,7 +17,6 @@ use hash::*; use sha3::*; use hashdb::*; -use rlp::*; use super::triedbmut::*; use super::trietraits::*; From fb0be9e730f2141e2bc0edadce6e0e07be0ee318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 May 2016 11:55:10 +0200 Subject: [PATCH 5/9] Updating status page (new docs) --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 14a73958a..3ea77cf45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -863,7 +863,7 @@ dependencies = [ [[package]] name = "parity-status" version = "0.4.3" -source = "git+https://github.com/ethcore/parity-status.git#1d383d74010f6ebcd712b60b8fc5ff547b44f4e5" +source = "git+https://github.com/ethcore/parity-status.git#606dfe6d272792f2fdb90909318f2439d58330a5" dependencies = [ "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] From b1cfbc460ef468722ccc06bf1d64d893c7d00954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 May 2016 12:56:18 +0200 Subject: [PATCH 6/9] Using signAndSend in topbar --- Cargo.lock | 6 +++--- webapp/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ea77cf45..13c107bbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,7 +357,7 @@ dependencies = [ "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-daodapp 0.2.1 (git+https://github.com/ethcore/parity-daodapp-rs.git)", - "parity-idmanager 0.2.2 (git+https://github.com/ethcore/parity-idmanager-rs.git)", + "parity-idmanager 0.3.2 (git+https://github.com/ethcore/parity-idmanager-rs.git)", "parity-makerotc 0.1.3 (git+https://github.com/ethcore/parity-makerotc-rs.git)", "parity-status 0.4.3 (git+https://github.com/ethcore/parity-status.git)", "parity-wallet 0.4.1 (git+https://github.com/ethcore/parity-wallet.git)", @@ -846,8 +846,8 @@ dependencies = [ [[package]] name = "parity-idmanager" -version = "0.2.2" -source = "git+https://github.com/ethcore/parity-idmanager-rs.git#19dd79ca7b7afb8824ad072b43ca63babe2ba9bc" +version = "0.3.2" +source = "git+https://github.com/ethcore/parity-idmanager-rs.git#5bc85d456455f7b9f6f257021dab9394de9e66b4" dependencies = [ "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml index 7d13f9260..0b6c0d075 100644 --- a/webapp/Cargo.toml +++ b/webapp/Cargo.toml @@ -23,7 +23,7 @@ ethcore-util = { path = "../util" } parity-webapp = { git = "https://github.com/ethcore/parity-webapp.git", version = "0.2" } # List of apps parity-status = { git = "https://github.com/ethcore/parity-status.git", version = "0.4.3" } -parity-idmanager = { git = "https://github.com/ethcore/parity-idmanager-rs.git", version = "0.2.2" } +parity-idmanager = { git = "https://github.com/ethcore/parity-idmanager-rs.git", version = "0.3.2" } parity-wallet = { git = "https://github.com/ethcore/parity-wallet.git", version = "0.4.1", optional = true } parity-daodapp = { git = "https://github.com/ethcore/parity-daodapp-rs.git", version = "0.2.1", optional = true } parity-makerotc = { git = "https://github.com/ethcore/parity-makerotc-rs.git", version = "0.1.3", optional = true } From 6c64aec13738b9412e0899791f26fc4345f18908 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 23 May 2016 18:42:59 +0200 Subject: [PATCH 7/9] Export formats and to file. --- parity/cli.rs | 3 +++ parity/main.rs | 27 ++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index d5b650d2e..e0edec29f 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -148,6 +148,8 @@ Export Options: hash [default: 0]. --to BLOCK Export to (including) block NUMBER, which may be an index, hash or 'latest' [default: latest]. + --format FORMAT Export in given format. FORMAT must be one of 'hex' + and 'binary' [default: hex]. Virtual Machine Options: --jitvm Enable the JIT VM. @@ -241,6 +243,7 @@ pub struct Args { pub flag_version: bool, pub flag_from: String, pub flag_to: String, + pub flag_format: String, pub flag_jitvm: bool, // legacy... pub flag_geth: bool, diff --git a/parity/main.rs b/parity/main.rs index 7035bddbd..52f6a23b9 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -65,6 +65,7 @@ mod configuration; use ctrlc::CtrlC; use util::*; +use std::fs::File; use util::panics::{MayPanic, ForwardPanic, PanicHandler}; use ethcore::client::{BlockID, BlockChainClient}; use ethcore::service::ClientService; @@ -222,6 +223,11 @@ fn flush_stdout() { ::std::io::stdout().flush().expect("stdout is flushable; qed"); } +enum DataFormat { + Hex, + Binary, +} + fn execute_export(conf: Configuration) { println!("Exporting to {:?} from {}, to {}", conf.args.arg_file, conf.args.flag_from, conf.args.flag_to); @@ -265,14 +271,29 @@ fn execute_export(conf: Configuration) { die!("Unknown block hash passed to --to parameter: {:?}", s); }) } else { - die!("Invalid --to parameter given: {:?}", s); + die!("Invalid block ID parameter given: {:?}", s); } }; let from = parse_block_id(&conf.args.flag_from); let to = parse_block_id(&conf.args.flag_to); + let format = match conf.args.flag_format.deref() { + "binary" | "bin" => DataFormat::Binary, + "hex" => DataFormat::Hex, + x => die!("Invalid --format parameter given: {:?}", x), + }; - for i in from..to { - println!("{}", client.deref().block(BlockID::Number(i)).unwrap().pretty()); + let mut out: Box = if let Some(f) = conf.args.arg_file { + Box::new(File::create(&f).unwrap_or_else(|_| die!("Cannot write to file given: {}", f))) + } else { + Box::new(::std::io::stdout()) + }; + + for i in from..(to + 1) { + let b = client.deref().block(BlockID::Number(i)).unwrap(); + match format { + DataFormat::Binary => { out.write(&b).expect("Couldn't write to stream."); } + DataFormat::Hex => { out.write_fmt(format_args!("{}", b.pretty())).expect("Couldn't write to stream."); } + } } } From 1def165c0b1878be6fbfee1d0432155b3cac374a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 23 May 2016 18:47:11 +0200 Subject: [PATCH 8/9] Adding info messages on mined blocks (#1127) --- miner/src/miner.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/miner/src/miner.rs b/miner/src/miner.rs index ed3c976c0..19869229f 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -459,15 +459,18 @@ impl MinerService for Miner { if let Some(b) = self.sealing_work.lock().unwrap().take_used_if(|b| &b.hash() == &pow_hash) { match chain.try_seal(b.lock(), seal) { Err(_) => { + info!(target: "miner", "Mined block rejected, PoW was invalid."); Err(Error::PowInvalid) } Ok(sealed) => { + info!(target: "miner", "New block mined, hash: {}", sealed.header().hash()); // TODO: commit DB from `sealed.drain` and make a VerifiedBlock to skip running the transactions twice. try!(chain.import_block(sealed.rlp_bytes())); Ok(()) } } } else { + info!(target: "miner", "Mined block rejected, PoW hash invalid or out of date."); Err(Error::PowHashInvalid) } } From 78d3dfbfa6b15df99546c2a070ae9d65934de215 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 24 May 2016 13:31:03 +0200 Subject: [PATCH 9/9] Fix error text. --- parity/main.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 52f6a23b9..b36bfbe58 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -261,21 +261,21 @@ fn execute_export(conf: Configuration) { let client = service.client(); // we have a client! - let parse_block_id = |s: &str| -> u64 { + let parse_block_id = |s: &str, arg: &str| -> u64 { if s == "latest" { client.chain_info().best_block_number } else if let Ok(n) = s.parse::() { n } else if let Ok(h) = H256::from_str(s) { client.block_number(BlockID::Hash(h)).unwrap_or_else(|| { - die!("Unknown block hash passed to --to parameter: {:?}", s); + die!("Unknown block hash passed to {} parameter: {:?}", arg, s); }) } else { - die!("Invalid block ID parameter given: {:?}", s); + die!("Invalid {} parameter given: {:?}", arg, s); } }; - let from = parse_block_id(&conf.args.flag_from); - let to = parse_block_id(&conf.args.flag_to); + let from = parse_block_id(&conf.args.flag_from, "--from"); + let to = parse_block_id(&conf.args.flag_to, "--to"); let format = match conf.args.flag_format.deref() { "binary" | "bin" => DataFormat::Binary, "hex" => DataFormat::Hex,