From d0b32f8d426398297bc5d07d859a27b6e7c5d80b Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 13:02:53 +0200 Subject: [PATCH 01/43] trait import from branch --- db/src/traits.rs | 95 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 18 deletions(-) diff --git a/db/src/traits.rs b/db/src/traits.rs index 1e5b2acf4..dd5743fe5 100644 --- a/db/src/traits.rs +++ b/db/src/traits.rs @@ -1,21 +1,38 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + //! Ethcore database trait -use ipc::BinaryConvertable; use std::mem; use ipc::binary::BinaryConvertError; use std::collections::VecDeque; +use std::cell::RefCell; -pub type TransactionHandle = u32; pub type IteratorHandle = u32; +pub const DEFAULT_CACHE_LEN: usize = 12288; + #[derive(Binary)] pub struct KeyValue { pub key: Vec, pub value: Vec, } -#[derive(Debug, Binary)] -pub enum Error { + #[derive(Debug, Binary)] + pub enum Error { AlreadyOpen, IsClosed, RocksDb(String), @@ -28,13 +45,36 @@ pub enum Error { #[derive(Binary)] pub struct DatabaseConfig { /// Optional prefix size in bytes. Allows lookup by partial key. - pub prefix_size: Option + pub prefix_size: Option, + /// write cache length + pub cache: usize, } -pub trait DatabaseService { +impl Default for DatabaseConfig { + fn default() -> DatabaseConfig { + DatabaseConfig { + prefix_size: None, + cache: DEFAULT_CACHE_LEN, + } + } +} + +impl DatabaseConfig { + fn with_prefix(prefix: usize) -> DatabaseConfig { + DatabaseConfig { + prefix_size: Some(prefix), + cache: DEFAULT_CACHE_LEN, + } + } +} + + pub trait DatabaseService : Sized { /// Opens database in the specified path fn open(&self, config: DatabaseConfig, path: String) -> Result<(), Error>; + /// Opens database in the specified path with the default config + fn open_default(&self, path: String) -> Result<(), Error>; + /// Closes database fn close(&self) -> Result<(), Error>; @@ -44,18 +84,6 @@ pub trait DatabaseService { /// Delete value by key. fn delete(&self, key: &[u8]) -> Result<(), Error>; - /// Insert a key-value pair in the transaction. Any existing value value will be overwritten. - fn transaction_put(&self, transaction: TransactionHandle, key: &[u8], value: &[u8]) -> Result<(), Error>; - - /// Delete value by key using transaction - fn transaction_delete(&self, transaction: TransactionHandle, key: &[u8]) -> Result<(), Error>; - - /// Commit transaction to database. - fn write(&self, tr: TransactionHandle) -> Result<(), Error>; - - /// Initiate new transaction on database - fn new_transaction(&self) -> TransactionHandle; - /// Get value by key. fn get(&self, key: &[u8]) -> Result>, Error>; @@ -70,4 +98,35 @@ pub trait DatabaseService { /// Next key-value for the the given iterator fn iter_next(&self, iterator: IteratorHandle) -> Option; + + /// Dispose iteration that is no longer needed + fn dispose_iter(&self, handle: IteratorHandle) -> Result<(), Error>; + + /// Write client transaction + fn write(&self, transaction: DBTransaction) -> Result<(), Error>; +} + +#[derive(Binary)] +pub struct DBTransaction { + pub writes: RefCell>, + pub removes: RefCell>>, +} + +impl DBTransaction { + pub fn new() -> DBTransaction { + DBTransaction { + writes: RefCell::new(Vec::new()), + removes: RefCell::new(Vec::new()), + } + } + + pub fn put(&self, key: &[u8], value: &[u8]) { + let mut brw = self.writes.borrow_mut(); + brw.push(KeyValue { key: key.to_vec(), value: value.to_vec() }); + } + + pub fn delete(&self, key: &[u8]) { + let mut brw = self.removes.borrow_mut(); + brw.push(key.to_vec()); + } } From 134f48cdfb211c971fc9db8edf7d150bb8e79ded Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 13:05:43 +0200 Subject: [PATCH 02/43] lib import --- db/src/lib.rs.in | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/db/src/lib.rs.in b/db/src/lib.rs.in index 694b4e3e1..4fa43b977 100644 --- a/db/src/lib.rs.in +++ b/db/src/lib.rs.in @@ -19,7 +19,71 @@ extern crate rocksdb; extern crate ethcore_devtools as devtools; extern crate semver; extern crate ethcore_ipc_nano as nanoipc; +extern crate nanomsg; +extern crate crossbeam; extern crate ethcore_util as util; pub mod database; pub mod traits; + +pub use traits::{DatabaseService, DBTransaction, Error}; +pub use database::{Database, DatabaseClient, DatabaseIterator}; + +use std::sync::Arc; +use std::sync::atomic::*; +use std::path::PathBuf; + +pub type DatabaseNanoClient = DatabaseClient<::nanomsg::Socket>; +pub type DatabaseConnection = nanoipc::GuardedSocket; + +#[derive(Debug)] +pub enum ServiceError { + Io(std::io::Error), + Socket(nanoipc::SocketError), +} + +impl std::convert::From for ServiceError { + fn from(io_error: std::io::Error) -> ServiceError { ServiceError::Io(io_error) } +} + +impl std::convert::From for ServiceError { + fn from(socket_error: nanoipc::SocketError) -> ServiceError { ServiceError::Socket(socket_error) } +} + +pub fn blocks_service_url(db_path: &str) -> Result { + let mut path = PathBuf::from(db_path); + try!(::std::fs::create_dir_all(db_path)); + path.push("blocks.ipc"); + Ok(format!("ipc://{}", path.to_str().unwrap())) +} + +pub fn extras_service_url(db_path: &str) -> Result { + let mut path = PathBuf::from(db_path); + try!(::std::fs::create_dir_all(db_path)); + path.push("extras.ipc"); + Ok(format!("ipc://{}", path.to_str().unwrap())) +} + +pub fn blocks_client(db_path: &str) -> Result { + let url = try!(blocks_service_url(db_path)); + let client = try!(nanoipc::init_client::>(&url)); + Ok(client) +} + +pub fn extras_client(db_path: &str) -> Result { + let url = try!(extras_service_url(db_path)); + let client = try!(nanoipc::init_client::>(&url)); + Ok(client) +} + +// for tests +pub fn run_worker(scope: &crossbeam::Scope, stop: Arc, socket_path: &str) { + let socket_path = socket_path.to_owned(); + scope.spawn(move || { + let mut worker = nanoipc::Worker::new(&Arc::new(Database::new())); + worker.add_reqrep(&socket_path).unwrap(); + while !stop.load(Ordering::Relaxed) { + worker.poll(); + } + }); +} From 1d5f407a298bf2cdd27730a8558bc9e45d28f3ff Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 13:08:15 +0200 Subject: [PATCH 03/43] database & write que import --- db/src/database.rs | 399 ++++++++++++++++++++++++++++++++++----------- db/src/service.rs | 0 2 files changed, 301 insertions(+), 98 deletions(-) delete mode 100644 db/src/service.rs diff --git a/db/src/database.rs b/db/src/database.rs index 4abc98467..d535f1f56 100644 --- a/db/src/database.rs +++ b/db/src/database.rs @@ -18,15 +18,13 @@ use traits::*; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBIterator, - IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; -use std::collections::BTreeMap; -use std::sync::{RwLock}; +IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; +use std::sync::{RwLock, Arc}; use std::convert::From; use ipc::IpcConfig; -use std::ops::*; use std::mem; use ipc::binary::BinaryConvertError; -use std::collections::VecDeque; +use std::collections::{VecDeque, HashMap, BTreeMap}; impl From for Error { fn from(s: String) -> Error { @@ -34,20 +32,136 @@ impl From for Error { } } +enum WriteCacheEntry { + Remove, + Write(Vec), +} + +pub struct WriteCache { + entries: HashMap, WriteCacheEntry>, + preferred_len: usize, +} + +const FLUSH_BATCH_SIZE: usize = 4096; + +impl WriteCache { + fn new(cache_len: usize) -> WriteCache { + WriteCache { + entries: HashMap::new(), + preferred_len: cache_len, + } + } + + fn write(&mut self, key: Vec, val: Vec) { + self.entries.insert(key, WriteCacheEntry::Write(val)); + } + + fn remove(&mut self, key: Vec) { + self.entries.insert(key, WriteCacheEntry::Remove); + } + + fn get(&self, key: &Vec) -> Option> { + self.entries.get(key).and_then( + |vec_ref| match vec_ref { + &WriteCacheEntry::Write(ref val) => Some(val.clone()), + &WriteCacheEntry::Remove => None + }) + } + + /// WriteCache should be locked for this + fn flush(&mut self, db: &DB, amount: usize) -> Result<(), Error> { + let batch = WriteBatch::new(); + let mut removed_so_far = 0; + while removed_so_far < amount { + if self.entries.len() == 0 { break; } + let removed_key = { + let (key, cache_entry) = self.entries.iter().nth(0) + .expect("if entries.len == 0, we should have break in the loop, still we got here somehow"); + + match *cache_entry { + WriteCacheEntry::Write(ref val) => { + try!(batch.put(&key, val)); + }, + WriteCacheEntry::Remove => { + try!(batch.delete(&key)); + }, + } + key.clone() + }; + + self.entries.remove(&removed_key); + + removed_so_far = removed_so_far + 1; + } + if removed_so_far > 0 { + try!(db.write(batch)); + } + Ok(()) + } + + /// flushes until cache is empty + fn flush_all(&mut self, db: &DB) -> Result<(), Error> { + while !self.is_empty() { try!(self.flush(db, FLUSH_BATCH_SIZE)); } + Ok(()) + } + + fn is_empty(&self) -> bool { + self.entries.is_empty() + } + + fn try_shrink(&mut self, db: &DB) -> Result<(), Error> { + if self.entries.len() > self.preferred_len { + try!(self.flush(db, FLUSH_BATCH_SIZE)); + } + Ok(()) + } +} + pub struct Database { db: RwLock>, - transactions: RwLock>, + /// Iterators - dont't use between threads! iterators: RwLock>, + write_cache: RwLock, } +unsafe impl Send for Database {} +unsafe impl Sync for Database {} + impl Database { pub fn new() -> Database { Database { db: RwLock::new(None), - transactions: RwLock::new(BTreeMap::new()), iterators: RwLock::new(BTreeMap::new()), + write_cache: RwLock::new(WriteCache::new(DEFAULT_CACHE_LEN)), } } + + pub fn flush(&self) -> Result<(), Error> { + let mut cache_lock = self.write_cache.write().unwrap(); + let db_lock = self.db.read().unwrap(); + if db_lock.is_none() { return Ok(()); } + let db = db_lock.as_ref().unwrap(); + + try!(cache_lock.try_shrink(&db)); + Ok(()) + } + + pub fn flush_all(&self) -> Result<(), Error> { + let mut cache_lock = self.write_cache.write().unwrap(); + let db_lock = self.db.read().unwrap(); + if db_lock.is_none() { return Ok(()); } + let db = db_lock.as_ref().expect("we should have exited with Ok(()) on the previous step"); + + try!(cache_lock.flush_all(&db)); + Ok(()) + + } +} + +impl Drop for Database { + fn drop(&mut self) { + self.flush().unwrap(); + } } #[derive(Ipc)] @@ -72,51 +186,64 @@ impl DatabaseService for Database { Ok(()) } + /// Opens database in the specified path with the default config + fn open_default(&self, path: String) -> Result<(), Error> { + self.open(DatabaseConfig::default(), path) + } + fn close(&self) -> Result<(), Error> { + try!(self.flush_all()); + let mut db = self.db.write().unwrap(); if db.is_none() { return Err(Error::IsClosed); } - // TODO: wait for transactions to expire/close here? - if self.transactions.read().unwrap().len() > 0 { return Err(Error::UncommitedTransactions); } - *db = None; Ok(()) } fn put(&self, key: &[u8], value: &[u8]) -> Result<(), Error> { - let db_lock = self.db.read().unwrap(); - let db = try!(db_lock.as_ref().ok_or(Error::IsClosed)); - - try!(db.put(key, value)); + let mut cache_lock = self.write_cache.write().unwrap(); + cache_lock.write(key.to_vec(), value.to_vec()); Ok(()) } fn delete(&self, key: &[u8]) -> Result<(), Error> { - let db_lock = self.db.read().unwrap(); - let db = try!(db_lock.as_ref().ok_or(Error::IsClosed)); - - try!(db.delete(key)); + let mut cache_lock = self.write_cache.write().unwrap(); + cache_lock.remove(key.to_vec()); Ok(()) } - fn write(&self, handle: TransactionHandle) -> Result<(), Error> { - let db_lock = self.db.read().unwrap(); - let db = try!(db_lock.as_ref().ok_or(Error::IsClosed)); + fn write(&self, transaction: DBTransaction) -> Result<(), Error> { + let mut cache_lock = self.write_cache.write().unwrap(); - let mut transactions = self.transactions.write().unwrap(); - let batch = try!( - transactions.remove(&handle).ok_or(Error::TransactionUnknown) - ); - try!(db.write(batch)); + let mut writes = transaction.writes.borrow_mut(); + for kv in writes.drain(..) { + cache_lock.write(kv.key, kv.value); + } + + let mut removes = transaction.removes.borrow_mut(); + for k in removes.drain(..) { + cache_lock.remove(k); + } Ok(()) } fn get(&self, key: &[u8]) -> Result>, Error> { + { + let key_vec = key.to_vec(); + let cache_hit = self.write_cache.read().unwrap().get(&key_vec); + + if cache_hit.is_some() { + return Ok(Some(cache_hit.expect("cache_hit.is_some() = true, still there is none somehow here"))) + } + } let db_lock = self.db.read().unwrap(); let db = try!(db_lock.as_ref().ok_or(Error::IsClosed)); match try!(db.get(key)) { - Some(db_vec) => Ok(Some(db_vec.to_vec())), + Some(db_vec) => { + Ok(Some(db_vec.to_vec())) + }, None => Ok(None), } } @@ -166,37 +293,35 @@ impl DatabaseService for Database { }) } - fn transaction_put(&self, transaction: TransactionHandle, key: &[u8], value: &[u8]) -> Result<(), Error> - { - let mut transactions = self.transactions.write().unwrap(); - let batch = try!( - transactions.get_mut(&transaction).ok_or(Error::TransactionUnknown) - ); - try!(batch.put(&key, &value)); + fn dispose_iter(&self, handle: IteratorHandle) -> Result<(), Error> { + let mut iterators = self.iterators.write().unwrap(); + iterators.remove(&handle); Ok(()) } - - fn transaction_delete(&self, transaction: TransactionHandle, key: &[u8]) -> Result<(), Error> { - let mut transactions = self.transactions.write().unwrap(); - let batch = try!( - transactions.get_mut(&transaction).ok_or(Error::TransactionUnknown) - ); - try!(batch.delete(&key)); - Ok(()) - } - - fn new_transaction(&self) -> TransactionHandle { - let mut transactions = self.transactions.write().unwrap(); - let next_transaction = transactions.keys().last().unwrap_or(&0) + 1; - transactions.insert(next_transaction, WriteBatch::new()); - - next_transaction - } } // TODO : put proper at compile-time impl IpcConfig for Database {} +/// Database iterator +pub struct DatabaseIterator { + client: Arc>, + handle: IteratorHandle, +} + +impl Iterator for DatabaseIterator { + type Item = (Vec, Vec); + + fn next(&mut self) -> Option { + self.client.iter_next(self.handle).and_then(|kv| Some((kv.key, kv.value))) + } +} + +impl Drop for DatabaseIterator { + fn drop(&mut self) { + self.client.dispose_iter(self.handle).unwrap(); + } +} #[cfg(test)] mod test { @@ -215,7 +340,7 @@ mod test { fn can_be_open_empty() { let db = Database::new(); let path = RandomTempPath::create_dir(); - db.open(DatabaseConfig { prefix_size: Some(8) }, path.as_str().to_owned()).unwrap(); + db.open_default(path.as_str().to_owned()).unwrap(); assert!(db.is_empty().is_ok()); } @@ -224,9 +349,10 @@ mod test { fn can_store_key() { let db = Database::new(); let path = RandomTempPath::create_dir(); - db.open(DatabaseConfig { prefix_size: None }, path.as_str().to_owned()).unwrap(); + db.open_default(path.as_str().to_owned()).unwrap(); db.put("xxx".as_bytes(), "1".as_bytes()).unwrap(); + db.flush_all().unwrap(); assert!(!db.is_empty().unwrap()); } @@ -234,15 +360,37 @@ mod test { fn can_retrieve() { let db = Database::new(); let path = RandomTempPath::create_dir(); - db.open(DatabaseConfig { prefix_size: None }, path.as_str().to_owned()).unwrap(); + db.open_default(path.as_str().to_owned()).unwrap(); db.put("xxx".as_bytes(), "1".as_bytes()).unwrap(); db.close().unwrap(); - db.open(DatabaseConfig { prefix_size: None }, path.as_str().to_owned()).unwrap(); + db.open_default(path.as_str().to_owned()).unwrap(); assert_eq!(db.get("xxx".as_bytes()).unwrap().unwrap(), "1".as_bytes().to_vec()); } } +#[cfg(test)] +mod write_cache_tests { + use super::Database; + use traits::*; + use devtools::*; + + #[test] + fn cache_write_flush() { + let db = Database::new(); + let path = RandomTempPath::create_dir(); + + db.open_default(path.as_str().to_owned()).unwrap(); + db.put("100500".as_bytes(), "1".as_bytes()).unwrap(); + db.delete("100500".as_bytes()).unwrap(); + db.flush_all().unwrap(); + + let val = db.get("100500".as_bytes()).unwrap(); + assert!(val.is_none()); + } + +} + #[cfg(test)] mod client_tests { use super::{DatabaseClient, Database}; @@ -251,6 +399,8 @@ mod client_tests { use nanoipc; use std::sync::Arc; use std::sync::atomic::{Ordering, AtomicBool}; + use crossbeam; + use run_worker; fn init_worker(addr: &str) -> nanoipc::Worker { let mut worker = nanoipc::Worker::::new(&Arc::new(Database::new())); @@ -268,7 +418,7 @@ mod client_tests { ::std::thread::spawn(move || { let mut worker = init_worker(url); - while !c_worker_should_exit.load(Ordering::Relaxed) { + while !c_worker_should_exit.load(Ordering::Relaxed) { worker.poll(); c_worker_is_ready.store(true, Ordering::Relaxed); } @@ -295,7 +445,7 @@ mod client_tests { ::std::thread::spawn(move || { let mut worker = init_worker(url); - while !c_worker_should_exit.load(Ordering::Relaxed) { + while !c_worker_should_exit.load(Ordering::Relaxed) { worker.poll(); c_worker_is_ready.store(true, Ordering::Relaxed); } @@ -304,7 +454,7 @@ mod client_tests { while !worker_is_ready.load(Ordering::Relaxed) { } let client = nanoipc::init_duplex_client::>(url).unwrap(); - client.open(DatabaseConfig { prefix_size: Some(8) }, path.as_str().to_owned()).unwrap(); + client.open_default(path.as_str().to_owned()).unwrap(); assert!(client.is_empty().unwrap()); worker_should_exit.store(true, Ordering::Relaxed); } @@ -314,27 +464,16 @@ mod client_tests { let url = "ipc:///tmp/parity-db-ipc-test-30.ipc"; let path = RandomTempPath::create_dir(); - let worker_should_exit = Arc::new(AtomicBool::new(false)); - let worker_is_ready = Arc::new(AtomicBool::new(false)); - let c_worker_should_exit = worker_should_exit.clone(); - let c_worker_is_ready = worker_is_ready.clone(); + crossbeam::scope(move |scope| { + let stop = Arc::new(AtomicBool::new(false)); + run_worker(scope, stop.clone(), url); + let client = nanoipc::init_client::>(url).unwrap(); + client.open_default(path.as_str().to_owned()).unwrap(); + client.put("xxx".as_bytes(), "1".as_bytes()).unwrap(); + client.close().unwrap(); - ::std::thread::spawn(move || { - let mut worker = init_worker(url); - while !c_worker_should_exit.load(Ordering::Relaxed) { - worker.poll(); - c_worker_is_ready.store(true, Ordering::Relaxed); - } + stop.store(true, Ordering::Relaxed); }); - - while !worker_is_ready.load(Ordering::Relaxed) { } - let client = nanoipc::init_duplex_client::>(url).unwrap(); - - client.open(DatabaseConfig { prefix_size: Some(8) }, path.as_str().to_owned()).unwrap(); - client.put("xxx".as_bytes(), "1".as_bytes()).unwrap(); - client.close().unwrap(); - - worker_should_exit.store(true, Ordering::Relaxed); } #[test] @@ -342,29 +481,93 @@ mod client_tests { let url = "ipc:///tmp/parity-db-ipc-test-40.ipc"; let path = RandomTempPath::create_dir(); - let worker_should_exit = Arc::new(AtomicBool::new(false)); - let worker_is_ready = Arc::new(AtomicBool::new(false)); - let c_worker_should_exit = worker_should_exit.clone(); - let c_worker_is_ready = worker_is_ready.clone(); + crossbeam::scope(move |scope| { + let stop = Arc::new(AtomicBool::new(false)); + run_worker(scope, stop.clone(), url); + let client = nanoipc::init_client::>(url).unwrap(); - ::std::thread::spawn(move || { - let mut worker = init_worker(url); - while !c_worker_should_exit.load(Ordering::Relaxed) { - worker.poll(); - c_worker_is_ready.store(true, Ordering::Relaxed); + client.open_default(path.as_str().to_owned()).unwrap(); + client.put("xxx".as_bytes(), "1".as_bytes()).unwrap(); + client.close().unwrap(); + + client.open_default(path.as_str().to_owned()).unwrap(); + assert_eq!(client.get("xxx".as_bytes()).unwrap().unwrap(), "1".as_bytes().to_vec()); + + stop.store(true, Ordering::Relaxed); + }); + } + + #[test] + fn can_read_empty() { + let url = "ipc:///tmp/parity-db-ipc-test-45.ipc"; + let path = RandomTempPath::create_dir(); + + crossbeam::scope(move |scope| { + let stop = Arc::new(AtomicBool::new(false)); + run_worker(scope, stop.clone(), url); + let client = nanoipc::init_client::>(url).unwrap(); + + client.open_default(path.as_str().to_owned()).unwrap(); + assert!(client.get("xxx".as_bytes()).unwrap().is_none()); + + stop.store(true, Ordering::Relaxed); + }); + } + + + #[test] + fn can_commit_client_transaction() { + let url = "ipc:///tmp/parity-db-ipc-test-60.ipc"; + let path = RandomTempPath::create_dir(); + + crossbeam::scope(move |scope| { + let stop = Arc::new(AtomicBool::new(false)); + run_worker(scope, stop.clone(), url); + let client = nanoipc::init_client::>(url).unwrap(); + client.open_default(path.as_str().to_owned()).unwrap(); + + let transaction = DBTransaction::new(); + transaction.put("xxx".as_bytes(), "1".as_bytes()); + client.write(transaction).unwrap(); + + client.close().unwrap(); + + client.open_default(path.as_str().to_owned()).unwrap(); + assert_eq!(client.get("xxx".as_bytes()).unwrap().unwrap(), "1".as_bytes().to_vec()); + + stop.store(true, Ordering::Relaxed); + }); + } + + #[test] + fn key_write_read_ipc() { + let url = "ipc:///tmp/parity-db-ipc-test-70.ipc"; + let path = RandomTempPath::create_dir(); + + crossbeam::scope(|scope| { + let stop = StopGuard::new(); + run_worker(&scope, stop.share(), url); + + let client = nanoipc::init_client::>(url).unwrap(); + + client.open_default(path.as_str().to_owned()).unwrap(); + let mut batch = Vec::new(); + for _ in 0..100 { + batch.push((random_str(256).as_bytes().to_vec(), random_str(256).as_bytes().to_vec())); + batch.push((random_str(256).as_bytes().to_vec(), random_str(2048).as_bytes().to_vec())); + batch.push((random_str(2048).as_bytes().to_vec(), random_str(2048).as_bytes().to_vec())); + batch.push((random_str(2048).as_bytes().to_vec(), random_str(256).as_bytes().to_vec())); + } + + for &(ref k, ref v) in batch.iter() { + client.put(k, v).unwrap(); + } + client.close().unwrap(); + + client.open_default(path.as_str().to_owned()).unwrap(); + for &(ref k, ref v) in batch.iter() { + assert_eq!(v, &client.get(k).unwrap().unwrap()); } }); - - while !worker_is_ready.load(Ordering::Relaxed) { } - let client = nanoipc::init_duplex_client::>(url).unwrap(); - - client.open(DatabaseConfig { prefix_size: Some(8) }, path.as_str().to_owned()).unwrap(); - client.put("xxx".as_bytes(), "1".as_bytes()).unwrap(); - client.close().unwrap(); - - client.open(DatabaseConfig { prefix_size: Some(8) }, path.as_str().to_owned()).unwrap(); - assert_eq!(client.get("xxx".as_bytes()).unwrap().unwrap(), "1".as_bytes().to_vec()); - - worker_should_exit.store(true, Ordering::Relaxed); } } diff --git a/db/src/service.rs b/db/src/service.rs deleted file mode 100644 index e69de29bb..000000000 From a944638b5e51397f6ab439b71fcd93d908c29a84 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 13:17:45 +0200 Subject: [PATCH 04/43] version lock --- db/Cargo.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/db/Cargo.toml b/db/Cargo.toml index 8bd26d1f9..24d0e6fbe 100644 --- a/db/Cargo.toml +++ b/db/Cargo.toml @@ -8,17 +8,19 @@ authors = ["Ethcore "] build = "build.rs" [build-dependencies] -syntex = "*" +syntex = "0.32" ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] -ethcore-util = { path = "../util" } clippy = { version = "0.0.67", optional = true} ethcore-devtools = { path = "../devtools" } ethcore-ipc = { path = "../ipc/rpc" } rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" } semver = "0.2" ethcore-ipc-nano = { path = "../ipc/nano" } +nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" } +crossbeam = "0.2" +ethcore-util = { path = "../util" } [features] dev = ["clippy"] From 1465b0d34c3c18abd12602ec66ac74aa188411c5 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 30 May 2016 13:10:33 +0200 Subject: [PATCH 05/43] refactor Miner to not wrap accounts in an RwLock, and to take a generalized AccountProvider --- miner/src/miner.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/miner/src/miner.rs b/miner/src/miner.rs index fc63aec6c..d356a644a 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -18,14 +18,14 @@ use rayon::prelude::*; use std::sync::atomic::AtomicBool; use util::*; -use util::keys::store::{AccountService, AccountProvider}; +use util::keys::store::AccountProvider; use ethcore::views::{BlockView, HeaderView}; use ethcore::client::{BlockChainClient, BlockID}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::*; use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; use ethcore::transaction::SignedTransaction; -use ethcore::receipt::{Receipt}; +use ethcore::receipt::Receipt; use ethcore::spec::Spec; use ethcore::engine::Engine; use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; @@ -44,7 +44,7 @@ pub struct Miner { extra_data: RwLock, spec: Spec, - accounts: RwLock>>, // TODO: this is horrible since AccountService already contains a single RwLock field. refactor. + accounts: Option>, } impl Default for Miner { @@ -58,7 +58,7 @@ impl Default for Miner { gas_floor_target: RwLock::new(U256::zero()), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), - accounts: RwLock::new(None), + accounts: None, spec: Spec::new_test(), } } @@ -76,13 +76,13 @@ impl Miner { gas_floor_target: RwLock::new(U256::zero()), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), - accounts: RwLock::new(None), + accounts: None, spec: spec, }) } /// Creates new instance of miner - pub fn with_accounts(force_sealing: bool, spec: Spec, accounts: Arc) -> Arc { + pub fn with_accounts(force_sealing: bool, spec: Spec, accounts: Arc) -> Arc { Arc::new(Miner { transaction_queue: Mutex::new(TransactionQueue::new()), force_sealing: force_sealing, @@ -92,7 +92,7 @@ impl Miner { gas_floor_target: RwLock::new(U256::zero()), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), - accounts: RwLock::new(Some(accounts)), + accounts: Some(accounts), spec: spec, }) } @@ -177,9 +177,8 @@ impl Miner { if !block.transactions().is_empty() { trace!(target: "miner", "prepare_sealing: block has transaction - attempting internal seal."); // block with transactions - see if we can seal immediately. - let a = self.accounts.read().unwrap(); - let s = self.engine().generate_seal(block.block(), match *a.deref() { - Some(ref x) => Some(x.deref() as &AccountProvider), + let s = self.engine().generate_seal(block.block(), match self.accounts { + Some(ref x) => Some(&**x), None => None, }); if let Some(seal) = s { From 266b4eedaad7d3a9dda7094bf8a7f91341024141 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 30 May 2016 17:42:42 +0200 Subject: [PATCH 06/43] correct locked_account_secret docs --- util/src/keys/store.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index 3ecabc07c..cf5b2a61e 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -87,7 +87,7 @@ struct AccountUnlock { } /// Basic account management trait -pub trait AccountProvider : Send + Sync { +pub trait AccountProvider: Send + Sync { /// Lists all accounts fn accounts(&self) -> Result, ::std::io::Error>; /// Unlocks account with the password provided @@ -325,7 +325,7 @@ impl SecretStore { ret } - /// Returns secret for unlocked account. + /// Returns secret for locked 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 { From 5cb58c42694cd1350a18dec3c169f0d34ce89447 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 30 May 2016 20:06:10 +0200 Subject: [PATCH 07/43] use Miner in rpc tests, remove chain_harness --- rpc/src/v1/tests/eth.rs | 371 ++++++++++++++++++++++------------------ 1 file changed, 208 insertions(+), 163 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 80a856aca..9b2cb3195 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,11 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; -use ethcore::client::{BlockChainClient, Client, ClientConfig}; -use ethcore::spec::Genesis; +use ethcore::client::{Client, BlockChainClient, ClientConfig}; +use ethcore::spec::{Genesis, Spec}; use ethcore::block::Block; use ethcore::ethereum; -use ethcore::transaction::{Transaction, Action}; -use ethminer::{MinerService, ExternalMiner}; +use ethminer::{Miner, MinerService, ExternalMiner}; use devtools::RandomTempPath; use util::io::IoChannel; use util::hash::Address; @@ -35,135 +34,7 @@ use ethjson::blockchain::BlockChain; use v1::traits::eth::Eth; use v1::impls::EthClient; -use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; - -struct EthTester { - _client: Arc, - _miner: Arc, - accounts: Arc, - handler: IoHandler, -} - -#[test] -fn harness_works() { - let chain: BlockChain = extract_chain!("BlockchainTests/bcUncleTest"); - chain_harness(chain, |_| {}); -} - -#[test] -fn eth_get_balance() { - let chain = extract_chain!("BlockchainTests/bcWalletTest", "wallet2outOf3txs"); - chain_harness(chain, |tester| { - // final account state - let req_latest = r#"{ - "jsonrpc": "2.0", - "method": "eth_getBalance", - "params": ["0xaaaf5374fce5edbc8e2a8697c15331677e6ebaaa", "latest"], - "id": 1 - }"#; - let res_latest = r#"{"jsonrpc":"2.0","result":"0x09","id":1}"#.to_owned(); - assert_eq!(tester.handler.handle_request(req_latest).unwrap(), res_latest); - - // non-existant account - let req_new_acc = r#"{ - "jsonrpc": "2.0", - "method": "eth_getBalance", - "params": ["0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], - "id": 3 - }"#; - - let res_new_acc = r#"{"jsonrpc":"2.0","result":"0x00","id":3}"#.to_owned(); - assert_eq!(tester.handler.handle_request(req_new_acc).unwrap(), res_new_acc); - }); -} - -#[test] -fn eth_block_number() { - let chain = extract_chain!("BlockchainTests/bcRPC_API_Test"); - chain_harness(chain, |tester| { - let req_number = r#"{ - "jsonrpc": "2.0", - "method": "eth_blockNumber", - "params": [], - "id": 1 - }"#; - - let res_number = r#"{"jsonrpc":"2.0","result":"0x20","id":1}"#.to_owned(); - assert_eq!(tester.handler.handle_request(req_number).unwrap(), res_number); - }); -} - -#[cfg(test)] -#[test] -fn eth_transaction_count() { - let chain = extract_chain!("BlockchainTests/bcRPC_API_Test"); - chain_harness(chain, |tester| { - let address = tester.accounts.new_account("123").unwrap(); - let secret = tester.accounts.account_secret(&address).unwrap(); - - let req_before = r#"{ - "jsonrpc": "2.0", - "method": "eth_getTransactionCount", - "params": [""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", "latest"], - "id": 15 - }"#; - - let res_before = r#"{"jsonrpc":"2.0","result":"0x00","id":15}"#; - - assert_eq!(tester.handler.handle_request(&req_before).unwrap(), res_before); - - 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 req_send_trans = r#"{ - "jsonrpc": "2.0", - "method": "eth_sendTransaction", - "params": [{ - "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", - "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", - "gas": "0x76c0", - "gasPrice": "0x9184e72a000", - "value": "0x9184e72a" - }], - "id": 16 - }"#; - - let res_send_trans = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":16}"#; - - // dispatch the transaction. - assert_eq!(tester.handler.handle_request(&req_send_trans).unwrap(), res_send_trans); - - // we have submitted the transaction -- but this shouldn't be reflected in a "latest" query. - let req_after_latest = r#"{ - "jsonrpc": "2.0", - "method": "eth_getTransactionCount", - "params": [""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", "latest"], - "id": 17 - }"#; - - let res_after_latest = r#"{"jsonrpc":"2.0","result":"0x00","id":17}"#; - - assert_eq!(&tester.handler.handle_request(&req_after_latest).unwrap(), res_after_latest); - - // the pending transactions should have been updated. - let req_after_pending = r#"{ - "jsonrpc": "2.0", - "method": "eth_getTransactionCount", - "params": [""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", "pending"], - "id": 18 - }"#; - - let res_after_pending = r#"{"jsonrpc":"2.0","result":"0x01","id":18}"#; - - assert_eq!(&tester.handler.handle_request(&req_after_pending).unwrap(), res_after_pending); - }); -} +use v1::tests::helpers::{TestSyncProvider, Config}; fn account_provider() -> Arc { let mut accounts = HashMap::new(); @@ -179,51 +50,225 @@ fn sync_provider() -> Arc { })) } -fn miner_service() -> Arc { - Arc::new(TestMinerService::default()) +fn miner_service(spec: Spec, accounts: Arc) -> Arc { + Miner::with_accounts(true, spec, accounts) } -// given a blockchain, this harness will create an EthClient wrapping it -// which tests can pass specially crafted requests to. -fn chain_harness(chain: BlockChain, mut cb: F) -> U - where F: FnMut(&EthTester) -> U { +fn make_spec(chain: &BlockChain) -> Spec { let genesis = Genesis::from(chain.genesis()); let mut spec = ethereum::new_frontier_test(); let state = chain.pre_state.clone().into(); spec.set_genesis_state(state); spec.overwrite_genesis_params(genesis); assert!(spec.is_state_root_valid()); + spec +} - let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), spec, dir.as_path(), IoChannel::disconnected()).unwrap(); - let sync_provider = sync_provider(); - let miner_service = miner_service(); - let account_provider = account_provider(); - let external_miner = Arc::new(ExternalMiner::default()); +struct EthTester { + _miner: Arc, + client: Arc, + accounts: Arc, + handler: IoHandler, +} - for b in &chain.blocks_rlp() { - if Block::is_good(&b) { - let _ = client.import_block(b.clone()); - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); +impl EthTester { + fn from_chain(chain: BlockChain) -> Self { + let tester = Self::from_spec_provider(|| make_spec(&chain)); + + for b in &chain.blocks_rlp() { + if Block::is_good(&b) { + let _ = tester.client.import_block(b.clone()); + tester.client.flush_queue(); + tester.client.import_verified_blocks(&IoChannel::disconnected()); + } } + + assert!(tester.client.chain_info().best_block_hash == chain.best_block.into()); + tester } - assert!(client.chain_info().best_block_hash == chain.best_block.into()); + fn from_spec_provider(spec_provider: F) -> Self + where F: Fn() -> Spec { - let eth_client = EthClient::new(&client, &sync_provider, &account_provider, - &miner_service, &external_miner); + let dir = RandomTempPath::new(); + let client = Client::new(ClientConfig::default(), spec_provider(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let sync_provider = sync_provider(); + let account_provider = account_provider(); + let miner_service = miner_service(spec_provider(), account_provider.clone()); + let external_miner = Arc::new(ExternalMiner::default()); - let handler = IoHandler::new(); - let delegate = eth_client.to_delegate(); - handler.add_delegate(delegate); + let eth_client = EthClient::new(&client, &sync_provider, &account_provider, + &miner_service, &external_miner); - let tester = EthTester { - _miner: miner_service, - _client: client, - accounts: account_provider, - handler: handler, - }; + let handler = IoHandler::new(); + let delegate = eth_client.to_delegate(); + handler.add_delegate(delegate); - cb(&tester) + EthTester { + _miner: miner_service, + client: client, + accounts: account_provider, + handler: handler, + } + } } + +#[test] +fn harness_works() { + let chain: BlockChain = extract_chain!("BlockchainTests/bcUncleTest"); + let _ = EthTester::from_chain(chain); +} + +#[test] +fn eth_get_balance() { + let chain = extract_chain!("BlockchainTests/bcWalletTest", "wallet2outOf3txs"); + let tester = EthTester::from_chain(chain); + // final account state + let req_latest = r#"{ + "jsonrpc": "2.0", + "method": "eth_getBalance", + "params": ["0xaaaf5374fce5edbc8e2a8697c15331677e6ebaaa", "latest"], + "id": 1 + }"#; + let res_latest = r#"{"jsonrpc":"2.0","result":"0x09","id":1}"#.to_owned(); + assert_eq!(tester.handler.handle_request(req_latest).unwrap(), res_latest); + + // non-existant account + let req_new_acc = r#"{ + "jsonrpc": "2.0", + "method": "eth_getBalance", + "params": ["0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], + "id": 3 + }"#; + + let res_new_acc = r#"{"jsonrpc":"2.0","result":"0x00","id":3}"#.to_owned(); + assert_eq!(tester.handler.handle_request(req_new_acc).unwrap(), res_new_acc); +} + +#[test] +fn eth_block_number() { + let chain = extract_chain!("BlockchainTests/bcRPC_API_Test"); + let tester = EthTester::from_chain(chain); + let req_number = r#"{ + "jsonrpc": "2.0", + "method": "eth_blockNumber", + "params": [], + "id": 1 + }"#; + + let res_number = r#"{"jsonrpc":"2.0","result":"0x20","id":1}"#.to_owned(); + assert_eq!(tester.handler.handle_request(req_number).unwrap(), res_number); +} + +// a frontier-like test with an expanded gas limit and balance on known account. +const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{ + "name": "Frontier (Test)", + "engine": { + "Ethash": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "frontierCompatibilityModeLimit": "0xffffffffffffffff" + } + } + }, + "params": { + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x50000", + "networkID" : "0x1" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x50000" + }, + "accounts": { + "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 } } } }, + "faa34835af5c2ea724333018a515fbb7d5bc0b33": { "balance": "10000000000000", "nonce": "0" } + } +} +"#; + +#[cfg(test)] +#[test] +fn eth_transaction_count() { + use util::crypto::Secret; + + let address = Address::from_str("faa34835af5c2ea724333018a515fbb7d5bc0b33").unwrap(); + let secret = Secret::from_str("8a283037bb19c4fed7b1c569e40c7dcff366165eb869110a1b11532963eb9cb2").unwrap(); + + let tester = EthTester::from_spec_provider(|| Spec::load(TRANSACTION_COUNT_SPEC)); + tester.accounts.accounts.write().unwrap().insert(address, TestAccount { + unlocked: false, + password: "123".into(), + secret: secret + }); + + let req_before = r#"{ + "jsonrpc": "2.0", + "method": "eth_getTransactionCount", + "params": [""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", "latest"], + "id": 15 + }"#; + + let res_before = r#"{"jsonrpc":"2.0","result":"0x00","id":15}"#; + + assert_eq!(tester.handler.handle_request(&req_before).unwrap(), res_before); + + let req_send_trans = r#"{ + "jsonrpc": "2.0", + "method": "eth_sendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x30000", + "gasPrice": "0x01", + "value": "0x9184e72a" + }], + "id": 16 + }"#; + + // dispatch the transaction. + tester.handler.handle_request(&req_send_trans).unwrap(); + + // we have submitted the transaction -- but this shouldn't be reflected in a "latest" query. + let req_after_latest = r#"{ + "jsonrpc": "2.0", + "method": "eth_getTransactionCount", + "params": [""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", "latest"], + "id": 17 + }"#; + + let res_after_latest = r#"{"jsonrpc":"2.0","result":"0x00","id":17}"#; + + assert_eq!(&tester.handler.handle_request(&req_after_latest).unwrap(), res_after_latest); + + // the pending transactions should have been updated. + let req_after_pending = r#"{ + "jsonrpc": "2.0", + "method": "eth_getTransactionCount", + "params": [""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", "pending"], + "id": 18 + }"#; + + let res_after_pending = r#"{"jsonrpc":"2.0","result":"0x01","id":18}"#; + + assert_eq!(&tester.handler.handle_request(&req_after_pending).unwrap(), res_after_pending); +} \ No newline at end of file From b729a381f8f926786dbe4d6a92bd50c6566eb0a1 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 16:29:53 +0200 Subject: [PATCH 08/43] rewrite map macros not to use an intermediate allocation --- util/src/common.rs | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/util/src/common.rs b/util/src/common.rs index a4ba41f82..7ed660f29 100644 --- a/util/src/common.rs +++ b/util/src/common.rs @@ -26,30 +26,46 @@ pub use sha3::*; #[macro_export] macro_rules! hash_map { - ( $( $x:expr => $y:expr ),* ) => { - vec![ $( ($x, $y) ),* ].into_iter().collect::>() - } + ( $( $x:expr => $y:expr ),* ) => {{ + let mut x = HashMap::new(); + $( + x.insert($x, $y); + )* + x + }} } #[macro_export] macro_rules! hash_mapx { - ( $( $x:expr => $y:expr ),* ) => { - vec![ $( ( From::from($x), From::from($y) ) ),* ].into_iter().collect::>() - } + ( $( $x:expr => $y:expr ),* ) => {{ + let mut x = HashMap::new(); + $( + x.insert($x.into(), $y.into()); + )* + x + }} } #[macro_export] macro_rules! map { - ( $( $x:expr => $y:expr ),* ) => { - vec![ $( ($x, $y) ),* ].into_iter().collect::>() - } + ( $( $x:expr => $y:expr ),* ) => {{ + let mut x = BTreeMap::new(); + $( + x.insert($x, $y); + )* + x + }} } #[macro_export] macro_rules! mapx { - ( $( $x:expr => $y:expr ),* ) => { - vec![ $( ( From::from($x), From::from($y) ) ),* ].into_iter().collect::>() - } + ( $( $x:expr => $y:expr ),* ) => {{ + let mut x = BTreeMap::new(); + $( + x.insert($x.into(), $y.into()); + )* + x + }} } #[macro_export] From 3788b3a149614a3d61cb72d0a3fb41e3f6221c0a Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 16:40:48 +0200 Subject: [PATCH 09/43] expunge x! from util --- util/src/hash.rs | 2 +- util/src/json_aid.rs | 2 +- util/src/keys/store.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/util/src/hash.rs b/util/src/hash.rs index ba96f812c..1a16cefa4 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -718,7 +718,7 @@ mod tests { #[test] fn from_and_to_u256() { - let u: U256 = x!(0x123456789abcdef0u64); + let u: U256 = 0x123456789abcdef0u64.into(); let h = H256::from(u); assert_eq!(H256::from(u), H256::from("000000000000000000000000000000000000000000000000123456789abcdef0")); let h_ref = H256::from(&u); diff --git a/util/src/json_aid.rs b/util/src/json_aid.rs index 6aed7f09c..7bf940b99 100644 --- a/util/src/json_aid.rs +++ b/util/src/json_aid.rs @@ -48,7 +48,7 @@ impl FromJson for Bytes { impl FromJson for BTreeMap { fn from_json(json: &Json) -> Self { match *json { - Json::Object(ref o) => o.iter().map(|(key, value)| (x!(&u256_from_str(key)), x!(&U256::from_json(value)))).collect(), + Json::Object(ref o) => o.iter().map(|(key, value)| (u256_from_str(key).into(), U256::from_json(value).into())).collect(), _ => BTreeMap::new(), } } diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index 3ecabc07c..296f7ad37 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -554,7 +554,7 @@ mod tests { H256::from_str("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2").unwrap(), 262144, 32)); - key_file.account = Some(x!(i as u64)); + key_file.account = Some((i as u64).into()); result.push(key_file.id.clone()); write_sstore.import_key(key_file).unwrap(); } From 0cd864429202cdf50c8f2f51538c4bcf2a079d49 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 16:41:15 +0200 Subject: [PATCH 10/43] split interfaces --- ethcore/src/client/client.rs | 146 +++++++++++++++--------------- ethcore/src/client/mod.rs | 20 ++-- ethcore/src/client/test_client.rs | 21 +++-- miner/src/lib.rs | 24 ++--- miner/src/miner.rs | 34 +++---- 5 files changed, 126 insertions(+), 119 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index ab1c21af1..8f6d607ba 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -37,7 +37,7 @@ use filter::Filter; use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, TraceFilter}; +use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, ExtendedBlockChainClient, TraceFilter}; use client::Error as ClientError; use env_info::EnvInfo; use executive::{Executive, Executed, TransactOptions, contract_address}; @@ -448,81 +448,10 @@ impl BlockChainClient for Client where V: Verifier { Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options) } - // TODO [todr] Should be moved to miner crate eventually. - fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result { - block.try_seal(self.engine.deref().deref(), seal) - } - fn vm_factory(&self) -> &EvmFactory { &self.vm_factory } - // 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, HashSet) { - let engine = self.engine.deref().deref(); - let h = self.chain.best_block_hash(); - let mut invalid_transactions = HashSet::new(); - - let mut b = OpenBlock::new( - engine, - &self.vm_factory, - false, // TODO: this will need to be parameterised once we want to do immediate mining insertion. - self.state_db.lock().unwrap().boxed_clone(), - match self.chain.block_header(&h) { Some(ref x) => x, None => { return (None, invalid_transactions) } }, - self.build_last_hashes(h.clone()), - author, - gas_floor_target, - extra_data, - ); - - // Add uncles - self.chain - .find_uncle_headers(&h, engine.maximum_uncle_age()) - .unwrap() - .into_iter() - .take(engine.maximum_uncle_count()) - .foreach(|h| { - b.push_uncle(h).unwrap(); - }); - - // Add transactions - let block_number = b.block().header().number(); - let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas); - - for tx in transactions { - // 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); - }, - _ => {} - } - } - - // And close - let b = b.close(); - trace!(target: "miner", "Sealing: number={}, hash={}, diff={}", - b.block().header().number(), - b.hash(), - b.block().header().difficulty() - ); - (Some(b), invalid_transactions) - } - fn block_header(&self, id: BlockID) -> Option { Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec())) } @@ -776,6 +705,79 @@ impl BlockChainClient for Client where V: Verifier { } } +impl ExtendedBlockChainClient 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, HashSet) { + let engine = self.engine.deref().deref(); + let h = self.chain.best_block_hash(); + let mut invalid_transactions = HashSet::new(); + + let mut b = OpenBlock::new( + engine, + &self.vm_factory, + false, // TODO: this will need to be parameterised once we want to do immediate mining insertion. + self.state_db.lock().unwrap().boxed_clone(), + match self.chain.block_header(&h) { Some(ref x) => x, None => { return (None, invalid_transactions) } }, + self.build_last_hashes(h.clone()), + author, + gas_floor_target, + extra_data, + ); + + // Add uncles + self.chain + .find_uncle_headers(&h, engine.maximum_uncle_age()) + .unwrap() + .into_iter() + .take(engine.maximum_uncle_count()) + .foreach(|h| { + b.push_uncle(h).unwrap(); + }); + + // Add transactions + let block_number = b.block().header().number(); + let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas); + + for tx in transactions { + // 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); + }, + _ => {} + } + } + + // And close + let b = b.close(); + trace!(target: "miner", "Sealing: number={}, hash={}, diff={}", + b.block().header().number(), + b.hash(), + b.block().header().difficulty() + ); + (Some(b), invalid_transactions) + } + + // TODO [todr] Should be moved to miner crate eventually. + fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result { + block.try_seal(self.engine.deref().deref(), seal) + } +} + impl MayPanic for Client { fn on_panic(&self, closure: F) where F: OnPanicListener { self.panic_handler.on_panic(closure); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 8e0a7b2dd..5537f8e66 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -154,15 +154,6 @@ pub trait BlockChainClient : Sync + Send { /// Returns logs matching given filter. fn logs(&self, filter: Filter) -> Vec; - // 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, 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. - fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; - /// Makes a non-persistent transaction call. fn call(&self, t: &SignedTransaction) -> Result; @@ -185,3 +176,14 @@ pub trait BlockChainClient : Sync + Send { fn last_hashes(&self) -> LastHashes; } +/// Extended client interface used for mining +pub trait ExtendedBlockChainClient : BlockChainClient { + // 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. + fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; + + // 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, HashSet); +} diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index de2973029..5c093b720 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder}; use util::*; use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; use blockchain::TreeRoute; -use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; +use client::{BlockChainClient, ExtendedBlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; use header::{Header as BlockHeader, BlockNumber}; use filter::Filter; use log_entry::LocalizedLogEntry; @@ -232,6 +232,17 @@ impl TestBlockChainClient { } } +impl ExtendedBlockChainClient for TestBlockChainClient { + fn try_seal(&self, block: LockedBlock, _seal: Vec) -> Result { + Err(block) + } + + + fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> (Option, HashSet) { + (None, HashSet::new()) + } +} + impl BlockChainClient for TestBlockChainClient { fn call(&self, _t: &SignedTransaction) -> Result { Ok(self.execution_result.read().unwrap().clone().unwrap()) @@ -296,14 +307,6 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec) -> (Option, HashSet) { - (None, HashSet::new()) - } - - fn try_seal(&self, block: LockedBlock, _seal: Vec) -> Result { - Err(block) - } - fn block_header(&self, id: BlockID) -> Option { self.block_hash(id).and_then(|hash| self.blocks.read().unwrap().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec())) } diff --git a/miner/src/lib.rs b/miner/src/lib.rs index a1780efff..db3315376 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -62,7 +62,7 @@ pub use external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; use util::{H256, U256, Address, Bytes}; -use ethcore::client::{BlockChainClient, Executed}; +use ethcore::client::{ExtendedBlockChainClient, Executed}; use ethcore::block::ClosedBlock; use ethcore::receipt::Receipt; use ethcore::error::{Error, ExecutionError}; @@ -110,7 +110,7 @@ pub trait MinerService : Send + Sync { where T: Fn(&Address) -> AccountDetails, Self: Sized; /// Imports own (node owner) transaction to queue. - fn import_own_transaction(&self, chain: &BlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails, Self: Sized; @@ -118,20 +118,20 @@ pub trait MinerService : Send + Sync { fn pending_transactions_hashes(&self) -> Vec; /// Removes all transactions from the queue and restart mining operation. - fn clear_and_reset(&self, chain: &BlockChainClient); + fn clear_and_reset(&self, chain: &ExtendedBlockChainClient); /// Called when blocks are imported to chain, updates transactions queue. - fn chain_new_blocks(&self, chain: &BlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); + fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); /// New chain head event. Restart mining operation. - fn update_sealing(&self, chain: &BlockChainClient); + fn update_sealing(&self, chain: &ExtendedBlockChainClient); /// 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>; + fn submit_seal(&self, chain: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; /// Get the sealing work package and if `Some`, apply some transform. - fn map_sealing_work(&self, chain: &BlockChainClient, f: F) -> Option + fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T, Self: Sized; /// Query pending transactions for hash. @@ -156,19 +156,19 @@ pub trait MinerService : Send + Sync { fn sensible_gas_limit(&self) -> U256 { x!(21000) } /// Latest account balance in pending state. - fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256; + fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; /// Call into contract code using pending state. - fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result; + fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result; /// Get storage value in pending state. - fn storage_at(&self, chain: &BlockChainClient, address: &Address, position: &H256) -> H256; + fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256; /// Get account nonce in pending state. - fn nonce(&self, chain: &BlockChainClient, address: &Address) -> U256; + fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; /// Get contract code in pending state. - fn code(&self, chain: &BlockChainClient, address: &Address) -> Option; + fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option; } /// Mining status diff --git a/miner/src/miner.rs b/miner/src/miner.rs index fc63aec6c..7438e7e9b 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -20,7 +20,7 @@ use std::sync::atomic::AtomicBool; use util::*; use util::keys::store::{AccountService, AccountProvider}; use ethcore::views::{BlockView, HeaderView}; -use ethcore::client::{BlockChainClient, BlockID}; +use ethcore::client::{ExtendedBlockChainClient, BlockID}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::*; use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; @@ -104,7 +104,7 @@ impl Miner { /// Prepares new block for sealing including top transactions from queue. #[cfg_attr(feature="dev", allow(match_same_arms))] #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] - fn prepare_sealing(&self, chain: &BlockChainClient) { + fn prepare_sealing(&self, chain: &ExtendedBlockChainClient) { trace!(target: "miner", "prepare_sealing: entering"); let transactions = self.transaction_queue.lock().unwrap().top_transactions(); let mut sealing_work = self.sealing_work.lock().unwrap(); @@ -206,14 +206,14 @@ impl Miner { trace!(target: "miner", "prepare_sealing: leaving (last={:?})", sealing_work.peek_last_ref().map(|b| b.block().fields().header.hash())); } - fn update_gas_limit(&self, chain: &BlockChainClient) { + fn update_gas_limit(&self, chain: &ExtendedBlockChainClient) { 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); } /// Returns true if we had to prepare new pending block - fn enable_and_prepare_sealing(&self, chain: &BlockChainClient) -> bool { + fn enable_and_prepare_sealing(&self, chain: &ExtendedBlockChainClient) -> bool { trace!(target: "miner", "enable_and_prepare_sealing: entering"); let have_work = self.sealing_work.lock().unwrap().peek_last_ref().is_some(); trace!(target: "miner", "enable_and_prepare_sealing: have_work={}", have_work); @@ -237,7 +237,7 @@ const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; impl MinerService for Miner { - fn clear_and_reset(&self, chain: &BlockChainClient) { + fn clear_and_reset(&self, chain: &ExtendedBlockChainClient) { self.transaction_queue.lock().unwrap().clear(); self.update_sealing(chain); } @@ -252,7 +252,7 @@ impl MinerService for Miner { } } - fn call(&self, chain: &BlockChainClient, t: &SignedTransaction) -> Result { + fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result { let sealing_work = self.sealing_work.lock().unwrap(); match sealing_work.peek_last_ref() { Some(work) => { @@ -288,7 +288,7 @@ impl MinerService for Miner { } } - fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256 { + fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_balance(address), @@ -296,7 +296,7 @@ impl MinerService for Miner { ) } - fn storage_at(&self, chain: &BlockChainClient, address: &Address, position: &H256) -> H256 { + fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_storage_at(address, position), @@ -304,12 +304,12 @@ impl MinerService for Miner { ) } - fn nonce(&self, chain: &BlockChainClient, address: &Address) -> U256 { + fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.latest_nonce(address), |b| b.block().fields().state.nonce(address)) } - fn code(&self, chain: &BlockChainClient, address: &Address) -> Option { + fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.code(address), |b| b.block().fields().state.code(address)) } @@ -376,7 +376,7 @@ impl MinerService for Miner { .collect() } - fn import_own_transaction(&self, chain: &BlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails { let hash = transaction.hash(); @@ -470,7 +470,7 @@ impl MinerService for Miner { self.transaction_queue.lock().unwrap().last_nonce(address) } - fn update_sealing(&self, chain: &BlockChainClient) { + fn update_sealing(&self, chain: &ExtendedBlockChainClient) { if self.sealing_enabled.load(atomic::Ordering::Relaxed) { let current_no = chain.chain_info().best_block_number; let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions(); @@ -490,7 +490,7 @@ impl MinerService for Miner { } } - fn map_sealing_work(&self, chain: &BlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { trace!(target: "miner", "map_sealing_work: entering"); self.enable_and_prepare_sealing(chain); trace!(target: "miner", "map_sealing_work: sealing prepared"); @@ -500,7 +500,7 @@ impl MinerService for Miner { ret.map(f) } - fn submit_seal(&self, chain: &BlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { + fn submit_seal(&self, chain: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { 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(_) => { @@ -523,8 +523,8 @@ impl MinerService for Miner { } } - fn chain_new_blocks(&self, chain: &BlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - fn fetch_transactions(chain: &BlockChainClient, hash: &H256) -> Vec { + fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { + fn fetch_transactions(chain: &ExtendedBlockChainClient, hash: &H256) -> Vec { let block = chain .block(BlockID::Hash(*hash)) // Client should send message after commit to db and inserting to chain. @@ -591,7 +591,7 @@ mod tests { use ethcore::client::{TestBlockChainClient, EachBlockWith}; use ethcore::block::*; - // TODO [ToDr] To uncomment when TestBlockChainClient can actually return a ClosedBlock. + // TODO [ToDr] To uncomment` when TestBlockChainClient can actually return a ClosedBlock. #[ignore] #[test] fn should_prepare_block_to_seal() { From ff7c755930c35205e80b2a5f48ff3c731d838c83 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 16:59:01 +0200 Subject: [PATCH 11/43] mostly purge x! from ethcore --- ethcore/src/account.rs | 18 +- ethcore/src/account_db.rs | 4 +- ethcore/src/basic_authority.rs | 14 +- ethcore/src/block.rs | 8 +- ethcore/src/block_queue.rs | 6 +- ethcore/src/client/client.rs | 4 +- ethcore/src/env_info.rs | 14 +- ethcore/src/ethereum/ethash.rs | 28 +-- ethcore/src/executive.rs | 20 +- ethcore/src/externalities.rs | 8 +- ethcore/src/pod_account.rs | 38 +-- ethcore/src/state.rs | 414 ++++++++++++++++----------------- ethcore/src/substate.rs | 6 +- ethcore/src/tests/client.rs | 2 +- ethcore/src/tests/helpers.rs | 6 +- ethcore/src/types/receipt.rs | 6 +- 16 files changed, 298 insertions(+), 298 deletions(-) diff --git a/ethcore/src/account.rs b/ethcore/src/account.rs index 66cceda42..7ba213393 100644 --- a/ethcore/src/account.rs +++ b/ethcore/src/account.rs @@ -261,7 +261,7 @@ mod tests { let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { - let mut a = Account::new_contract(x!(69), x!(0)); + let mut a = Account::new_contract(69.into(), 0.into()); a.set_storage(H256::from(&U256::from(0x00u64)), H256::from(&U256::from(0x1234u64))); a.commit_storage(&mut db); a.init_code(vec![]); @@ -281,7 +281,7 @@ mod tests { let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { - let mut a = Account::new_contract(x!(69), x!(0)); + let mut a = Account::new_contract(69.into(), 0.into()); a.init_code(vec![0x55, 0x44, 0xffu8]); a.commit_code(&mut db); a.rlp() @@ -296,10 +296,10 @@ mod tests { #[test] fn commit_storage() { - let mut a = Account::new_contract(x!(69), x!(0)); + let mut a = Account::new_contract(69.into(), 0.into()); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); - a.set_storage(x!(0), x!(0x1234)); + a.set_storage(0.into(), 0x1234.into()); assert_eq!(a.storage_root(), None); a.commit_storage(&mut db); assert_eq!(a.storage_root().unwrap().hex(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2"); @@ -307,21 +307,21 @@ mod tests { #[test] fn commit_remove_commit_storage() { - let mut a = Account::new_contract(x!(69), x!(0)); + let mut a = Account::new_contract(69.into(), 0.into()); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); - a.set_storage(x!(0), x!(0x1234)); + a.set_storage(0.into(), 0x1234.into()); a.commit_storage(&mut db); - a.set_storage(x!(1), x!(0x1234)); + a.set_storage(1.into(), 0x1234.into()); a.commit_storage(&mut db); - a.set_storage(x!(1), x!(0)); + a.set_storage(1.into(), 0.into()); a.commit_storage(&mut db); assert_eq!(a.storage_root().unwrap().hex(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2"); } #[test] fn commit_code() { - let mut a = Account::new_contract(x!(69), x!(0)); + let mut a = Account::new_contract(69.into(), 0.into()); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.init_code(vec![0x55, 0x44, 0xffu8]); diff --git a/ethcore/src/account_db.rs b/ethcore/src/account_db.rs index f95ec53a1..c21ea2993 100644 --- a/ethcore/src/account_db.rs +++ b/ethcore/src/account_db.rs @@ -20,7 +20,7 @@ impl<'db> AccountDB<'db> { pub fn new(db: &'db HashDB, address: &Address) -> AccountDB<'db> { AccountDB { db: db, - address: x!(address), + address: address.into(), } } } @@ -67,7 +67,7 @@ impl<'db> AccountDBMut<'db> { pub fn new(db: &'db mut HashDB, address: &Address) -> AccountDBMut<'db> { AccountDBMut { db: db, - address: x!(address), + address: address.into(), } } diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index fec23cf54..b4a938642 100644 --- a/ethcore/src/basic_authority.rs +++ b/ethcore/src/basic_authority.rs @@ -86,9 +86,9 @@ impl Engine for BasicAuthority { let gas_limit = parent.gas_limit; let bound_divisor = self.our_params.gas_limit_bound_divisor; if gas_limit < gas_floor_target { - min(gas_floor_target, gas_limit + gas_limit / bound_divisor - x!(1)) + min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) } else { - max(gas_floor_target, gas_limit - gas_limit / bound_divisor + x!(1)) + max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) } }; header.note_dirty(); @@ -211,12 +211,12 @@ mod tests { let engine = new_test_authority().engine; let schedule = engine.schedule(&EnvInfo { number: 10000000, - author: x!(0), + author: 0.into(), timestamp: 0, - difficulty: x!(0), + difficulty: 0.into(), last_hashes: vec![], - gas_used: x!(0), - gas_limit: x!(0) + gas_used: 0.into(), + gas_limit: 0.into() }); assert!(schedule.stack_limit > 0); @@ -278,7 +278,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr.clone(), x!(3141562), vec![]); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr.clone(), 3141562.into(), vec![]); let b = b.close_and_lock(); let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap(); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 90d4eec2d..0b75f5a7e 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -469,7 +469,7 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head } } - let mut b = OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone()); + let mut b = OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, header.author().clone(), 3141562.into(), header.extra_data().clone()); b.set_difficulty(*header.difficulty()); b.set_gas_limit(*header.gas_limit()); b.set_timestamp(header.timestamp()); @@ -514,7 +514,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]); let b = b.close_and_lock(); let _ = b.seal(engine.deref(), vec![]); } @@ -530,7 +530,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close_and_lock().seal(engine.deref(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]).close_and_lock().seal(engine.deref(), vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); @@ -557,7 +557,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]); + let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]); let mut uncle1_header = Header::new(); uncle1_header.extra_data = b"uncle1".to_vec(); let mut uncle2_header = Header::new(); diff --git a/ethcore/src/block_queue.rs b/ethcore/src/block_queue.rs index bf11f5f1f..5e89641c0 100644 --- a/ethcore/src/block_queue.rs +++ b/ethcore/src/block_queue.rs @@ -311,17 +311,17 @@ impl BlockQueue { let h = header.hash(); { if self.processing.read().unwrap().contains(&h) { - return Err(x!(ImportError::AlreadyQueued)); + return Err(ImportError::AlreadyQueued.into()); } let mut bad = self.verification.bad.lock().unwrap(); if bad.contains(&h) { - return Err(x!(ImportError::KnownBad)); + return Err(ImportError::KnownBad.into()); } if bad.contains(&header.parent_hash) { bad.insert(h.clone()); - return Err(x!(ImportError::KnownBad)); + return Err(ImportError::KnownBad.into()); } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index ab1c21af1..8fb0de9eb 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -655,10 +655,10 @@ impl BlockChainClient for Client where V: Verifier { { let header = BlockView::new(&bytes).header_view(); if self.chain.is_known(&header.sha3()) { - return Err(x!(ImportError::AlreadyInChain)); + return Err(ImportError::AlreadyInChain.into()); } if self.block_status(BlockID::Hash(header.parent_hash())) == BlockStatus::Unknown { - return Err(x!(BlockError::UnknownParent(header.parent_hash()))); + return Err(BlockError::UnknownParent(header.parent_hash()).into()); } } self.block_queue.import_block(bytes) diff --git a/ethcore/src/env_info.rs b/ethcore/src/env_info.rs index 18b8af856..e6d15cee6 100644 --- a/ethcore/src/env_info.rs +++ b/ethcore/src/env_info.rs @@ -47,10 +47,10 @@ impl Default for EnvInfo { number: 0, author: Address::new(), timestamp: 0, - difficulty: x!(0), - gas_limit: x!(0), + difficulty: 0.into(), + gas_limit: 0.into(), last_hashes: vec![], - gas_used: x!(0), + gas_used: 0.into(), } } } @@ -92,15 +92,15 @@ mod tests { assert_eq!(env_info.number, 1112339); assert_eq!(env_info.author, Address::from_str("000000f00000000f000000000000f00000000f00").unwrap()); - assert_eq!(env_info.gas_limit, x!(40000)); - assert_eq!(env_info.difficulty, x!(50000)); - assert_eq!(env_info.gas_used, x!(0)); + assert_eq!(env_info.gas_limit, 40000.into()); + assert_eq!(env_info.difficulty, 50000.into()); + assert_eq!(env_info.gas_used, 0.into()); } #[test] fn it_can_be_created_as_default() { let default_env_info = EnvInfo::default(); - assert_eq!(default_env_info.difficulty, x!(0)); + assert_eq!(default_env_info.difficulty, 0.into()); } } diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index cb06959d0..1dadb8a65 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -111,9 +111,9 @@ impl Engine for Ethash { let gas_limit = parent.gas_limit; let bound_divisor = self.ethash_params.gas_limit_bound_divisor; if gas_limit < gas_floor_target { - min(gas_floor_target, gas_limit + gas_limit / bound_divisor - x!(1)) + min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) } else { - max(gas_floor_target, gas_limit - gas_limit / bound_divisor + x!(1) + (header.gas_used * x!(6) / x!(5)) / bound_divisor) + max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into() + (header.gas_used * 6.into() / 5.into()) / bound_divisor) } }; header.note_dirty(); @@ -255,12 +255,12 @@ impl Ethash { /// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`. pub fn boundary_to_difficulty(boundary: &H256) -> U256 { - U256::from((U512::one() << 256) / x!(U256::from(boundary.as_slice()))) + U256::from((U512::one() << 256) / U256::from(boundary.as_slice()).into()) } /// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`. pub fn difficulty_to_boundary(difficulty: &U256) -> H256 { - x!(U256::from((U512::one() << 256) / x!(difficulty))) + U256::from((U512::one() << 256) / difficulty.into()).into() } fn to_ethash(hash: H256) -> EH256 { @@ -308,7 +308,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]); let b = b.close(); assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap()); } @@ -323,7 +323,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); + let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]); let mut uncle = Header::new(); let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106"); uncle.author = uncle_author.clone(); @@ -346,24 +346,24 @@ mod tests { let engine = new_morden().engine; let schedule = engine.schedule(&EnvInfo { number: 10000000, - author: x!(0), + author: 0.into(), timestamp: 0, - difficulty: x!(0), + difficulty: 0.into(), last_hashes: vec![], - gas_used: x!(0), - gas_limit: x!(0) + gas_used: 0.into(), + gas_limit: 0.into() }); assert!(schedule.stack_limit > 0); let schedule = engine.schedule(&EnvInfo { number: 100, - author: x!(0), + author: 0.into(), timestamp: 0, - difficulty: x!(0), + difficulty: 0.into(), last_hashes: vec![], - gas_used: x!(0), - gas_limit: x!(0) + gas_used: 0.into(), + gas_limit: 0.into() }); assert!(!schedule.have_delegate_call); diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 320a89cb8..291b4dba2 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -361,7 +361,7 @@ impl<'a> Executive<'a> { let refunds_bound = sstore_refunds + suicide_refunds; // real ammount to refund - let gas_left_prerefund = match result { Ok(x) => x, _ => x!(0) }; + let gas_left_prerefund = match result { Ok(x) => x, _ => 0.into() }; let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) / U256::from(2)); let gas_left = gas_left_prerefund + refunded; @@ -588,10 +588,10 @@ mod tests { let expected_trace = vec![ Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("cd1722f3947def4cf144679da39c4c32bdc35681"), - to: x!("b010143a42d5980c7e5ef0e4a4416dc098a4fed3"), - value: x!(100), - gas: x!(100000), + from: "cd1722f3947def4cf144679da39c4c32bdc35681".into(), + to: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + value: 100.into(), + gas: 100000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -601,9 +601,9 @@ mod tests { subs: vec![Trace { depth: 1, action: trace::Action::Create(trace::Create { - from: x!("b010143a42d5980c7e5ef0e4a4416dc098a4fed3"), - value: x!(23), - gas: x!(67979), + from: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + value: 23.into(), + gas: 67979.into(), init: vec![96, 16, 128, 96, 12, 96, 0, 57, 96, 0, 243, 0, 96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53, 85] }), result: trace::Res::Create(trace::CreateResult { @@ -642,7 +642,7 @@ mod tests { params.origin = sender.clone(); params.gas = U256::from(100_000); params.code = Some(code.clone()); - params.value = ActionValue::Transfer(x!(100)); + params.value = ActionValue::Transfer(100.into()); let mut state_result = get_temp_state(); let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from(100)); @@ -660,7 +660,7 @@ mod tests { depth: 0, action: trace::Action::Create(trace::Create { from: params.sender, - value: x!(100), + value: 100.into(), gas: params.gas, init: vec![96, 16, 128, 96, 12, 96, 0, 57, 96, 0, 243, 0, 96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53, 85], }), diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index c936ac207..99d2eed72 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -311,12 +311,12 @@ mod tests { fn get_test_env_info() -> EnvInfo { EnvInfo { number: 100, - author: x!(0), + author: 0.into(), timestamp: 0, - difficulty: x!(0), + difficulty: 0.into(), last_hashes: vec![], - gas_used: x!(0), - gas_limit: x!(0) + gas_used: 0.into(), + gas_limit: 0.into() } } diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 27ddc8a97..6f3949db3 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -114,11 +114,11 @@ mod test { #[test] fn existence() { - let a = PodAccount{balance: x!(69), nonce: x!(0), code: vec![], storage: map![]}; + let a = PodAccount{balance: 69.into(), nonce: 0.into(), code: vec![], storage: map![]}; assert_eq!(AccountDiff::diff_pod(Some(&a), Some(&a)), None); assert_eq!(AccountDiff::diff_pod(None, Some(&a)), Some(AccountDiff{ - balance: Diff::Born(x!(69)), - nonce: Diff::Born(x!(0)), + balance: Diff::Born(69.into()), + nonce: Diff::Born(0.into()), code: Diff::Born(vec![]), storage: map![], })); @@ -126,11 +126,11 @@ mod test { #[test] fn basic() { - let a = PodAccount{balance: x!(69), nonce: x!(0), code: vec![], storage: map![]}; - let b = PodAccount{balance: x!(42), nonce: x!(1), code: vec![], storage: map![]}; + let a = PodAccount{balance: 69.into(), nonce: 0.into(), code: vec![], storage: map![]}; + let b = PodAccount{balance: 42.into(), nonce: 1.into(), code: vec![], storage: map![]}; assert_eq!(AccountDiff::diff_pod(Some(&a), Some(&b)), Some(AccountDiff { - balance: Diff::Changed(x!(69), x!(42)), - nonce: Diff::Changed(x!(0), x!(1)), + balance: Diff::Changed(69.into(), 42.into()), + nonce: Diff::Changed(0.into(), 1.into()), code: Diff::Same, storage: map![], })); @@ -138,11 +138,11 @@ mod test { #[test] fn code() { - let a = PodAccount{balance: x!(0), nonce: x!(0), code: vec![], storage: map![]}; - let b = PodAccount{balance: x!(0), nonce: x!(1), code: vec![0], storage: map![]}; + let a = PodAccount{balance: 0.into(), nonce: 0.into(), code: vec![], storage: map![]}; + let b = PodAccount{balance: 0.into(), nonce: 1.into(), code: vec![0], storage: map![]}; assert_eq!(AccountDiff::diff_pod(Some(&a), Some(&b)), Some(AccountDiff { balance: Diff::Same, - nonce: Diff::Changed(x!(0), x!(1)), + nonce: Diff::Changed(0.into(), 1.into()), code: Diff::Changed(vec![], vec![0]), storage: map![], })); @@ -151,14 +151,14 @@ mod test { #[test] fn storage() { let a = PodAccount { - balance: x!(0), - nonce: x!(0), + balance: 0.into(), + nonce: 0.into(), code: vec![], storage: mapx![1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 0, 6 => 0, 7 => 0] }; let b = PodAccount { - balance: x!(0), - nonce: x!(0), + balance: 0.into(), + nonce: 0.into(), code: vec![], storage: mapx![1 => 1, 2 => 3, 3 => 0, 5 => 0, 7 => 7, 8 => 0, 9 => 9] }; @@ -167,11 +167,11 @@ mod test { nonce: Diff::Same, code: Diff::Same, storage: map![ - x!(2) => Diff::new(x!(2), x!(3)), - x!(3) => Diff::new(x!(3), x!(0)), - x!(4) => Diff::new(x!(4), x!(0)), - x!(7) => Diff::new(x!(0), x!(7)), - x!(9) => Diff::new(x!(0), x!(9)) + 2.into() => Diff::new(2.into(), 3.into()), + 3.into() => Diff::new(3.into(), 0.into()), + 4.into() => Diff::new(4.into(), 0.into()), + 7.into() => Diff::new(0.into(), 7.into()), + 9.into() => Diff::new(0.into(), 9.into()), ], })); } diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index eabca24a8..6e0e4f2f6 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -214,7 +214,7 @@ impl State { /// Initialise the code of account `a` so that it is `value` for `key`. /// NOTE: Account should have been created with `new_contract`. pub fn init_code(&mut self, a: &Address, code: Bytes) { - self.require_or_from(a, true, || Account::new_contract(x!(0), self.account_start_nonce), |_|{}).init_code(code); + self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{}).init_code(code); } /// Execute a given transaction. @@ -377,27 +377,27 @@ fn should_apply_create_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), action: Action::Create, - value: x!(100), + value: 100.into(), data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(), }.sign(&"".sha3()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Create(trace::Create { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - value: x!(100), - gas: x!(77412), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + value: 100.into(), + gas: 77412.into(), init: vec![96, 16, 128, 96, 12, 96, 0, 57, 96, 0, 243, 0, 96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53, 85], }), result: trace::Res::Create(trace::CreateResult { @@ -438,27 +438,27 @@ fn should_trace_failed_create_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), action: Action::Create, - value: x!(100), + value: 100.into(), data: FromHex::from_hex("5b600056").unwrap(), }.sign(&"".sha3()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Create(trace::Create { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - value: x!(100), - gas: x!(78792), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + value: 100.into(), + gas: 78792.into(), init: vec![91, 96, 0, 86], }), result: trace::Res::FailedCreate, @@ -476,29 +476,29 @@ fn should_trace_call_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -519,28 +519,28 @@ fn should_trace_basic_call_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![], }.sign(&"".sha3()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -561,15 +561,15 @@ fn should_trace_call_transaction_to_builtin() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = Spec::new_test().engine; let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0x1)), - value: x!(0), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0x1.into()), + value: 0.into(), data: vec![], }.sign(&"".sha3()); @@ -579,10 +579,10 @@ fn should_trace_call_transaction_to_builtin() { assert_eq!(result.trace, Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!("0000000000000000000000000000000000000001"), - value: x!(0), - gas: x!(79_000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: "0000000000000000000000000000000000000001".into(), + value: 0.into(), + gas: 79_000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -601,29 +601,29 @@ fn should_not_trace_subcall_transaction_to_builtin() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = Spec::new_test().engine; let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(0), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 0.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("600060006000600060006001610be0f1").unwrap()); + state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap()); let vm_factory = Default::default(); let result = state.apply(&info, engine.deref(), &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(0), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 0.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -643,30 +643,30 @@ fn should_not_trace_callcode() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = Spec::new_test().engine; let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(0), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 0.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b611000f2").unwrap()); - state.init_code(&x!(0xb), FromHex::from_hex("6000").unwrap()); + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); let vm_factory = Default::default(); let result = state.apply(&info, engine.deref(), &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(0), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 0.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -686,33 +686,33 @@ fn should_not_trace_delegatecall() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); info.number = 0x789b0; let engine = Spec::new_test().engine; println!("schedule.have_delegate_call: {:?}", engine.schedule(&info).have_delegate_call); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(0), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 0.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("6000600060006000600b618000f4").unwrap()); - state.init_code(&x!(0xb), FromHex::from_hex("6000").unwrap()); + state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); let vm_factory = Default::default(); let result = state.apply(&info, engine.deref(), &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(0), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 0.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -732,29 +732,29 @@ fn should_trace_failed_call_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("5b600056").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::FailedCall, @@ -774,30 +774,30 @@ fn should_trace_call_with_subcall_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&x!(0xb), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -807,10 +807,10 @@ fn should_trace_call_with_subcall_transaction() { subs: vec![Trace { depth: 1, action: trace::Action::Call(trace::Call { - from: x!(0xa), - to: x!(0xb), - value: x!(0), - gas: x!(78934), + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -832,29 +832,29 @@ fn should_trace_call_with_basic_subcall_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -864,10 +864,10 @@ fn should_trace_call_with_basic_subcall_transaction() { subs: vec![Trace { depth: 1, action: trace::Action::Call(trace::Call { - from: x!(0xa), - to: x!(0xb), - value: x!(69), - gas: x!(2300), + from: 0xa.into(), + to: 0xb.into(), + value: 69.into(), + gas: 2300.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult::default()), @@ -886,29 +886,29 @@ fn should_not_trace_call_with_invalid_basic_subcall_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds. - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds. + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -929,30 +929,30 @@ fn should_trace_failed_subcall_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![],//600480600b6000396000f35b600056 }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&x!(0xb), FromHex::from_hex("5b600056").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -962,10 +962,10 @@ fn should_trace_failed_subcall_transaction() { subs: vec![Trace { depth: 1, action: trace::Action::Call(trace::Call { - from: x!(0xa), - to: x!(0xb), - value: x!(0), - gas: x!(78934), + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), input: vec![], }), result: trace::Res::FailedCall, @@ -984,31 +984,31 @@ fn should_trace_call_with_subcall_with_subcall_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![], }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&x!(0xb), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()); - state.init_code(&x!(0xc), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()); + state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -1018,10 +1018,10 @@ fn should_trace_call_with_subcall_with_subcall_transaction() { subs: vec![Trace { depth: 1, action: trace::Action::Call(trace::Call { - from: x!(0xa), - to: x!(0xb), - value: x!(0), - gas: x!(78934), + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -1031,10 +1031,10 @@ fn should_trace_call_with_subcall_with_subcall_transaction() { subs: vec![Trace { depth: 2, action: trace::Action::Call(trace::Call { - from: x!(0xb), - to: x!(0xc), - value: x!(0), - gas: x!(78868), + from: 0xb.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78868.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -1057,31 +1057,31 @@ fn should_trace_failed_subcall_with_subcall_transaction() { let mut state = get_temp_state_in(temp.as_path()); let mut info = EnvInfo::default(); - info.gas_limit = x!(1_000_000); + info.gas_limit = 1_000_000.into(); let engine = TestEngine::new(5); let t = Transaction { - nonce: x!(0), - gas_price: x!(0), - gas: x!(100_000), - action: Action::Call(x!(0xa)), - value: x!(100), + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Call(0xa.into()), + value: 100.into(), data: vec![],//600480600b6000396000f35b600056 }.sign(&"".sha3()); - state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); - state.init_code(&x!(0xb), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()); - state.init_code(&x!(0xc), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); + state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); + state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()); + state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); + state.add_balance(t.sender().as_ref().unwrap(), &100.into()); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { - from: x!("9cce34f7ab185c7aba1b7c8140d620b4bda941d6"), - to: x!(0xa), - value: x!(100), - gas: x!(79000), + from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + to: 0xa.into(), + value: 100.into(), + gas: 79000.into(), input: vec![], }), result: trace::Res::Call(trace::CallResult { @@ -1091,21 +1091,21 @@ fn should_trace_failed_subcall_with_subcall_transaction() { subs: vec![Trace { depth: 1, action: trace::Action::Call(trace::Call { - from: x!(0xa), - to: x!(0xb), - value: x!(0), - gas: x!(78934), + from: 0xa.into(), + to: 0xb.into(), + value: 0.into(), + gas: 78934.into(), input: vec![], }), result: trace::Res::FailedCall, subs: vec![Trace { depth: 2, action: trace::Action::Call(trace::Call { - from: x!(0xb), - to: x!(0xc), - value: x!(0), - gas: x!(78868), - input: vec![], + from: 0xb.into(), + to: 0xc.into(), + value: 0.into(), + gas: 78868.into(), + input: vec![], }), result: trace::Res::Call(trace::CallResult { gas_used: U256::from(3), @@ -1125,7 +1125,7 @@ fn code_from_database() { let temp = RandomTempPath::new(); let (root, db) = { let mut state = get_temp_state_in(temp.as_path()); - state.require_or_from(&a, false, ||Account::new_contract(x!(42), x!(0)), |_|{}); + state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{}); state.init_code(&a, vec![1, 2, 3]); assert_eq!(state.code(&a), Some([1u8, 2, 3].to_vec())); state.commit(); diff --git a/ethcore/src/substate.rs b/ethcore/src/substate.rs index 65b314663..247bbb398 100644 --- a/ethcore/src/substate.rs +++ b/ethcore/src/substate.rs @@ -74,7 +74,7 @@ mod tests { topics: vec![], data: vec![] }); - sub_state.sstore_clears_count = x!(5); + sub_state.sstore_clears_count = 5.into(); sub_state.suicides.insert(address_from_u64(10u64)); let mut sub_state_2 = Substate::new(); @@ -84,11 +84,11 @@ mod tests { topics: vec![], data: vec![] }); - sub_state_2.sstore_clears_count = x!(7); + sub_state_2.sstore_clears_count = 7.into(); sub_state.accrue(sub_state_2); assert_eq!(sub_state.contracts_created.len(), 2); - assert_eq!(sub_state.sstore_clears_count, x!(12)); + assert_eq!(sub_state.sstore_clears_count, 12.into()); assert_eq!(sub_state.suicides.len(), 1); } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index d734b0b47..4a71bf7d7 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -136,7 +136,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![]).0.unwrap(); + let b = client.prepare_sealing(Address::default(), 31415926.into(), vec![], vec![]).0.unwrap(); assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3()); assert!(client.try_seal(b.lock(), vec![]).is_ok()); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 7262da9e8..6a370e49f 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -98,8 +98,8 @@ pub fn create_test_block(header: &Header) -> Bytes { fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header { let mut header = Header::new(); - header.gas_limit = x!(0); - header.difficulty = x!(order * 100); + header.gas_limit = 0.into(); + header.difficulty = order * 100.into(); header.timestamp = (order * 10) as u64; header.number = order as u64; header.parent_hash = parent_hash; @@ -335,7 +335,7 @@ pub fn get_bad_state_dummy_block() -> Bytes { block_header.timestamp = 40; block_header.number = 1; block_header.parent_hash = test_spec.genesis_header().hash(); - block_header.state_root = x!(0xbad); + block_header.state_root = 0xbad.into(); create_test_block(&block_header) } diff --git a/ethcore/src/types/receipt.rs b/ethcore/src/types/receipt.rs index f07a12212..78216eb16 100644 --- a/ethcore/src/types/receipt.rs +++ b/ethcore/src/types/receipt.rs @@ -105,10 +105,10 @@ pub struct LocalizedReceipt { fn test_basic() { let expected = ::rustc_serialize::hex::FromHex::from_hex("f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); let r = Receipt::new( - x!("2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee"), - x!(0x40cae), + "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into(), + 0x40cae.into(), vec![LogEntry { - address: x!("dcf421d093428b096ca501a7cd1a740855a7976f"), + address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), topics: vec![], data: vec![0u8; 32] }] From 3abaeadcf3794708246042d961096ef349d65519 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 17:18:21 +0200 Subject: [PATCH 12/43] finish purging x! from ethcore --- ethcore/src/state_diff.rs | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/ethcore/src/state_diff.rs b/ethcore/src/state_diff.rs index 6c41d167c..1c1975e70 100644 --- a/ethcore/src/state_diff.rs +++ b/ethcore/src/state_diff.rs @@ -59,19 +59,19 @@ mod test { #[test] fn create_delete() { - let a = PodState::from(map![ x!(1) => PodAccount::new(x!(69), x!(0), vec![], map![]) ]); + let a = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); assert_eq!(StateDiff::diff_pod(&a, &PodState::new()), StateDiff(map![ - x!(1) => AccountDiff{ - balance: Diff::Died(x!(69)), - nonce: Diff::Died(x!(0)), + 1.into() => AccountDiff{ + balance: Diff::Died(69.into()), + nonce: Diff::Died(0.into()), code: Diff::Died(vec![]), storage: map![], } ])); assert_eq!(StateDiff::diff_pod(&PodState::new(), &a), StateDiff(map![ - x!(1) => AccountDiff{ - balance: Diff::Born(x!(69)), - nonce: Diff::Born(x!(0)), + 1.into() => AccountDiff{ + balance: Diff::Born(69.into()), + nonce: Diff::Born(0.into()), code: Diff::Born(vec![]), storage: map![], } @@ -80,23 +80,23 @@ mod test { #[test] fn create_delete_with_unchanged() { - let a = PodState::from(map![ x!(1) => PodAccount::new(x!(69), x!(0), vec![], map![]) ]); + let a = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); let b = PodState::from(map![ - x!(1) => PodAccount::new(x!(69), x!(0), vec![], map![]), - x!(2) => PodAccount::new(x!(69), x!(0), vec![], map![]) + 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]), + 2.into() => PodAccount::new(69.into(), 0.into(),, vec![], map![]) ]); assert_eq!(StateDiff::diff_pod(&a, &b), StateDiff(map![ - x!(2) => AccountDiff{ - balance: Diff::Born(x!(69)), - nonce: Diff::Born(x!(0)), + 2.into() => AccountDiff{ + balance: Diff::Born(69.into()), + nonce: Diff::Born(0.into()), code: Diff::Born(vec![]), storage: map![], } ])); assert_eq!(StateDiff::diff_pod(&b, &a), StateDiff(map![ - x!(2) => AccountDiff{ - balance: Diff::Died(x!(69)), - nonce: Diff::Died(x!(0)), + 2.into() => AccountDiff{ + balance: Diff::Died(69.into()), + nonce: Diff::Died(0.into()), code: Diff::Died(vec![]), storage: map![], } @@ -106,17 +106,17 @@ mod test { #[test] fn change_with_unchanged() { let a = PodState::from(map![ - x!(1) => PodAccount::new(x!(69), x!(0), vec![], map![]), - x!(2) => PodAccount::new(x!(69), x!(0), vec![], map![]) + 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]), + 2.into() => PodAccount::new(69.into(), 0.into(),, vec![], map![]) ]); let b = PodState::from(map![ - x!(1) => PodAccount::new(x!(69), x!(1), vec![], map![]), - x!(2) => PodAccount::new(x!(69), x!(0), vec![], map![]) + 1.into() => PodAccount::new(69.into(), 1.into(),, vec![], map![]), + 2.into() => PodAccount::new(69.into(), 0.into(),, vec![], map![]) ]); assert_eq!(StateDiff::diff_pod(&a, &b), StateDiff(map![ - x!(1) => AccountDiff{ + 1.into() => AccountDiff{ balance: Diff::Same, - nonce: Diff::Changed(x!(0), x!(1)), + nonce: Diff::Changed(0.into(), 1.into()), code: Diff::Same, storage: map![], } From c62bfcddef1fedaaa76eed2870071cd93846c1c7 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 17:25:25 +0200 Subject: [PATCH 13/43] finish purging x! from parity, remove x! and xx! macros --- miner/src/lib.rs | 4 ++-- miner/src/miner.rs | 6 +++--- sync/src/chain.rs | 6 +++--- util/src/common.rs | 14 -------------- util/src/keys/store.rs | 2 +- 5 files changed, 9 insertions(+), 23 deletions(-) diff --git a/miner/src/lib.rs b/miner/src/lib.rs index a1780efff..f91811948 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -150,10 +150,10 @@ pub trait MinerService : Send + Sync { fn last_nonce(&self, address: &Address) -> Option; /// Suggested gas price. - fn sensible_gas_price(&self) -> U256 { x!(20000000000u64) } + fn sensible_gas_price(&self) -> U256 { 20000000000u64.into() } /// Suggested gas limit. - fn sensible_gas_limit(&self) -> U256 { x!(21000) } + fn sensible_gas_limit(&self) -> U256 { 21000.into() } /// Latest account balance in pending state. fn balance(&self, chain: &BlockChainClient, address: &Address) -> U256; diff --git a/miner/src/miner.rs b/miner/src/miner.rs index fc63aec6c..d9abb09f4 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -137,7 +137,7 @@ impl Miner { 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 - let min_tx_gas: U256 = x!(21000); // TODO: figure this out properly. + let min_tx_gas: U256 = 21000.into(); // TODO: figure this out properly. if gas_limit - gas_used < min_tx_gas { break; } @@ -337,11 +337,11 @@ impl MinerService for Miner { fn sensible_gas_price(&self) -> U256 { // 10% above our minimum. - *self.transaction_queue.lock().unwrap().minimal_gas_price() * x!(110) / x!(100) + *self.transaction_queue.lock().unwrap().minimal_gas_price() * 110.into() / 100.into() } fn sensible_gas_limit(&self) -> U256 { - *self.gas_floor_target.read().unwrap() / x!(5) + *self.gas_floor_target.read().unwrap() / 5.into() } fn transactions_limit(&self) -> usize { diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 2f31f1d47..dcfdc1c16 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1310,8 +1310,8 @@ mod tests { fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { let mut header = Header::new(); - header.gas_limit = x!(0); - header.difficulty = x!(order * 100); + header.gas_limit = 0.into(); + header.difficulty = (order * 100).into(); header.timestamp = (order * 10) as u64; header.number = order as u64; header.parent_hash = parent_hash; @@ -1327,7 +1327,7 @@ mod tests { fn get_dummy_blocks(order: u32, parent_hash: H256) -> Bytes { let mut rlp = RlpStream::new_list(1); rlp.append_raw(&get_dummy_block(order, parent_hash), 1); - let difficulty: U256 = x!(100 * order); + let difficulty: U256 = (100 * order).into(); rlp.append(&difficulty); rlp.out() } diff --git a/util/src/common.rs b/util/src/common.rs index 7ed660f29..c1de582df 100644 --- a/util/src/common.rs +++ b/util/src/common.rs @@ -68,20 +68,6 @@ macro_rules! mapx { }} } -#[macro_export] -macro_rules! x { - ( $x:expr ) => { - From::from($x) - } -} - -#[macro_export] -macro_rules! xx { - ( $x:expr ) => { - From::from(From::from($x)) - } -} - #[macro_export] macro_rules! flush { ($($arg:tt)*) => ($crate::flush(format!("{}", format_args!($($arg)*)))); diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index 296f7ad37..3402596d3 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -627,7 +627,7 @@ mod tests { sstore.sign(&address, &H256::random()).unwrap() }; - assert!(signature != x!(0)); + assert!(signature != 0.into()); } #[test] From da9d6bf8d5a8824d4ea712403adace4bce5b256b Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 17:29:01 +0200 Subject: [PATCH 14/43] rename [hash_]mapx to [hash_]map_into --- ethcore/src/pod_account.rs | 4 ++-- util/src/common.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 6f3949db3..96642d1f8 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -154,13 +154,13 @@ mod test { balance: 0.into(), nonce: 0.into(), code: vec![], - storage: mapx![1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 0, 6 => 0, 7 => 0] + storage: map_into![1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 0, 6 => 0, 7 => 0] }; let b = PodAccount { balance: 0.into(), nonce: 0.into(), code: vec![], - storage: mapx![1 => 1, 2 => 3, 3 => 0, 5 => 0, 7 => 7, 8 => 0, 9 => 9] + storage: map_into![1 => 1, 2 => 3, 3 => 0, 5 => 0, 7 => 7, 8 => 0, 9 => 9] }; assert_eq!(AccountDiff::diff_pod(Some(&a), Some(&b)), Some(AccountDiff { balance: Diff::Same, diff --git a/util/src/common.rs b/util/src/common.rs index c1de582df..2eb2ea017 100644 --- a/util/src/common.rs +++ b/util/src/common.rs @@ -36,7 +36,7 @@ macro_rules! hash_map { } #[macro_export] -macro_rules! hash_mapx { +macro_rules! hash_map_into { ( $( $x:expr => $y:expr ),* ) => {{ let mut x = HashMap::new(); $( @@ -58,7 +58,7 @@ macro_rules! map { } #[macro_export] -macro_rules! mapx { +macro_rules! map_into { ( $( $x:expr => $y:expr ),* ) => {{ let mut x = BTreeMap::new(); $( From 4f732972bc366b758ef97190380d86192cef779c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 19:01:37 +0200 Subject: [PATCH 15/43] refactoring to hold miner within the client --- ethcore/Cargo.toml | 1 + ethcore/src/client/client.rs | 32 ++++++++++++++++++++++++-------- ethcore/src/client/mod.rs | 11 +++++++++-- sync/src/chain.rs | 22 ++-------------------- sync/src/io.rs | 8 ++++---- sync/src/lib.rs | 11 ----------- sync/src/tests/chain.rs | 2 +- sync/src/tests/helpers.rs | 2 +- 8 files changed, 42 insertions(+), 47 deletions(-) diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 34a010794..f63eb957c 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -29,6 +29,7 @@ ethcore-devtools = { path = "../devtools" } ethjson = { path = "../json" } bloomchain = "0.1" "ethcore-ipc" = { path = "../ipc/rpc" } +ethminer = { path = "../miner" } [features] jit = ["evmjit"] diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 8f6d607ba..7a616fdbc 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -90,6 +90,7 @@ pub struct Client where V: Verifier { panic_handler: Arc, verifier: PhantomData, vm_factory: Arc, + miner: Arc, } const HISTORY: u64 = 1200; @@ -126,7 +127,13 @@ pub fn append_path(path: &Path, item: &str) -> String { impl Client where V: Verifier { /// Create a new client with given spec and DB path and custom verifier. - pub fn new_with_verifier(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel ) -> Result>, ClientError> { + pub fn new_with_verifier( + config: ClientConfig, + spec: Spec, + path: &Path, + message_channel: IoChannel) + -> Result>, ClientError> + { let path = get_db_path(path, config.pruning, spec.genesis_header().hash()); let gb = spec.genesis_block(); let chain = Arc::new(BlockChain::new(config.blockchain, &gb, &path)); @@ -328,18 +335,13 @@ impl Client where V: Verifier { { 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, - invalid: invalid_blocks, - enacted: enacted, - retracted: retracted, - })).unwrap(); + self.miner.chain_new_blocks(imported_blocks, invalid_blocks, enacted, retracted); } } { if self.chain_info().best_block_hash != original_best { - io.send(NetworkIoMessage::User(SyncMessage::NewChainHead)).unwrap(); + self.miner.update_sealing(&self); } } @@ -778,6 +780,20 @@ impl ExtendedBlockChainClient for Client where V: Verifier { } } +impl MiningClient for Client { + fn import_transactions(&self, transactions: Vec) -> Vec> { + let fetch_account = |a: &Address| AccountDetails { + nonce: self.latest_nonce(a), + balance: self.latest_balance(a), + }; + self.miner.import_transactions(transactions, fetch_account) + } + + fn all_transactions(&self) -> Vec { + self.miner.all_transactions() + } +} + impl MayPanic for Client { fn on_panic(&self, closure: F) where F: OnPanicListener { self.panic_handler.on_panic(closure); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 5537f8e66..dfef54a40 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -178,12 +178,19 @@ pub trait BlockChainClient : Sync + Send { /// Extended client interface used for mining pub trait ExtendedBlockChainClient : BlockChainClient { - // 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. fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; - // 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, HashSet); } + +/// Extended client interface that supports mining +pub trait MiningClient : BlockChainClient { + /// import transactions from network/other 3rd party + fn import_transactions(&self, transactions: Vec) -> Vec>; + + /// list all transactions + fn all_transactions(&self) -> Vec; +} diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 2f31f1d47..a0d0ba1fa 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -903,7 +903,7 @@ impl ChainSync { nonce: chain.latest_nonce(a), balance: chain.latest_balance(a), }; - let _ = self.miner.import_transactions(transactions, fetch_account); + let _ = io.chain().import_transactions(transactions, fetch_account); Ok(()) } @@ -1226,7 +1226,7 @@ impl ChainSync { return 0; } - let mut transactions = self.miner.all_transactions(); + let mut transactions = io.chain().all_transactions(); if transactions.is_empty() { return 0; } @@ -1275,24 +1275,6 @@ impl ChainSync { pub fn maintain_sync(&mut self, io: &mut SyncIo) { self.check_resume(io); } - - /// 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 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); - } - if !invalid.is_empty() { - trace!(target: "sync", "Bad blocks in the queue, restarting"); - self.restart_on_bad_block(io); - } - } - - pub fn chain_new_head(&mut self, io: &mut SyncIo) { - self.miner.update_sealing(io.chain()); - } } #[cfg(test)] diff --git a/sync/src/io.rs b/sync/src/io.rs index 84697a021..49cccd7ca 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethcore::client::BlockChainClient; +use ethcore::client::MiningClient; use util::{NetworkContext, PeerId, PacketId,}; use util::error::UtilError; use ethcore::service::SyncMessage; @@ -32,7 +32,7 @@ pub trait SyncIo { /// Send a packet to a peer. fn send(&mut self, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError>; /// Get the blockchain - fn chain(&self) -> &BlockChainClient; + fn chain(&self) -> &MiningClient; /// Returns peer client identifier string fn peer_info(&self, peer_id: PeerId) -> String { peer_id.to_string() @@ -46,12 +46,12 @@ pub trait SyncIo { /// Wraps `NetworkContext` and the blockchain client pub struct NetSyncIo<'s, 'h> where 'h: 's { network: &'s NetworkContext<'h, SyncMessage>, - chain: &'s BlockChainClient + chain: &'s MiningClient } impl<'s, 'h> NetSyncIo<'s, 'h> { /// Creates a new instance from the `NetworkContext` and the blockchain client reference. - pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s BlockChainClient) -> NetSyncIo<'s, 'h> { + pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s MiningClient) -> NetSyncIo<'s, 'h> { NetSyncIo { network: network, chain: chain, diff --git a/sync/src/lib.rs b/sync/src/lib.rs index c8dc93db6..6b72a24fc 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -166,16 +166,5 @@ impl NetworkProtocolHandler for EthSync { } fn message(&self, io: &NetworkContext, message: &SyncMessage) { - match *message { - 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); - }, - SyncMessage::NewChainHead => { - let mut sync_io = NetSyncIo::new(io, self.chain.deref()); - self.sync.write().unwrap().chain_new_head(&mut sync_io); - }, - _ => {/* Ignore other messages */}, - } } } diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index 09e83e358..463771ffe 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{BlockChainClient, BlockID, EachBlockWith}; +use ethcore::client::{MiningClient, BlockID, EachBlockWith}; use chain::{SyncState}; use super::helpers::*; diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index d1ffde0f0..70ddb78db 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -63,7 +63,7 @@ impl<'p> SyncIo for TestIo<'p> { Ok(()) } - fn chain(&self) -> &BlockChainClient { + fn chain(&self) -> &MiningClient { self.chain } } From 4ccaabde40365d0815a9fcd0c69eecc041cea784 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 19:30:40 +0200 Subject: [PATCH 16/43] add transaction count verifier tests --- rpc/src/v1/tests/eth.rs | 96 ++++++++++++++++++++++++++++++++++++----- rpc/src/v1/tests/mod.rs | 25 ++++++++--- 2 files changed, 104 insertions(+), 17 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 9b2cb3195..0c159ceb2 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,15 +19,18 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; +use ethcore::ids::BlockID; use ethcore::client::{Client, BlockChainClient, ClientConfig}; use ethcore::spec::{Genesis, Spec}; use ethcore::block::Block; +use ethcore::views::BlockView; use ethcore::ethereum; use ethminer::{Miner, MinerService, ExternalMiner}; use devtools::RandomTempPath; +use util::Hashable; use util::io::IoChannel; -use util::hash::Address; -use util::numbers::{Uint, U256}; +use util::hash::{Address, H256}; +use util::numbers::U256; use util::keys::{AccountProvider, TestAccount, TestAccountProvider}; use jsonrpc_core::IoHandler; use ethjson::blockchain::BlockChain; @@ -72,8 +75,8 @@ struct EthTester { } impl EthTester { - fn from_chain(chain: BlockChain) -> Self { - let tester = Self::from_spec_provider(|| make_spec(&chain)); + fn from_chain(chain: &BlockChain) -> Self { + let tester = Self::from_spec_provider(|| make_spec(chain)); for b in &chain.blocks_rlp() { if Block::is_good(&b) { @@ -83,7 +86,9 @@ impl EthTester { } } - assert!(tester.client.chain_info().best_block_hash == chain.best_block.into()); + tester.client.flush_queue(); + + assert!(tester.client.chain_info().best_block_hash == chain.best_block.clone().into()); tester } @@ -116,13 +121,13 @@ impl EthTester { #[test] fn harness_works() { let chain: BlockChain = extract_chain!("BlockchainTests/bcUncleTest"); - let _ = EthTester::from_chain(chain); + let _ = EthTester::from_chain(&chain); } #[test] fn eth_get_balance() { let chain = extract_chain!("BlockchainTests/bcWalletTest", "wallet2outOf3txs"); - let tester = EthTester::from_chain(chain); + let tester = EthTester::from_chain(&chain); // final account state let req_latest = r#"{ "jsonrpc": "2.0", @@ -148,7 +153,7 @@ fn eth_get_balance() { #[test] fn eth_block_number() { let chain = extract_chain!("BlockchainTests/bcRPC_API_Test"); - let tester = EthTester::from_chain(chain); + let tester = EthTester::from_chain(&chain); let req_number = r#"{ "jsonrpc": "2.0", "method": "eth_blockNumber", @@ -206,7 +211,6 @@ const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{ } "#; -#[cfg(test)] #[test] fn eth_transaction_count() { use util::crypto::Secret; @@ -271,4 +275,76 @@ fn eth_transaction_count() { let res_after_pending = r#"{"jsonrpc":"2.0","result":"0x01","id":18}"#; assert_eq!(&tester.handler.handle_request(&req_after_pending).unwrap(), res_after_pending); -} \ No newline at end of file +} + +fn verify_transaction_counts(name: String, chain: BlockChain) { + struct PanicHandler(String); + impl Drop for PanicHandler { + fn drop(&mut self) { + if ::std::thread::panicking() { + println!("Test failed: {}", self.0); + } + } + } + + let _panic = PanicHandler(name); + + fn by_hash(hash: H256, count: usize, id: &mut usize) -> (String, String) { + let req = r#"{ + "jsonrpc": "2.0", + "method": "eth_getBlockTransactionCountByHash", + "params": [ + ""#.to_owned() + format!("0x{:?}", hash).as_ref() + r#"" + ], + "id": "# + format!("{}", *id).as_ref() + r#" + }"#; + + let res = r#"{"jsonrpc":"2.0","result":""#.to_owned() + + format!("0x{:02x}", count).as_ref() + + r#"","id":"# + + format!("{}", *id).as_ref() + r#"}"#; + *id += 1; + (req, res) + } + + fn by_number(num: u64, count: usize, id: &mut usize) -> (String, String) { + let req = r#"{ + "jsonrpc": "2.0", + "method": "eth_getBlockTransactionCountByNumber", + "params": [ + "#.to_owned() + &::serde_json::to_string(&U256::from(num)).unwrap() + r#" + ], + "id": "# + format!("{}", *id).as_ref() + r#" + }"#; + + let res = r#"{"jsonrpc":"2.0","result":""#.to_owned() + + format!("0x{:02x}", count).as_ref() + + r#"","id":"# + + format!("{}", *id).as_ref() + r#"}"#; + *id += 1; + (req, res) + } + + let tester = EthTester::from_chain(&chain); + + let mut id = 1; + for b in chain.blocks_rlp().iter().filter(|b| Block::is_good(b)).map(|b| BlockView::new(b)) { + let count = b.transactions_count(); + + let hash = b.sha3(); + let number = b.header_view().number(); + + let (req, res) = by_hash(hash, count, &mut id); + assert_eq!(tester.handler.handle_request(&req), Some(res)); + + // uncles can share block numbers, so skip them. + if tester.client.block_hash(BlockID::Number(number)) == Some(hash) { + let (req, res) = by_number(number, count, &mut id); + assert_eq!(tester.handler.handle_request(&req), Some(res)); + } + } +} + +register_test!(eth_transaction_count_1, verify_transaction_counts, "BlockchainTests/bcWalletTest"); +register_test!(eth_transaction_count_2, verify_transaction_counts, "BlockchainTests/bcTotalDifficultyTest"); +register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/bcGasPricerTest"); \ No newline at end of file diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs index 3455bfd1f..9e71addd4 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/rpc/src/v1/tests/mod.rs @@ -13,11 +13,15 @@ pub mod helpers; // extract the chain with that name. This will panic if no chain by that name // is found. macro_rules! extract_chain { - ($file:expr, $name:expr) => {{ + (iter $file:expr) => {{ const RAW_DATA: &'static [u8] = include_bytes!(concat!("../../../../ethcore/res/ethereum/tests/", $file, ".json")); + ::ethjson::blockchain::Test::load(RAW_DATA).unwrap().into_iter() + }}; + + ($file:expr, $name:expr) => {{ let mut chain = None; - for (name, c) in ::ethjson::blockchain::Test::load(RAW_DATA).unwrap() { + for (name, c) in extract_chain!(iter $file) { if name == $name { chain = Some(c); break; @@ -27,14 +31,21 @@ macro_rules! extract_chain { }}; ($file:expr) => {{ - const RAW_DATA: &'static [u8] = - include_bytes!(concat!("../../../../ethcore/res/ethereum/tests/", $file, ".json")); - - ::ethjson::blockchain::Test::load(RAW_DATA) - .unwrap().into_iter().next().unwrap().1 + extract_chain!(iter $file).next().unwrap().1 }}; } +macro_rules! register_test { + ($name:ident, $cb:expr, $file:expr) => { + #[test] + fn $name() { + for (name, chain) in extract_chain!(iter $file) { + $cb(name, chain); + } + } + } +} + #[cfg(test)] mod mocked; #[cfg(test)] From c81e4e24b303a765120fefe15600705918aa9afe Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 19:51:24 +0200 Subject: [PATCH 17/43] add ability to have heavy tests --- rpc/src/v1/tests/mod.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs index 9e71addd4..a48727475 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/rpc/src/v1/tests/mod.rs @@ -43,7 +43,27 @@ macro_rules! register_test { $cb(name, chain); } } - } + }; + + (heavy $name:ident, $cb:expr, $file:expr) => { + #[test] + #[cfg(feature = "test-heavy")] + fn $name() { + for (name, chain) in extract_chain!(iter $file) { + $cb(name, chain); + } + } + }; + + (ignore $name:ident, $cb:expr, $file:expr) => { + #[test] + #[ignore] + fn $name() { + for (name, chain) in extract_chain!(iter $file) { + $cb(name, chain); + } + } + }; } #[cfg(test)] From 8e252d5f1ba81585292477be869f3e1843c16fa1 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 19:52:53 +0200 Subject: [PATCH 18/43] refactored to merge client & client --- ethcore/Cargo.toml | 2 +- ethcore/src/client/client.rs | 41 +++++++++---------- ethcore/src/client/mod.rs | 17 ++++---- ethcore/src/client/test_client.rs | 11 +++++ ethcore/src/lib.rs | 2 + {miner/src => ethcore/src/miner}/external.rs | 0 {miner/src => ethcore/src/miner}/miner.rs | 20 ++++----- miner/src/lib.rs => ethcore/src/miner/mod.rs | 32 +++++---------- .../src/miner}/transaction_queue.rs | 4 +- ethcore/src/service.rs | 5 ++- 10 files changed, 68 insertions(+), 66 deletions(-) rename {miner/src => ethcore/src/miner}/external.rs (100%) rename {miner/src => ethcore/src/miner}/miner.rs (98%) rename miner/src/lib.rs => ethcore/src/miner/mod.rs (89%) rename {miner/src => ethcore/src/miner}/transaction_queue.rs (99%) diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index f63eb957c..1de24ee32 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -29,7 +29,7 @@ ethcore-devtools = { path = "../devtools" } ethjson = { path = "../json" } bloomchain = "0.1" "ethcore-ipc" = { path = "../ipc/rpc" } -ethminer = { path = "../miner" } +rayon = "0.3.1" [features] jit = ["evmjit"] diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 7a616fdbc..d23bffa31 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -48,6 +48,7 @@ use trace; pub use types::blockchain_info::BlockChainInfo; pub use types::block_status::BlockStatus; use evm::Factory as EvmFactory; +use miner::{Miner, MinerService, TransactionImportResult, AccountDetails}; impl fmt::Display for BlockChainInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -90,7 +91,7 @@ pub struct Client where V: Verifier { panic_handler: Arc, verifier: PhantomData, vm_factory: Arc, - miner: Arc, + miner: Arc, } const HISTORY: u64 = 1200; @@ -103,8 +104,8 @@ const CLIENT_DB_VER_STR: &'static str = "5.3"; impl Client { /// Create a new client with given spec and DB path. - pub fn new(config: ClientConfig, spec: Spec, path: &Path, message_channel: IoChannel ) -> Result, ClientError> { - Client::::new_with_verifier(config, spec, path, message_channel) + pub fn new(config: ClientConfig, spec: Spec, path: &Path, miner: Arc, message_channel: IoChannel ) -> Result, ClientError> { + Client::::new_with_verifier(config, spec, path, miner, message_channel) } } @@ -131,6 +132,7 @@ impl Client where V: Verifier { config: ClientConfig, spec: Spec, path: &Path, + miner: Arc, message_channel: IoChannel) -> Result>, ClientError> { @@ -162,6 +164,7 @@ impl Client where V: Verifier { panic_handler: panic_handler, verifier: PhantomData, vm_factory: Arc::new(EvmFactory::new(config.vm_type)), + miner: miner, }; Ok(Arc::new(client)) @@ -335,13 +338,13 @@ impl Client where V: Verifier { { if !imported_blocks.is_empty() && self.block_queue.queue_info().is_empty() { let (enacted, retracted) = self.calculate_enacted_retracted(import_results); - self.miner.chain_new_blocks(imported_blocks, invalid_blocks, enacted, retracted); + self.miner.chain_new_blocks(self, &imported_blocks, &invalid_blocks, &enacted, &retracted); } } { if self.chain_info().best_block_hash != original_best { - self.miner.update_sealing(&self); + self.miner.update_sealing(self); } } @@ -705,10 +708,21 @@ impl BlockChainClient for Client where V: Verifier { fn last_hashes(&self) -> LastHashes { self.build_last_hashes(self.chain.best_block_hash()) } + + fn import_transactions(&self, transactions: Vec) -> Vec> { + let fetch_account = |a: &Address| AccountDetails { + nonce: self.latest_nonce(a), + balance: self.latest_balance(a), + }; + self.miner.import_transactions(transactions, fetch_account) + } + + fn all_transactions(&self) -> Vec { + self.miner.all_transactions() + } } impl ExtendedBlockChainClient 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, HashSet) { let engine = self.engine.deref().deref(); @@ -774,26 +788,11 @@ impl ExtendedBlockChainClient for Client where V: Verifier { (Some(b), invalid_transactions) } - // TODO [todr] Should be moved to miner crate eventually. fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result { block.try_seal(self.engine.deref().deref(), seal) } } -impl MiningClient for Client { - fn import_transactions(&self, transactions: Vec) -> Vec> { - let fetch_account = |a: &Address| AccountDetails { - nonce: self.latest_nonce(a), - balance: self.latest_balance(a), - }; - self.miner.import_transactions(transactions, fetch_account) - } - - fn all_transactions(&self) -> Vec { - self.miner.all_transactions() - } -} - impl MayPanic for Client { fn on_panic(&self, closure: F) where F: OnPanicListener { self.panic_handler.on_panic(closure); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index dfef54a40..67c753d46 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -46,6 +46,8 @@ use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; use evm::Factory as EvmFactory; +use miner::{TransactionImportResult, AccountDetails}; +use error::Error as EthError; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -174,6 +176,12 @@ pub trait BlockChainClient : Sync + Send { /// Get last hashes starting from best block. fn last_hashes(&self) -> LastHashes; + + /// import transactions from network/other 3rd party + fn import_transactions(&self, transactions: Vec) -> Vec>; + + /// list all transactions + fn all_transactions(&self) -> Vec; } /// Extended client interface used for mining @@ -185,12 +193,3 @@ pub trait ExtendedBlockChainClient : BlockChainClient { fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> (Option, HashSet); } - -/// Extended client interface that supports mining -pub trait MiningClient : BlockChainClient { - /// import transactions from network/other 3rd party - fn import_transactions(&self, transactions: Vec) -> Vec>; - - /// list all transactions - fn all_transactions(&self) -> Vec; -} diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 5c093b720..ad398bbcb 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -35,6 +35,9 @@ use executive::Executed; use error::{ExecutionError}; use trace::LocalizedTrace; +use miner::{TransactionImportResult, AccountDetails}; +use error::Error as EthError; + /// Test client. pub struct TestBlockChainClient { /// Blocks. @@ -479,4 +482,12 @@ impl BlockChainClient for TestBlockChainClient { fn block_traces(&self, _trace: BlockID) -> Option> { unimplemented!(); } + + fn import_transactions(&self, transactions: Vec) -> Vec> { + unimplemented!(); + } + + fn all_transactions(&self) -> Vec { + unimplemented!(); + } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 1d4ddadbc..5cf9d50a1 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -90,6 +90,7 @@ extern crate crossbeam; extern crate ethjson; extern crate bloomchain; #[macro_use] extern crate ethcore_ipc as ipc; +extern crate rayon; #[cfg(test)] extern crate ethcore_devtools as devtools; #[cfg(feature = "jit" )] extern crate evmjit; @@ -109,6 +110,7 @@ pub mod views; pub mod pod_state; pub mod engine; pub mod migrations; +pub mod miner; mod blooms; mod db; diff --git a/miner/src/external.rs b/ethcore/src/miner/external.rs similarity index 100% rename from miner/src/external.rs rename to ethcore/src/miner/external.rs diff --git a/miner/src/miner.rs b/ethcore/src/miner/miner.rs similarity index 98% rename from miner/src/miner.rs rename to ethcore/src/miner/miner.rs index 7438e7e9b..c4bec7659 100644 --- a/miner/src/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -19,16 +19,16 @@ use std::sync::atomic::AtomicBool; use util::*; use util::keys::store::{AccountService, AccountProvider}; -use ethcore::views::{BlockView, HeaderView}; -use ethcore::client::{ExtendedBlockChainClient, BlockID}; -use ethcore::block::{ClosedBlock, IsBlock}; -use ethcore::error::*; -use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; -use ethcore::transaction::SignedTransaction; -use ethcore::receipt::{Receipt}; -use ethcore::spec::Spec; -use ethcore::engine::Engine; -use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; +use views::{BlockView, HeaderView}; +use client::{ExtendedBlockChainClient, BlockID}; +use block::{ClosedBlock, IsBlock}; +use error::*; +use client::{Executive, Executed, EnvInfo, TransactOptions}; +use transaction::SignedTransaction; +use receipt::{Receipt}; +use spec::Spec; +use engine::Engine; +use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; /// Keeps track of transactions using priority queue and holds currently mined block. pub struct Miner { diff --git a/miner/src/lib.rs b/ethcore/src/miner/mod.rs similarity index 89% rename from miner/src/lib.rs rename to ethcore/src/miner/mod.rs index db3315376..95453027c 100644 --- a/miner/src/lib.rs +++ b/ethcore/src/miner/mod.rs @@ -26,12 +26,11 @@ //! ```rust //! extern crate ethcore_util as util; //! extern crate ethcore; -//! extern crate ethminer; //! use std::env; //! use util::network::{NetworkService, NetworkConfiguration}; -//! use ethcore::client::{Client, ClientConfig}; -//! use ethcore::ethereum; -//! use ethminer::{Miner, MinerService}; +//! use client::{Client, ClientConfig}; +//! use ethereum; +//! use ethcore::miner::{Miner, MinerService}; //! //! fn main() { //! let miner: Miner = Miner::default(); @@ -43,30 +42,21 @@ //! } //! ``` - -#[macro_use] -extern crate log; -#[macro_use] -extern crate ethcore_util as util; -extern crate ethcore; -extern crate env_logger; -extern crate rayon; - mod miner; mod external; mod transaction_queue; -pub use transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; -pub use miner::{Miner}; -pub use external::{ExternalMiner, ExternalMinerService}; +pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; +pub use self::miner::{Miner}; +pub use self::external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; use util::{H256, U256, Address, Bytes}; -use ethcore::client::{ExtendedBlockChainClient, Executed}; -use ethcore::block::ClosedBlock; -use ethcore::receipt::Receipt; -use ethcore::error::{Error, ExecutionError}; -use ethcore::transaction::SignedTransaction; +use client::{ExtendedBlockChainClient, Executed}; +use block::ClosedBlock; +use receipt::Receipt; +use error::{Error, ExecutionError}; +use transaction::SignedTransaction; /// Miner client API pub trait MinerService : Send + Sync { diff --git a/miner/src/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs similarity index 99% rename from miner/src/transaction_queue.rs rename to ethcore/src/miner/transaction_queue.rs index fc62c411e..1b88a7a11 100644 --- a/miner/src/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -89,8 +89,8 @@ use std::collections::{HashMap, BTreeSet}; use util::numbers::{Uint, U256}; use util::hash::{Address, H256}; use util::table::*; -use ethcore::transaction::*; -use ethcore::error::{Error, TransactionError}; +use transaction::*; +use error::{Error, TransactionError}; /// Transaction origin #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 38bd873b8..e82f6725b 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -21,6 +21,7 @@ use util::panics::*; use spec::Spec; use error::*; use client::{Client, ClientConfig}; +use miner::Miner; /// Message type for external and internal events #[derive(Clone)] @@ -54,14 +55,14 @@ pub struct ClientService { impl ClientService { /// Start the service in a separate thread. - pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path) -> Result { + pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path, miner: Arc) -> Result { let panic_handler = PanicHandler::new_in_arc(); let mut net_service = try!(NetworkService::start(net_config)); panic_handler.forward_from(&net_service); info!("Starting {}", net_service.host_info()); info!("Configured for {} using {:?} engine", spec.name, spec.engine.name()); - let client = try!(Client::new(config, spec, db_path, net_service.io().channel())); + let client = try!(Client::new(config, spec, db_path, miner, net_service.io().channel())); panic_handler.forward_from(client.deref()); let client_io = Arc::new(ClientIoHandler { client: client.clone() From a845e08bc6ab8f8f8073fd659e731c76b815cb6a Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 20:33:26 +0200 Subject: [PATCH 19/43] rename of the trait --- ethcore/src/client/client.rs | 4 ++-- ethcore/src/client/mod.rs | 2 +- ethcore/src/client/test_client.rs | 4 ++-- ethcore/src/miner/miner.rs | 32 +++++++++++++++---------------- ethcore/src/miner/mod.rs | 24 +++++++++++------------ 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index d23bffa31..6ff56b3ea 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -37,7 +37,7 @@ use filter::Filter; use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, ExtendedBlockChainClient, TraceFilter}; +use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, MiningBlockChainClient, TraceFilter}; use client::Error as ClientError; use env_info::EnvInfo; use executive::{Executive, Executed, TransactOptions, contract_address}; @@ -722,7 +722,7 @@ impl BlockChainClient for Client where V: Verifier { } } -impl ExtendedBlockChainClient for Client where V: Verifier { +impl MiningBlockChainClient for Client where V: Verifier { fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> (Option, HashSet) { let engine = self.engine.deref().deref(); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 67c753d46..209a9f6e2 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -185,7 +185,7 @@ pub trait BlockChainClient : Sync + Send { } /// Extended client interface used for mining -pub trait ExtendedBlockChainClient : BlockChainClient { +pub trait MiningBlockChainClient : BlockChainClient { /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index ad398bbcb..fd392f025 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder}; use util::*; use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; use blockchain::TreeRoute; -use client::{BlockChainClient, ExtendedBlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; +use client::{BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes}; use header::{Header as BlockHeader, BlockNumber}; use filter::Filter; use log_entry::LocalizedLogEntry; @@ -235,7 +235,7 @@ impl TestBlockChainClient { } } -impl ExtendedBlockChainClient for TestBlockChainClient { +impl MiningBlockChainClient for TestBlockChainClient { fn try_seal(&self, block: LockedBlock, _seal: Vec) -> Result { Err(block) } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c4bec7659..5f49a38c9 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -20,7 +20,7 @@ use std::sync::atomic::AtomicBool; use util::*; use util::keys::store::{AccountService, AccountProvider}; use views::{BlockView, HeaderView}; -use client::{ExtendedBlockChainClient, BlockID}; +use client::{MiningBlockChainClient, BlockID}; use block::{ClosedBlock, IsBlock}; use error::*; use client::{Executive, Executed, EnvInfo, TransactOptions}; @@ -104,7 +104,7 @@ impl Miner { /// Prepares new block for sealing including top transactions from queue. #[cfg_attr(feature="dev", allow(match_same_arms))] #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] - fn prepare_sealing(&self, chain: &ExtendedBlockChainClient) { + fn prepare_sealing(&self, chain: &MiningBlockChainClient) { trace!(target: "miner", "prepare_sealing: entering"); let transactions = self.transaction_queue.lock().unwrap().top_transactions(); let mut sealing_work = self.sealing_work.lock().unwrap(); @@ -206,14 +206,14 @@ impl Miner { trace!(target: "miner", "prepare_sealing: leaving (last={:?})", sealing_work.peek_last_ref().map(|b| b.block().fields().header.hash())); } - fn update_gas_limit(&self, chain: &ExtendedBlockChainClient) { + fn update_gas_limit(&self, chain: &MiningBlockChainClient) { 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); } /// Returns true if we had to prepare new pending block - fn enable_and_prepare_sealing(&self, chain: &ExtendedBlockChainClient) -> bool { + fn enable_and_prepare_sealing(&self, chain: &MiningBlockChainClient) -> bool { trace!(target: "miner", "enable_and_prepare_sealing: entering"); let have_work = self.sealing_work.lock().unwrap().peek_last_ref().is_some(); trace!(target: "miner", "enable_and_prepare_sealing: have_work={}", have_work); @@ -237,7 +237,7 @@ const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; impl MinerService for Miner { - fn clear_and_reset(&self, chain: &ExtendedBlockChainClient) { + fn clear_and_reset(&self, chain: &MiningBlockChainClient) { self.transaction_queue.lock().unwrap().clear(); self.update_sealing(chain); } @@ -252,7 +252,7 @@ impl MinerService for Miner { } } - fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result { + fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction) -> Result { let sealing_work = self.sealing_work.lock().unwrap(); match sealing_work.peek_last_ref() { Some(work) => { @@ -288,7 +288,7 @@ impl MinerService for Miner { } } - fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { + fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_balance(address), @@ -296,7 +296,7 @@ impl MinerService for Miner { ) } - fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256 { + fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else( || chain.latest_storage_at(address, position), @@ -304,12 +304,12 @@ impl MinerService for Miner { ) } - fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256 { + fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> U256 { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.latest_nonce(address), |b| b.block().fields().state.nonce(address)) } - fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option { + fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option { let sealing_work = self.sealing_work.lock().unwrap(); sealing_work.peek_last_ref().map_or_else(|| chain.code(address), |b| b.block().fields().state.code(address)) } @@ -376,7 +376,7 @@ impl MinerService for Miner { .collect() } - fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails { let hash = transaction.hash(); @@ -470,7 +470,7 @@ impl MinerService for Miner { self.transaction_queue.lock().unwrap().last_nonce(address) } - fn update_sealing(&self, chain: &ExtendedBlockChainClient) { + fn update_sealing(&self, chain: &MiningBlockChainClient) { if self.sealing_enabled.load(atomic::Ordering::Relaxed) { let current_no = chain.chain_info().best_block_number; let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions(); @@ -490,7 +490,7 @@ impl MinerService for Miner { } } - fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + fn map_sealing_work(&self, chain: &MiningBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { trace!(target: "miner", "map_sealing_work: entering"); self.enable_and_prepare_sealing(chain); trace!(target: "miner", "map_sealing_work: sealing prepared"); @@ -500,7 +500,7 @@ impl MinerService for Miner { ret.map(f) } - fn submit_seal(&self, chain: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { + fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { 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(_) => { @@ -523,8 +523,8 @@ impl MinerService for Miner { } } - fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - fn fetch_transactions(chain: &ExtendedBlockChainClient, hash: &H256) -> Vec { + fn chain_new_blocks(&self, chain: &MiningBlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { + fn fetch_transactions(chain: &MiningBlockChainClient, hash: &H256) -> Vec { let block = chain .block(BlockID::Hash(*hash)) // Client should send message after commit to db and inserting to chain. diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 95453027c..824b1f51b 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -52,7 +52,7 @@ pub use self::external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; use util::{H256, U256, Address, Bytes}; -use client::{ExtendedBlockChainClient, Executed}; +use client::{MiningBlockChainClient, Executed}; use block::ClosedBlock; use receipt::Receipt; use error::{Error, ExecutionError}; @@ -100,7 +100,7 @@ pub trait MinerService : Send + Sync { where T: Fn(&Address) -> AccountDetails, Self: Sized; /// Imports own (node owner) transaction to queue. - fn import_own_transaction(&self, chain: &ExtendedBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails, Self: Sized; @@ -108,20 +108,20 @@ pub trait MinerService : Send + Sync { fn pending_transactions_hashes(&self) -> Vec; /// Removes all transactions from the queue and restart mining operation. - fn clear_and_reset(&self, chain: &ExtendedBlockChainClient); + fn clear_and_reset(&self, chain: &MiningBlockChainClient); /// Called when blocks are imported to chain, updates transactions queue. - fn chain_new_blocks(&self, chain: &ExtendedBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); + fn chain_new_blocks(&self, chain: &MiningBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); /// New chain head event. Restart mining operation. - fn update_sealing(&self, chain: &ExtendedBlockChainClient); + fn update_sealing(&self, chain: &MiningBlockChainClient); /// 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: &ExtendedBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; + fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; /// Get the sealing work package and if `Some`, apply some transform. - fn map_sealing_work(&self, chain: &ExtendedBlockChainClient, f: F) -> Option + fn map_sealing_work(&self, chain: &MiningBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T, Self: Sized; /// Query pending transactions for hash. @@ -146,19 +146,19 @@ pub trait MinerService : Send + Sync { fn sensible_gas_limit(&self) -> U256 { x!(21000) } /// Latest account balance in pending state. - fn balance(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; + fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> U256; /// Call into contract code using pending state. - fn call(&self, chain: &ExtendedBlockChainClient, t: &SignedTransaction) -> Result; + fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction) -> Result; /// Get storage value in pending state. - fn storage_at(&self, chain: &ExtendedBlockChainClient, address: &Address, position: &H256) -> H256; + fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256; /// Get account nonce in pending state. - fn nonce(&self, chain: &ExtendedBlockChainClient, address: &Address) -> U256; + fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> U256; /// Get contract code in pending state. - fn code(&self, chain: &ExtendedBlockChainClient, address: &Address) -> Option; + fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option; } /// Mining status From f5ed31792fcd6daa252e748725c243c106edd55f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 20:54:02 +0200 Subject: [PATCH 20/43] fixed sync with client only --- Cargo.lock | 18 +----------------- Cargo.toml | 3 +-- miner/Cargo.toml | 24 ------------------------ miner/build.rs | 25 ------------------------- rpc/Cargo.toml | 3 +-- sync/Cargo.toml | 3 +-- sync/src/chain.rs | 10 +++------- sync/src/io.rs | 8 ++++---- sync/src/lib.rs | 6 ++---- sync/src/tests/helpers.rs | 1 - 10 files changed, 13 insertions(+), 88 deletions(-) delete mode 100644 miner/Cargo.toml delete mode 100644 miner/build.rs diff --git a/Cargo.lock b/Cargo.lock index cc2a8ef8c..291e90562 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,6 @@ dependencies = [ "ethcore-rpc 1.2.0", "ethcore-signer 1.2.0", "ethcore-util 1.2.0", - "ethminer 1.2.0", "ethsync 1.2.0", "fdlimit 0.1.0", "hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -255,6 +254,7 @@ dependencies = [ "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -334,7 +334,6 @@ dependencies = [ "ethcore-devtools 1.2.0", "ethcore-util 1.2.0", "ethjson 0.1.0", - "ethminer 1.2.0", "ethsync 1.2.0", "json-ipc-server 0.1.0 (git+https://github.com/ethcore/json-ipc-server.git)", "jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -415,20 +414,6 @@ dependencies = [ "syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ethminer" -version = "1.2.0" -dependencies = [ - "clippy 0.0.69 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.2.0", - "ethcore-util 1.2.0", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ethsync" version = "1.2.0" @@ -437,7 +422,6 @@ dependencies = [ "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.2.0", "ethcore-util 1.2.0", - "ethminer 1.2.0", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index d7813468a..ce8823bd2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ clippy = { version = "0.0.69", optional = true} ethcore = { path = "ethcore" } ethcore-util = { path = "util" } ethsync = { path = "sync" } -ethminer = { path = "miner" } ethcore-devtools = { path = "devtools" } ethcore-rpc = { path = "rpc", optional = true } ethcore-signer = { path = "signer", optional = true } @@ -46,7 +45,7 @@ default-features = false default = ["rpc", "dapps", "ethcore-signer"] rpc = ["ethcore-rpc"] dapps = ["ethcore-dapps"] -dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethcore-rpc/dev", "ethminer/dev", +dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethcore-rpc/dev", "ethcore-dapps/dev", "ethcore-signer/dev"] travis-beta = ["ethcore/json-tests"] travis-nightly = ["ethcore/json-tests", "dev"] diff --git a/miner/Cargo.toml b/miner/Cargo.toml deleted file mode 100644 index a3a1c059f..000000000 --- a/miner/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -description = "Ethminer library" -homepage = "http://ethcore.io" -license = "GPL-3.0" -name = "ethminer" -version = "1.2.0" -authors = ["Ethcore "] -build = "build.rs" - -[build-dependencies] -rustc_version = "0.1" - -[dependencies] -ethcore-util = { path = "../util" } -ethcore = { path = "../ethcore" } -log = "0.3" -env_logger = "0.3" -rustc-serialize = "0.3" -rayon = "0.3.1" -clippy = { version = "0.0.69", optional = true} - -[features] -default = [] -dev = ["clippy"] diff --git a/miner/build.rs b/miner/build.rs deleted file mode 100644 index 41b9a1b3e..000000000 --- a/miner/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -// 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_version; - -use rustc_version::{version_meta, Channel}; - -fn main() { - if let Channel::Nightly = version_meta().channel { - println!("cargo:rustc-cfg=nightly"); - } -} diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 61b51cf88..2dbefd7f4 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -18,7 +18,6 @@ ethcore-util = { path = "../util" } ethcore = { path = "../ethcore" } ethash = { path = "../ethash" } ethsync = { path = "../sync" } -ethminer = { path = "../miner" } ethjson = { path = "../json" } ethcore-devtools = { path = "../devtools" } rustc-serialize = "0.3" @@ -34,4 +33,4 @@ syntex = "^0.32.0" [features] default = ["serde_codegen"] nightly = ["serde_macros"] -dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethminer/dev"] +dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev"] diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 7940aaa2d..1b80e23fc 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -11,7 +11,6 @@ authors = ["Ethcore , /// Network ID network_id: U256, - /// Miner - miner: Arc, } type RlpResponseResult = Result, PacketDecodeError>; impl ChainSync { /// Create a new instance of syncing strategy. - pub fn new(config: SyncConfig, miner: Arc, chain: &BlockChainClient) -> ChainSync { + pub fn new(config: SyncConfig, chain: &BlockChainClient) -> ChainSync { let chain = chain.chain_info(); let mut sync = ChainSync { state: SyncState::ChainHead, @@ -265,7 +263,6 @@ impl ChainSync { imported_this_round: None, _max_download_ahead_blocks: max(MAX_HEADERS_TO_REQUEST, config.max_download_ahead_blocks), network_id: config.network_id, - miner: miner, }; sync.reset(); sync @@ -903,7 +900,7 @@ impl ChainSync { nonce: chain.latest_nonce(a), balance: chain.latest_balance(a), }; - let _ = io.chain().import_transactions(transactions, fetch_account); + let _ = io.chain().import_transactions(transactions); Ok(()) } @@ -1288,7 +1285,6 @@ mod tests { use ethcore::header::*; use ethcore::client::*; use ethcore::spec::Spec; - use ethminer::{Miner, MinerService}; fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { let mut header = Header::new(); diff --git a/sync/src/io.rs b/sync/src/io.rs index 49cccd7ca..53a546e1c 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethcore::client::MiningClient; use util::{NetworkContext, PeerId, PacketId,}; use util::error::UtilError; use ethcore::service::SyncMessage; +use ethcore::client::BlockChainClient; /// IO interface for the syning handler. /// Provides peer connection management and an interface to the blockchain client. @@ -32,7 +32,7 @@ pub trait SyncIo { /// Send a packet to a peer. fn send(&mut self, peer_id: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError>; /// Get the blockchain - fn chain(&self) -> &MiningClient; + fn chain(&self) -> &BlockChainClient; /// Returns peer client identifier string fn peer_info(&self, peer_id: PeerId) -> String { peer_id.to_string() @@ -46,12 +46,12 @@ pub trait SyncIo { /// Wraps `NetworkContext` and the blockchain client pub struct NetSyncIo<'s, 'h> where 'h: 's { network: &'s NetworkContext<'h, SyncMessage>, - chain: &'s MiningClient + chain: &'s BlockChainClient } impl<'s, 'h> NetSyncIo<'s, 'h> { /// Creates a new instance from the `NetworkContext` and the blockchain client reference. - pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s MiningClient) -> NetSyncIo<'s, 'h> { + pub fn new(network: &'s NetworkContext<'h, SyncMessage>, chain: &'s BlockChainClient) -> NetSyncIo<'s, 'h> { NetSyncIo { network: network, chain: chain, diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 6b72a24fc..9fa6501a2 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -55,7 +55,6 @@ extern crate log; #[macro_use] extern crate ethcore_util as util; extern crate ethcore; -extern crate ethminer; extern crate env_logger; extern crate time; extern crate rand; @@ -69,7 +68,6 @@ use util::TimerToken; use util::{U256, ONE_U256}; use ethcore::client::Client; use ethcore::service::SyncMessage; -use ethminer::Miner; use io::NetSyncIo; use chain::ChainSync; @@ -115,8 +113,8 @@ pub use self::chain::{SyncStatus, SyncState}; impl EthSync { /// Creates and register protocol with the network service - pub fn register(service: &mut NetworkService, config: SyncConfig, chain: Arc, miner: Arc) -> Arc { - let sync = ChainSync::new(config, miner, chain.deref()); + pub fn register(service: &mut NetworkService, config: SyncConfig, chain: Arc) -> Arc { + let sync = ChainSync::new(config, chain.deref()); let sync = Arc::new(EthSync { chain: chain, sync: RwLock::new(sync), diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 70ddb78db..c2e0e2d04 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -19,7 +19,6 @@ use ethcore::client::{TestBlockChainClient, BlockChainClient}; use ethcore::spec::Spec; use io::SyncIo; use chain::ChainSync; -use ethminer::Miner; use ::SyncConfig; pub struct TestIo<'p> { From 10d914d6c663a0f9bb9b2d517bebee7ae3115832 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 20:58:33 +0200 Subject: [PATCH 21/43] restored chain_new_blocks --- sync/src/chain.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 42d425af9..1270f775f 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1272,6 +1272,18 @@ impl ChainSync { pub fn maintain_sync(&mut self, io: &mut SyncIo) { self.check_resume(io); } + + /// 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 io.is_chain_queue_empty() { + // Propagate latests blocks + self.propagate_latest_blocks(io); + } + if !invalid.is_empty() { + trace!(target: "sync", "Bad blocks in the queue, restarting"); + self.restart_on_bad_block(io); + } + } } #[cfg(test)] From ec7af964ab75f6c6e12a1449684bf0b5fa233e3a Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 21:01:47 +0200 Subject: [PATCH 22/43] correct map macro invocation --- ethcore/src/pod_account.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 96642d1f8..65146296a 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -171,7 +171,7 @@ mod test { 3.into() => Diff::new(3.into(), 0.into()), 4.into() => Diff::new(4.into(), 0.into()), 7.into() => Diff::new(0.into(), 7.into()), - 9.into() => Diff::new(0.into(), 9.into()), + 9.into() => Diff::new(0.into(), 9.into()) ], })); } From 495e7feb62807ec90f3548cfae16d606453d05fc Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:13:32 +0200 Subject: [PATCH 23/43] dispatching message return --- sync/src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 9fa6501a2..863ad6382 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -164,5 +164,12 @@ impl NetworkProtocolHandler for EthSync { } fn message(&self, io: &NetworkContext, message: &SyncMessage) { + match *message { + 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); + }, + _ => {/* Ignore other messages */}, + } } } From 2a08fb8fe3ffaff3de41aa7427ba5c38c1559232 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:17:46 +0200 Subject: [PATCH 24/43] and conditional dispatch --- ethcore/src/client/client.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6ff56b3ea..4df72f1fd 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -338,7 +338,17 @@ impl Client where V: Verifier { { if !imported_blocks.is_empty() && self.block_queue.queue_info().is_empty() { let (enacted, retracted) = self.calculate_enacted_retracted(import_results); - self.miner.chain_new_blocks(self, &imported_blocks, &invalid_blocks, &enacted, &retracted); + + if self.queue_info().is_empty() { + self.miner.chain_new_blocks(self, &imported_blocks, &invalid_blocks, &enacted, &retracted); + } + + io.send(NetworkIoMessage::User(SyncMessage::NewChainBlocks { + imported: imported_blocks, + invalid: invalid_blocks, + enacted: enacted, + retracted: retracted, + })).unwrap(); } } From 4146e1f02b45f548834a4e3507420ec18b725046 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 21:18:54 +0200 Subject: [PATCH 25/43] add empty rule to map macros --- util/src/common.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/util/src/common.rs b/util/src/common.rs index 2eb2ea017..0e0cd7757 100644 --- a/util/src/common.rs +++ b/util/src/common.rs @@ -26,6 +26,7 @@ pub use sha3::*; #[macro_export] macro_rules! hash_map { + () => { HashMap::new() }; ( $( $x:expr => $y:expr ),* ) => {{ let mut x = HashMap::new(); $( @@ -37,6 +38,7 @@ macro_rules! hash_map { #[macro_export] macro_rules! hash_map_into { + () => { HashMap::new() }; ( $( $x:expr => $y:expr ),* ) => {{ let mut x = HashMap::new(); $( @@ -48,6 +50,7 @@ macro_rules! hash_map_into { #[macro_export] macro_rules! map { + () => { BTreeMap::new() }; ( $( $x:expr => $y:expr ),* ) => {{ let mut x = BTreeMap::new(); $( @@ -59,6 +62,7 @@ macro_rules! map { #[macro_export] macro_rules! map_into { + () => { BTreeMap::new() }; ( $( $x:expr => $y:expr ),* ) => {{ let mut x = BTreeMap::new(); $( From 77cef765183491e69d53210258824c43e22bf5d0 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:31:42 +0200 Subject: [PATCH 26/43] rpc bindings resolved --- parity/dapps.rs | 2 +- parity/main.rs | 2 +- parity/rpc.rs | 2 +- parity/signer.rs | 2 +- rpc/src/lib.rs | 1 - rpc/src/v1/impls/eth.rs | 16 +++++++------- rpc/src/v1/impls/ethcore.rs | 2 +- rpc/src/v1/impls/mod.rs | 10 ++++----- rpc/src/v1/impls/personal.rs | 10 ++++----- rpc/src/v1/tests/eth.rs | 6 +++--- rpc/src/v1/tests/helpers/miner_service.rs | 26 +++++++++++------------ rpc/src/v1/tests/mocked/eth.rs | 2 +- rpc/src/v1/tests/mocked/ethcore.rs | 2 +- sync/src/chain.rs | 2 +- sync/src/tests/helpers.rs | 2 +- 15 files changed, 43 insertions(+), 44 deletions(-) diff --git a/parity/dapps.rs b/parity/dapps.rs index 986e3dd07..7909bb9bc 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -19,7 +19,7 @@ use std::str::FromStr; use std::net::SocketAddr; use ethcore::client::Client; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use util::RotatingLogger; use util::panics::PanicHandler; use util::keys::store::AccountService; diff --git a/parity/main.rs b/parity/main.rs index 7f16d28a5..539797fb9 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -85,7 +85,7 @@ use ethcore::error::{Error, ImportError}; use ethcore::service::ClientService; use ethcore::spec::Spec; use ethsync::EthSync; -use ethminer::{Miner, MinerService, ExternalMiner}; +use ethcore::miner::{Miner, MinerService, ExternalMiner}; use daemonize::Daemonize; use migration::migrate; use informant::Informant; diff --git a/parity/rpc.rs b/parity/rpc.rs index 60766263b..0d8d7562e 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -21,7 +21,7 @@ use std::sync::Arc; use std::net::SocketAddr; use ethcore::client::Client; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use util::RotatingLogger; use util::panics::PanicHandler; use util::keys::store::AccountService; diff --git a/parity/signer.rs b/parity/signer.rs index 5e3339bcc..3f6197e3a 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use ethcore::client::Client; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use util::keys::store::AccountService; use util::panics::{PanicHandler, ForwardPanic}; use die::*; diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 24d58819c..80c92388a 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -29,7 +29,6 @@ extern crate jsonrpc_http_server; extern crate ethcore_util as util; extern crate ethcore; extern crate ethsync; -extern crate ethminer; extern crate transient_hashmap; extern crate json_ipc_server as ipc; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a57fc333c..ad15fb2f7 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -22,13 +22,13 @@ use std::collections::HashSet; use std::sync::{Arc, Weak, Mutex}; use std::ops::Deref; use ethsync::{SyncProvider, SyncState}; -use ethminer::{MinerService, ExternalMinerService}; +use ethcore::miner::{MinerService, ExternalMinerService}; use jsonrpc_core::*; use util::numbers::*; use util::sha3::*; use util::rlp::{encode, decode, UntrustedRlp, View}; use util::keys::store::AccountProvider; -use ethcore::client::{BlockChainClient, BlockID, TransactionID, UncleID}; +use ethcore::client::{MiningBlockChainClient, BlockID, TransactionID, UncleID}; use ethcore::block::IsBlock; use ethcore::views::*; use ethcore::ethereum::Ethash; @@ -44,7 +44,7 @@ use serde; /// Eth rpc implementation. pub struct EthClient where - C: BlockChainClient, + C: MiningBlockChainClient, S: SyncProvider, A: AccountProvider, M: MinerService, @@ -59,7 +59,7 @@ pub struct EthClient where } impl EthClient where - C: BlockChainClient, + C: MiningBlockChainClient, S: SyncProvider, A: AccountProvider, M: MinerService, @@ -224,7 +224,7 @@ fn make_unsupported_err() -> Error { } impl Eth for EthClient where - C: BlockChainClient + 'static, + C: MiningBlockChainClient + 'static, S: SyncProvider + 'static, A: AccountProvider + 'static, M: MinerService + 'static, @@ -566,7 +566,7 @@ impl Eth for EthClient where /// Eth filter rpc implementation. pub struct EthFilterClient where - C: BlockChainClient, + C: MiningBlockChainClient, M: MinerService { client: Weak, @@ -575,7 +575,7 @@ pub struct EthFilterClient where } impl EthFilterClient where - C: BlockChainClient, + C: MiningBlockChainClient, M: MinerService { /// Creates new Eth filter client. @@ -589,7 +589,7 @@ impl EthFilterClient where } impl EthFilter for EthFilterClient where - C: BlockChainClient + 'static, + C: MiningBlockChainClient + 'static, M: MinerService + 'static { fn new_filter(&self, params: Params) -> Result { diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index f5d6f1fda..e649e37f4 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -22,7 +22,7 @@ use std::sync::{Arc, Weak}; use std::ops::Deref; use std::collections::BTreeMap; use jsonrpc_core::*; -use ethminer::MinerService; +use ethcore::miner::MinerService; use v1::traits::Ethcore; use v1::types::Bytes; diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 7ee8b8b8a..2f1c07ff6 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -47,8 +47,8 @@ pub use self::rpc::RpcClient; use v1::types::TransactionRequest; use std::sync::Weak; -use ethminer::{AccountDetails, MinerService}; -use ethcore::client::BlockChainClient; +use ethcore::miner::{AccountDetails, MinerService}; +use ethcore::client::MiningBlockChainClient; use ethcore::transaction::{Action, SignedTransaction, Transaction}; use util::numbers::*; use util::rlp::encode; @@ -56,7 +56,7 @@ use util::bytes::ToPretty; use jsonrpc_core::{Error, to_value, Value}; fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result - where C: BlockChainClient, M: MinerService { + where C: MiningBlockChainClient, M: MinerService { let hash = signed_transaction.hash(); let import = miner.import_own_transaction(client, signed_transaction, |a: &Address| { @@ -70,7 +70,7 @@ fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedT } fn sign_and_dispatch(client: &Weak, miner: &Weak, request: TransactionRequest, secret: H256) -> Result - where C: BlockChainClient, M: MinerService { + where C: MiningBlockChainClient, M: MinerService { let client = take_weak!(client); let miner = take_weak!(miner); @@ -92,4 +92,4 @@ fn sign_and_dispatch(client: &Weak, miner: &Weak, request: Transacti trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); dispatch_transaction(&*client, &*miner, signed_transaction) -} \ No newline at end of file +} diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 19e902996..074bb8c77 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -22,19 +22,19 @@ use v1::types::TransactionRequest; use v1::impls::sign_and_dispatch; use util::keys::store::*; use util::numbers::*; -use ethcore::client::BlockChainClient; -use ethminer::MinerService; +use ethcore::client::MiningBlockChainClient; +use ethcore::miner::MinerService; /// Account management (personal) rpc implementation. pub struct PersonalClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { accounts: Weak, client: Weak, miner: Weak, } impl PersonalClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { /// Creates new PersonalClient pub fn new(store: &Arc, client: &Arc, miner: &Arc) -> Self { PersonalClient { @@ -46,7 +46,7 @@ impl PersonalClient } impl Personal for PersonalClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { fn accounts(&self, _: Params) -> Result { let store = take_weak!(self.accounts); match store.accounts() { diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 80a856aca..7f5d5e333 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,12 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; -use ethcore::client::{BlockChainClient, Client, ClientConfig}; +use ethcore::client::{MiningBlockChainClient, Client, ClientConfig}; use ethcore::spec::Genesis; use ethcore::block::Block; use ethcore::ethereum; use ethcore::transaction::{Transaction, Action}; -use ethminer::{MinerService, ExternalMiner}; +use ethcore::miner::{MinerService, ExternalMiner}; use devtools::RandomTempPath; use util::io::IoChannel; use util::hash::Address; @@ -38,7 +38,7 @@ use v1::impls::EthClient; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; struct EthTester { - _client: Arc, + _client: Arc, _miner: Arc, accounts: Arc, handler: IoHandler, diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 600f88508..a53ca3a08 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -19,11 +19,11 @@ use util::{Address, H256, Bytes, U256, FixedHash, Uint}; use util::standard::*; use ethcore::error::{Error, ExecutionError}; -use ethcore::client::{BlockChainClient, Executed}; +use ethcore::client::{MiningBlockChainClient, Executed}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::transaction::SignedTransaction; use ethcore::receipt::Receipt; -use ethminer::{MinerService, MinerStatus, AccountDetails, TransactionImportResult}; +use ethcore::miner::{MinerService, MinerStatus, AccountDetails, TransactionImportResult}; /// Test miner service. pub struct TestMinerService { @@ -132,7 +132,7 @@ impl MinerService for TestMinerService { } /// Imports transactions to transaction queue. - fn import_own_transaction(&self, chain: &BlockChainClient, transaction: SignedTransaction, _fetch_account: T) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction, _fetch_account: T) -> Result where T: Fn(&Address) -> AccountDetails { @@ -154,21 +154,21 @@ impl MinerService for TestMinerService { } /// Removes all transactions from the queue and restart mining operation. - fn clear_and_reset(&self, _chain: &BlockChainClient) { + fn clear_and_reset(&self, _chain: &MiningBlockChainClient) { unimplemented!(); } /// Called when blocks are imported to chain, updates transactions queue. - fn chain_new_blocks(&self, _chain: &BlockChainClient, _imported: &[H256], _invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) { + fn chain_new_blocks(&self, _chain: &MiningBlockChainClient, _imported: &[H256], _invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) { unimplemented!(); } /// New chain head event. Restart mining operation. - fn update_sealing(&self, _chain: &BlockChainClient) { + fn update_sealing(&self, _chain: &MiningBlockChainClient) { unimplemented!(); } - fn map_sealing_work(&self, _chain: &BlockChainClient, _f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + fn map_sealing_work(&self, _chain: &MiningBlockChainClient, _f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { unimplemented!(); } @@ -194,29 +194,29 @@ impl MinerService for TestMinerService { /// 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> { + fn submit_seal(&self, _chain: &MiningBlockChainClient, _pow_hash: H256, _seal: Vec) -> Result<(), Error> { unimplemented!(); } - fn balance(&self, _chain: &BlockChainClient, address: &Address) -> U256 { + fn balance(&self, _chain: &MiningBlockChainClient, address: &Address) -> U256 { self.latest_closed_block.lock().unwrap().as_ref().map_or_else(U256::zero, |b| b.block().fields().state.balance(address).clone()) } - fn call(&self, _chain: &BlockChainClient, _t: &SignedTransaction) -> Result { + fn call(&self, _chain: &MiningBlockChainClient, _t: &SignedTransaction) -> Result { unimplemented!(); } - fn storage_at(&self, _chain: &BlockChainClient, address: &Address, position: &H256) -> H256 { + fn storage_at(&self, _chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256 { self.latest_closed_block.lock().unwrap().as_ref().map_or_else(H256::default, |b| b.block().fields().state.storage_at(address, position).clone()) } - fn nonce(&self, _chain: &BlockChainClient, address: &Address) -> U256 { + fn nonce(&self, _chain: &MiningBlockChainClient, address: &Address) -> U256 { // we assume all transactions are in a pending block, ignoring the // reality of gas limits. self.last_nonce(address).unwrap_or(U256::zero()) } - fn code(&self, _chain: &BlockChainClient, address: &Address) -> Option { + fn code(&self, _chain: &MiningBlockChainClient, address: &Address) -> Option { self.latest_closed_block.lock().unwrap().as_ref().map_or(None, |b| b.block().fields().state.code(address).clone()) } diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index c51d6d7da..579f57e6c 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -25,7 +25,7 @@ use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed, Transaction use ethcore::log_entry::{LocalizedLogEntry, LogEntry}; use ethcore::receipt::LocalizedReceipt; use ethcore::transaction::{Transaction, Action}; -use ethminer::{ExternalMiner, MinerService}; +use ethcore::miner::{ExternalMiner, MinerService}; use ethsync::SyncState; use v1::{Eth, EthClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs index cc822daef..d51545d86 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/ethcore.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use std::str::FromStr; use jsonrpc_core::IoHandler; use v1::{Ethcore, EthcoreClient}; -use ethminer::MinerService; +use ethcore::miner::MinerService; use v1::tests::helpers::TestMinerService; use util::numbers::*; use rustc_serialize::hex::FromHex; diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 1270f775f..dc397d77d 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1470,7 +1470,7 @@ mod tests { } fn dummy_sync_with_peer(peer_latest_hash: H256, client: &BlockChainClient) -> ChainSync { - let mut sync = ChainSync::new(SyncConfig::default(), Miner::new(false, Spec::new_test()), client); + let mut sync = ChainSync::new(SyncConfig::default(), client); sync.peers.insert(0, PeerInfo { protocol_version: 0, diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index c2e0e2d04..7cde0b54c 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -92,7 +92,7 @@ impl TestNet { }; for _ in 0..n { let chain = TestBlockChainClient::new(); - let sync = ChainSync::new(SyncConfig::default(), Miner::new(false, Spec::new_test()), &chain); + let sync = ChainSync::new(SyncConfig::default(), &chain); net.peers.push(TestPeer { sync: sync, chain: chain, From bbb858b3862856bf1d18b559b263075be0149d89 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 21:38:05 +0200 Subject: [PATCH 27/43] address small syntax breakages --- ethcore/src/state.rs | 24 ++++++++++++------------ ethcore/src/state_diff.rs | 8 ++++---- ethcore/src/tests/helpers.rs | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index 6e0e4f2f6..c099b17a5 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -389,7 +389,7 @@ fn should_apply_create_transaction() { data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555").unwrap(), }.sign(&"".sha3()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -450,7 +450,7 @@ fn should_trace_failed_create_transaction() { data: FromHex::from_hex("5b600056").unwrap(), }.sign(&"".sha3()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -489,7 +489,7 @@ fn should_trace_call_transaction() { }.sign(&"".sha3()); state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -531,7 +531,7 @@ fn should_trace_basic_call_transaction() { data: vec![], }.sign(&"".sha3()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -745,7 +745,7 @@ fn should_trace_failed_call_transaction() { }.sign(&"".sha3()); state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -788,7 +788,7 @@ fn should_trace_call_with_subcall_transaction() { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -845,7 +845,7 @@ fn should_trace_call_with_basic_subcall_transaction() { }.sign(&"".sha3()); state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -899,7 +899,7 @@ fn should_not_trace_call_with_invalid_basic_subcall_transaction() { }.sign(&"".sha3()); state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds. - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -943,7 +943,7 @@ fn should_trace_failed_subcall_transaction() { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -999,7 +999,7 @@ fn should_trace_call_with_subcall_with_subcall_transaction() { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()); state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { @@ -1032,7 +1032,7 @@ fn should_trace_call_with_subcall_with_subcall_transaction() { depth: 2, action: trace::Action::Call(trace::Call { from: 0xb.into(), - to: 0xb.into(), + to: 0xc.into(), value: 0.into(), gas: 78868.into(), input: vec![], @@ -1072,7 +1072,7 @@ fn should_trace_failed_subcall_with_subcall_transaction() { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()); state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()); - state.add_balance(t.sender().as_ref().unwrap(), &100.into()); + state.add_balance(t.sender().as_ref().unwrap(), &(100.into())); let vm_factory = Default::default(); let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { diff --git a/ethcore/src/state_diff.rs b/ethcore/src/state_diff.rs index 1c1975e70..c362d96d1 100644 --- a/ethcore/src/state_diff.rs +++ b/ethcore/src/state_diff.rs @@ -83,7 +83,7 @@ mod test { let a = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); let b = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]), - 2.into() => PodAccount::new(69.into(), 0.into(),, vec![], map![]) + 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); assert_eq!(StateDiff::diff_pod(&a, &b), StateDiff(map![ 2.into() => AccountDiff{ @@ -107,11 +107,11 @@ mod test { fn change_with_unchanged() { let a = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]), - 2.into() => PodAccount::new(69.into(), 0.into(),, vec![], map![]) + 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); let b = PodState::from(map![ - 1.into() => PodAccount::new(69.into(), 1.into(),, vec![], map![]), - 2.into() => PodAccount::new(69.into(), 0.into(),, vec![], map![]) + 1.into() => PodAccount::new(69.into(), 1.into(), vec![], map![]), + 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); assert_eq!(StateDiff::diff_pod(&a, &b), StateDiff(map![ 1.into() => AccountDiff{ diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 6a370e49f..22282ccdd 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -99,7 +99,7 @@ pub fn create_test_block(header: &Header) -> Bytes { fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header { let mut header = Header::new(); header.gas_limit = 0.into(); - header.difficulty = order * 100.into(); + header.difficulty = (order * 100).into(); header.timestamp = (order * 10) as u64; header.number = order as u64; header.parent_hash = parent_hash; From c33b1caf21d67ce3f5b56b2894ec000ff10a79e7 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:38:07 +0200 Subject: [PATCH 28/43] executable all issues resolved --- parity/main.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 539797fb9..0575d80ea 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -27,7 +27,6 @@ extern crate rustc_serialize; extern crate ethcore_util as util; extern crate ethcore; extern crate ethsync; -extern crate ethminer; #[macro_use] extern crate log as rlog; extern crate env_logger; @@ -173,14 +172,6 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Secret Store let account_service = Arc::new(conf.account_service()); - // Build client - let mut 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(); - // Miner let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone()); miner.set_author(conf.author()); @@ -189,11 +180,19 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) miner.set_minimal_gas_price(conf.gas_price()); miner.set_transactions_limit(conf.args.flag_tx_limit); + // Build client + let mut service = ClientService::start( + client_config, spec, net_settings, Path::new(&conf.path()), miner.clone() + ).unwrap_or_else(|e| die_with_error("Client", e)); + + panic_handler.forward_from(&service); + let client = service.client(); + let external_miner = Arc::new(ExternalMiner::default()); let network_settings = Arc::new(conf.network_settings()); // Sync - let sync = EthSync::register(service.network(), sync_config, client.clone(), miner.clone()); + let sync = EthSync::register(service.network(), sync_config, client.clone()); let dependencies = Arc::new(rpc::Dependencies { panic_handler: panic_handler.clone(), @@ -295,7 +294,7 @@ fn execute_export(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()) + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); @@ -366,7 +365,7 @@ fn execute_import(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()) + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); From 99573286074b3daebf1690fb30a9397c495e27ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 31 May 2016 21:39:11 +0200 Subject: [PATCH 29/43] DENY frames from other origins to prevent clickjacking --- dapps/src/apps.rs | 6 ++++-- dapps/src/page/mod.rs | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/dapps/src/apps.rs b/dapps/src/apps.rs index 559282584..28f1979bf 100644 --- a/dapps/src/apps.rs +++ b/dapps/src/apps.rs @@ -38,11 +38,13 @@ pub fn utils() -> Box { pub fn all_endpoints() -> Endpoints { let mut pages = Endpoints::new(); - pages.insert("proxy".to_owned(), ProxyPac::boxed()); + pages.insert("proxy".into(), ProxyPac::boxed()); + pages.insert("home".into(), Box::new( + PageEndpoint::new_safe_to_embed(parity_dapps_builtins::App::default()) + )); insert::(&mut pages, "status"); insert::(&mut pages, "parity"); - insert::(&mut pages, "home"); wallet_page(&mut pages); daodapp_page(&mut pages); diff --git a/dapps/src/page/mod.rs b/dapps/src/page/mod.rs index 71989bca7..c7bfd83ec 100644 --- a/dapps/src/page/mod.rs +++ b/dapps/src/page/mod.rs @@ -30,6 +30,8 @@ pub struct PageEndpoint { pub app: Arc, /// Prefix to strip from the path (when `None` deducted from `app_id`) pub prefix: Option, + /// Safe to be loaded in frame by other origin. (use wisely!) + safe_to_embed: bool, } impl PageEndpoint { @@ -37,6 +39,7 @@ impl PageEndpoint { PageEndpoint { app: Arc::new(app), prefix: None, + safe_to_embed: false, } } @@ -44,6 +47,18 @@ impl PageEndpoint { PageEndpoint { app: Arc::new(app), prefix: Some(prefix), + safe_to_embed: false, + } + } + + /// Creates new `PageEndpoint` which can be safely used in iframe + /// even from different origin. It might be dangerous (clickjacking). + /// Use wisely! + pub fn new_safe_to_embed(app: T) -> Self { + PageEndpoint { + app: Arc::new(app), + prefix: None, + safe_to_embed: true, } } } @@ -61,6 +76,7 @@ impl Endpoint for PageEndpoint { path: path, file: None, write_pos: 0, + safe_to_embed: self.safe_to_embed, }) } } @@ -83,6 +99,7 @@ struct PageHandler { path: EndpointPath, file: Option, write_pos: usize, + safe_to_embed: bool, } impl PageHandler { @@ -128,6 +145,9 @@ impl server::Handler for PageHandler { if let Some(f) = self.file.as_ref().and_then(|f| self.app.file(f)) { res.set_status(StatusCode::Ok); res.headers_mut().set(header::ContentType(f.content_type.parse().unwrap())); + if !self.safe_to_embed { + res.headers_mut().set_raw("X-Frame-Options", vec![b"SAMEORIGIN".to_vec()]); + } Next::write() } else { res.set_status(StatusCode::NotFound); From dad61bb7cfb26f252a56236dcfb1368ffc64d676 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 21:40:26 +0200 Subject: [PATCH 30/43] test and travis fix for absent crate --- .travis.yml | 1 - test.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0f0766ee4..995b765c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,6 @@ after_success: | $KCOV_CMD target/debug/deps/ethcore_rpc-* && $KCOV_CMD target/debug/deps/ethcore_dapps-* && $KCOV_CMD target/debug/deps/ethcore_signer-* && - $KCOV_CMD target/debug/deps/ethminer-* && $KCOV_CMD target/debug/deps/ethjson-* && $KCOV_CMD target/debug/parity-* && [ $TRAVIS_BRANCH = master ] && diff --git a/test.sh b/test.sh index e70718afc..d89740aba 100755 --- a/test.sh +++ b/test.sh @@ -10,5 +10,4 @@ cargo test --features ethcore/json-tests $1 \ -p ethcore-signer \ -p ethcore-dapps \ -p parity \ - -p ethminer \ -p bigint From 5fd4b9d7bd74e641779864b05ce007bf23da008f Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 31 May 2016 21:50:25 +0200 Subject: [PATCH 31/43] formatting fix --- rpc/src/v1/tests/eth.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 0c159ceb2..30815b8a8 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -102,8 +102,13 @@ impl EthTester { let miner_service = miner_service(spec_provider(), account_provider.clone()); let external_miner = Arc::new(ExternalMiner::default()); - let eth_client = EthClient::new(&client, &sync_provider, &account_provider, - &miner_service, &external_miner); + let eth_client = EthClient::new( + &client, + &sync_provider, + &account_provider, + &miner_service, + &external_miner + ); let handler = IoHandler::new(); let delegate = eth_client.to_delegate(); From ae1bcd6a5b7880e10dae42b00c90300e3d9de6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 31 May 2016 21:50:34 +0200 Subject: [PATCH 32/43] Disabling ethcore APIs for RPC and IPC --- dapps/src/page/mod.rs | 1 + parity/cli.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dapps/src/page/mod.rs b/dapps/src/page/mod.rs index c7bfd83ec..819988310 100644 --- a/dapps/src/page/mod.rs +++ b/dapps/src/page/mod.rs @@ -212,6 +212,7 @@ fn should_extract_path_with_appid() { }, file: None, write_pos: 0, + safe_to_embed: true, }; // when diff --git a/parity/cli.rs b/parity/cli.rs index 60b622bf7..95b77a00d 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -76,13 +76,13 @@ API and Console Options: interface. APIS is a comma-delimited list of API name. Possible name are web3, eth, net, personal, ethcore, traces. - [default: web3,eth,net,personal,ethcore,traces]. + [default: web3,eth,net,personal,traces]. --ipc-off Disable JSON-RPC over IPC service. --ipc-path PATH Specify custom path for JSON-RPC over IPC service [default: $HOME/.parity/jsonrpc.ipc]. --ipc-apis APIS Specify custom API set available via JSON-RPC over - IPC [default: web3,eth,net,personal,ethcore]. + IPC [default: web3,eth,net,personal,traces]. --dapps-off Disable the Dapps server (e.g. status page). --dapps-port PORT Specify the port portion of the Dapps server From 67421fc69e3053ec5ed0c1d5bdb02711b50084b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 31 May 2016 21:56:41 +0200 Subject: [PATCH 33/43] Adding explanatory comment for safe_to_embed --- dapps/src/apps.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dapps/src/apps.rs b/dapps/src/apps.rs index 28f1979bf..130b20fb9 100644 --- a/dapps/src/apps.rs +++ b/dapps/src/apps.rs @@ -40,6 +40,9 @@ pub fn all_endpoints() -> Endpoints { let mut pages = Endpoints::new(); pages.insert("proxy".into(), ProxyPac::boxed()); + // Home page needs to be safe embed + // because we use Cross-Origin LocalStorage. + // TODO [ToDr] Account naming should be moved to parity. pages.insert("home".into(), Box::new( PageEndpoint::new_safe_to_embed(parity_dapps_builtins::App::default()) )); From d45a676dc0db78cb2ef3a85a2b7b3e647d950929 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 31 May 2016 22:24:32 +0200 Subject: [PATCH 34/43] all tests fixed --- ethcore/src/client/test_client.rs | 4 ++++ ethcore/src/json_tests/chain.rs | 3 ++- ethcore/src/miner/miner.rs | 8 ++++---- ethcore/src/miner/transaction_queue.rs | 4 ++-- ethcore/src/service.rs | 4 +++- ethcore/src/tests/client.rs | 9 +++++---- ethcore/src/tests/helpers.rs | 5 +++-- rpc/src/v1/tests/eth.rs | 6 +++--- sync/src/chain.rs | 15 ++++++++------- sync/src/tests/chain.rs | 2 +- sync/src/tests/helpers.rs | 4 ++-- 11 files changed, 37 insertions(+), 27 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index fd392f025..fa91aab4a 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -28,6 +28,7 @@ use receipt::{Receipt, LocalizedReceipt}; use blockchain::extras::BlockReceipts; use error::{ImportResult}; use evm::Factory as EvmFactory; +use miner::Miner; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock, LockedBlock}; @@ -64,6 +65,8 @@ pub struct TestBlockChainClient { pub receipts: RwLock>, /// Block queue size. pub queue_size: AtomicUsize, + /// Miner + pub miner: Arc, } #[derive(Clone)] @@ -102,6 +105,7 @@ impl TestBlockChainClient { execution_result: RwLock::new(None), receipts: RwLock::new(HashMap::new()), queue_size: AtomicUsize::new(0), + miner: Arc::new(Miner::default()), }; client.add_blocks(1, EachBlockWith::Nothing); // add genesis block client.genesis_hash = client.last_hash.read().unwrap().clone(); diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index a1154f6a9..53052d8dc 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -22,6 +22,7 @@ use tests::helpers::*; use devtools::*; use spec::Genesis; use ethjson; +use miner::Miner; pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { init_log(); @@ -53,7 +54,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { let temp = RandomTempPath::new(); { - let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), spec, temp.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); for b in &blockchain.blocks_rlp() { if Block::is_good(&b) { let _ = client.import_block(b.clone()); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 5f49a38c9..66ede48bf 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -585,11 +585,11 @@ impl MinerService for Miner { #[cfg(test)] mod tests { - use MinerService; - use super::{Miner}; + use super::super::MinerService; + use super::Miner; use util::*; - use ethcore::client::{TestBlockChainClient, EachBlockWith}; - use ethcore::block::*; + use client::{TestBlockChainClient, EachBlockWith}; + use block::*; // TODO [ToDr] To uncomment` when TestBlockChainClient can actually return a ClosedBlock. #[ignore] diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 1b88a7a11..bf1512bde 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -778,8 +778,8 @@ mod test { extern crate rustc_serialize; use util::table::*; use util::*; - use ethcore::transaction::*; - use ethcore::error::{Error, TransactionError}; + use transaction::*; + use error::{Error, TransactionError}; use super::*; use super::{TransactionSet, TransactionOrder, VerifiedTransaction}; diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index e82f6725b..13f1c9f74 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -142,12 +142,14 @@ mod tests { use util::network::*; use devtools::*; use client::ClientConfig; + use std::sync::Arc; + use miner::Miner; #[test] fn it_can_be_started() { let spec = get_test_spec(); let temp_path = RandomTempPath::new(); - let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path()); + let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path(), Arc::new(Miner::default())); assert!(service.is_ok()); } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index d734b0b47..84bfb716f 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -14,16 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use client::{BlockChainClient, Client, ClientConfig, BlockID}; +use client::{BlockChainClient, MiningBlockChainClient, Client, ClientConfig, BlockID}; use block::IsBlock; use tests::helpers::*; use common::*; use devtools::*; +use miner::Miner; #[test] fn imports_from_empty() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); client.import_verified_blocks(&IoChannel::disconnected()); client.flush_queue(); } @@ -41,7 +42,7 @@ fn returns_state_root_basic() { #[test] fn imports_good_block() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let good_block = get_good_dummy_block(); if let Err(_) = client.import_block(good_block) { panic!("error importing block being good by definition"); @@ -56,7 +57,7 @@ fn imports_good_block() { #[test] fn query_none_block() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header(BlockID::Number(188)); assert!(non_existant.is_none()); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 7262da9e8..cc841d7f4 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -23,6 +23,7 @@ use evm::Schedule; use engine::*; use ethereum; use devtools::*; +use miner::Miner; #[cfg(feature = "json-tests")] pub enum ChainEra { @@ -139,7 +140,7 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTrans pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let test_spec = get_test_spec(); let test_engine = &test_spec.engine; let state_root = test_spec.genesis_header().state_root; @@ -205,7 +206,7 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult> { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); for block in &blocks { if let Err(_) = client.import_block(block.clone()) { panic!("panic importing block which is well-formed"); diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 7f5d5e333..eb50ea5d1 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,12 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; -use ethcore::client::{MiningBlockChainClient, Client, ClientConfig}; +use ethcore::client::{MiningBlockChainClient, BlockChainClient, Client, ClientConfig}; use ethcore::spec::Genesis; use ethcore::block::Block; use ethcore::ethereum; use ethcore::transaction::{Transaction, Action}; -use ethcore::miner::{MinerService, ExternalMiner}; +use ethcore::miner::{MinerService, ExternalMiner, Miner}; use devtools::RandomTempPath; use util::io::IoChannel; use util::hash::Address; @@ -195,7 +195,7 @@ fn chain_harness(chain: BlockChain, mut cb: F) -> U assert!(spec.is_state_root_valid()); let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), spec, dir.as_path(), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), spec, dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let sync_provider = sync_provider(); let miner_service = miner_service(); let account_provider = account_provider(); diff --git a/sync/src/chain.rs b/sync/src/chain.rs index dc397d77d..e3e773c26 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -101,7 +101,7 @@ use io::SyncIo; use time; use super::SyncConfig; use blocks::BlockCollection; -use ethcore::miner::{AccountDetails, TransactionImportResult}; +use ethcore::miner::{AccountDetails, TransactionImportResult, MinerService}; known_heap_size!(0, PeerInfo); @@ -1297,6 +1297,7 @@ mod tests { use ethcore::header::*; use ethcore::client::*; use ethcore::spec::Spec; + use ethcore::miner::MinerService; fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { let mut header = Header::new(); @@ -1702,8 +1703,8 @@ mod tests { let mut queue = VecDeque::new(); let mut io = TestIo::new(&mut client, &mut queue, None); 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); + assert_eq!(io.chain.miner.status().transactions_in_future_queue, 0); + assert_eq!(io.chain.miner.status().transactions_in_pending_queue, 1); } // We need to update nonce status (because we say that the block has been imported) for h in &[good_blocks[0]] { @@ -1718,7 +1719,7 @@ mod tests { } // then - let status = sync.miner.status(); + let status = client.miner.status(); assert_eq!(status.transactions_in_pending_queue, 1); assert_eq!(status.transactions_in_future_queue, 0); } @@ -1740,12 +1741,12 @@ mod tests { // when 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); + assert_eq!(io.chain.miner.status().transactions_in_future_queue, 0); + assert_eq!(io.chain.miner.status().transactions_in_pending_queue, 0); sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks); // then - let status = sync.miner.status(); + let status = io.chain.miner.status(); assert_eq!(status.transactions_in_pending_queue, 0); assert_eq!(status.transactions_in_future_queue, 0); } diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index 463771ffe..09e83e358 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{MiningClient, BlockID, EachBlockWith}; +use ethcore::client::{BlockChainClient, BlockID, EachBlockWith}; use chain::{SyncState}; use super::helpers::*; diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 7cde0b54c..9ca0065ee 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{TestBlockChainClient, BlockChainClient}; +use ethcore::client::{TestBlockChainClient, MiningBlockChainClient, BlockChainClient}; use ethcore::spec::Spec; use io::SyncIo; use chain::ChainSync; @@ -62,7 +62,7 @@ impl<'p> SyncIo for TestIo<'p> { Ok(()) } - fn chain(&self) -> &MiningClient { + fn chain(&self) -> &BlockChainClient { self.chain } } From cee31f9e8da4d51b1bbf3bac714f86fe7575cf82 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 03:19:20 +0200 Subject: [PATCH 35/43] fix travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 995b765c2..230e7862f 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 -p ethjson -p ethcore-dapps -p ethcore-signer" + - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethjson -p ethcore-dapps -p ethcore-signer" - 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 db749dc564bda58f07c71879db34b76b2ad0a2b1 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 12:44:11 +0200 Subject: [PATCH 36/43] fix remaining tests & doctest --- ethcore/src/client/test_client.rs | 13 ++++++++++--- sync/src/chain.rs | 9 ++------- sync/src/lib.rs | 7 +++---- sync/src/tests/helpers.rs | 3 +-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index fa91aab4a..83799c78f 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -28,7 +28,7 @@ use receipt::{Receipt, LocalizedReceipt}; use blockchain::extras::BlockReceipts; use error::{ImportResult}; use evm::Factory as EvmFactory; -use miner::Miner; +use miner::{Miner, MinerService}; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock, LockedBlock}; @@ -488,10 +488,17 @@ impl BlockChainClient for TestBlockChainClient { } fn import_transactions(&self, transactions: Vec) -> Vec> { - unimplemented!(); + let nonces = self.nonces.read().unwrap(); + let balances = self.balances.read().unwrap(); + let fetch_account = |a: &Address| AccountDetails { + nonce: nonces[a], + balance: balances[a], + }; + + self.miner.import_transactions(transactions, &fetch_account) } fn all_transactions(&self) -> Vec { - unimplemented!(); + self.miner.all_transactions() } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index e3e773c26..38d3a53f9 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -101,7 +101,6 @@ use io::SyncIo; use time; use super::SyncConfig; use blocks::BlockCollection; -use ethcore::miner::{AccountDetails, TransactionImportResult, MinerService}; known_heap_size!(0, PeerInfo); @@ -895,11 +894,6 @@ impl ChainSync { let tx: SignedTransaction = try!(r.val_at(i)); transactions.push(tx); } - let chain = io.chain(); - let fetch_account = |a: &Address| AccountDetails { - nonce: chain.latest_nonce(a), - balance: chain.latest_balance(a), - }; let _ = io.chain().import_transactions(transactions); Ok(()) } @@ -1296,7 +1290,6 @@ mod tests { use ethcore::views::BlockView; use ethcore::header::*; use ethcore::client::*; - use ethcore::spec::Spec; use ethcore::miner::MinerService; fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { @@ -1702,6 +1695,7 @@ mod tests { { let mut queue = VecDeque::new(); let mut io = TestIo::new(&mut client, &mut queue, None); + io.chain.miner.chain_new_blocks(io.chain, &[], &[], &[], &good_blocks); sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); assert_eq!(io.chain.miner.status().transactions_in_future_queue, 0); assert_eq!(io.chain.miner.status().transactions_in_pending_queue, 1); @@ -1715,6 +1709,7 @@ mod tests { { let mut queue = VecDeque::new(); let mut io = TestIo::new(&mut client, &mut queue, None); + io.chain.miner.chain_new_blocks(io.chain, &[], &[], &good_blocks, &retracted_blocks); sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks); } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 863ad6382..9f69bb7da 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -32,21 +32,20 @@ //! extern crate ethcore_util as util; //! extern crate ethcore; //! extern crate ethsync; -//! extern crate ethminer; //! use std::env; //! use std::sync::Arc; //! use util::network::{NetworkService, NetworkConfiguration}; //! use ethcore::client::{Client, ClientConfig}; //! use ethsync::{EthSync, SyncConfig}; -//! use ethminer::Miner; //! use ethcore::ethereum; +//! use ethcore::miner::Miner; //! //! fn main() { //! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); //! let dir = env::temp_dir(); -//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel()).unwrap(); +//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap(); //! let miner = Miner::new(false, ethereum::new_frontier()); -//! EthSync::register(&mut service, SyncConfig::default(), client, miner); +//! EthSync::register(&mut service, SyncConfig::default(), client); //! } //! ``` diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 9ca0065ee..a9163b52e 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -15,8 +15,7 @@ // along with Parity. If not, see . use util::*; -use ethcore::client::{TestBlockChainClient, MiningBlockChainClient, BlockChainClient}; -use ethcore::spec::Spec; +use ethcore::client::{TestBlockChainClient, BlockChainClient}; use io::SyncIo; use chain::ChainSync; use ::SyncConfig; From 985d412c483bf993b76b22b5628a7169f62c4e76 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 13:03:26 +0200 Subject: [PATCH 37/43] fix merges again --- rpc/src/v1/tests/eth.rs | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 8cfc13191..4dc22df56 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -19,12 +19,8 @@ use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; -<<<<<<< HEAD use ethcore::client::{MiningBlockChainClient, BlockChainClient, Client, ClientConfig}; -use ethcore::spec::Genesis; -======= use ethcore::ids::BlockID; -use ethcore::client::{Client, BlockChainClient, ClientConfig}; use ethcore::spec::{Genesis, Spec}; use ethcore::block::Block; use ethcore::views::BlockView; @@ -73,7 +69,7 @@ fn make_spec(chain: &BlockChain) -> Spec { } struct EthTester { - _client: Arc, + client: Arc, _miner: Arc, accounts: Arc, handler: IoHandler, @@ -101,10 +97,10 @@ impl EthTester { where F: Fn() -> Spec { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), spec_provider(), dir.as_path(), IoChannel::disconnected()).unwrap(); - let sync_provider = sync_provider(); let account_provider = account_provider(); let miner_service = miner_service(spec_provider(), account_provider.clone()); + let client = Client::new(ClientConfig::default(), spec_provider(), dir.as_path(), miner_service.clone(), IoChannel::disconnected()).unwrap(); + let sync_provider = sync_provider(); let external_miner = Arc::new(ExternalMiner::default()); let eth_client = EthClient::new( @@ -347,25 +343,10 @@ fn verify_transaction_counts(name: String, chain: BlockChain) { let (req, res) = by_hash(hash, count, &mut id); assert_eq!(tester.handler.handle_request(&req), Some(res)); -<<<<<<< HEAD - let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), spec, dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); - let sync_provider = sync_provider(); - let miner_service = miner_service(); - let account_provider = account_provider(); - let external_miner = Arc::new(ExternalMiner::default()); - - for b in &chain.blocks_rlp() { - if Block::is_good(&b) { - let _ = client.import_block(b.clone()); - client.flush_queue(); - client.import_verified_blocks(&IoChannel::disconnected()); -======= // uncles can share block numbers, so skip them. if tester.client.block_hash(BlockID::Number(number)) == Some(hash) { let (req, res) = by_number(number, count, &mut id); assert_eq!(tester.handler.handle_request(&req), Some(res)); ->>>>>>> master } } } From ae572cb8f5be2b52ec3b5839605de6158637ab0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 1 Jun 2016 13:25:20 +0200 Subject: [PATCH 38/43] Using ordered hashmap to keep the order of dapps on home screen --- dapps/src/endpoint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dapps/src/endpoint.rs b/dapps/src/endpoint.rs index 60708f549..28ca6ea11 100644 --- a/dapps/src/endpoint.rs +++ b/dapps/src/endpoint.rs @@ -21,7 +21,7 @@ use hyper::{header, server, Decoder, Encoder, Next}; use hyper::net::HttpStream; use std::io::Write; -use std::collections::HashMap; +use std::collections::BTreeMap; #[derive(Debug, PartialEq, Default, Clone)] pub struct EndpointPath { @@ -45,7 +45,7 @@ pub trait Endpoint : Send + Sync { fn to_handler(&self, path: EndpointPath) -> Box>; } -pub type Endpoints = HashMap>; +pub type Endpoints = BTreeMap>; pub type Handler = server::Handler; pub struct ContentHandler { From 1ef4db82e80bf6f7ed2459b8ce1036922c6370af Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 14:50:06 +0200 Subject: [PATCH 39/43] doctest fixes --- ethcore/src/client/mod.rs | 2 +- ethcore/src/miner/mod.rs | 3 +-- ethcore/src/miner/transaction_queue.rs | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 209a9f6e2..3f64cb620 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -46,7 +46,7 @@ use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; use evm::Factory as EvmFactory; -use miner::{TransactionImportResult, AccountDetails}; +use miner::{TransactionImportResult}; use error::Error as EthError; /// Blockchain database client. Owns and manages a blockchain and a block queue. diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 0159d7fd6..60b680f7a 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -28,8 +28,7 @@ //! extern crate ethcore; //! use std::env; //! use util::network::{NetworkService, NetworkConfiguration}; -//! use client::{Client, ClientConfig}; -//! use ethereum; +//! use ethcore::client::{Client, ClientConfig}; //! use ethcore::miner::{Miner, MinerService}; //! //! fn main() { diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index bf1512bde..8f34d78d1 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -26,13 +26,12 @@ //! ```rust //! extern crate ethcore_util as util; //! extern crate ethcore; -//! extern crate ethminer; //! extern crate rustc_serialize; //! //! use util::crypto::KeyPair; //! use util::hash::Address; //! use util::numbers::{Uint, U256}; -//! use ethminer::{TransactionQueue, AccountDetails, TransactionOrigin}; +//! use ethcore::miner::{TransactionQueue, AccountDetails, TransactionOrigin}; //! use ethcore::transaction::*; //! use rustc_serialize::hex::FromHex; //! From 99e26b8480a2678954daa69852aa966d33f8e498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 1 Jun 2016 19:37:34 +0200 Subject: [PATCH 40/43] Simple signing queue, confirmation APIs exposed in signer WebSockets. (#1182) * Splitting methods requiring signing into separate trait * Single place where RPC apis are created. * Separating eth_filter * Separating eth_signing * Stubs for Personal Signer methods * Test for EthSigningQueueClient * TransactionConfirmation API * Exposing PersonalSigner API * Defining ApiSets dependent on context * Removing types * Fixing default impl * Fixing un-mocked tests * Update signing_queue.rs [ci skip] * Removing unused import [ci skip] --- Cargo.lock | 5 - dapps/src/lib.rs | 13 +- parity/dapps.rs | 24 +- parity/main.rs | 27 +-- parity/rpc.rs | 79 ++----- parity/rpc_apis.rs | 168 ++++++++++++++ parity/signer.rs | 18 +- rpc/src/lib.rs | 19 +- rpc/src/v1/helpers/mod.rs | 2 + rpc/src/v1/helpers/signing_queue.rs | 108 +++++++++ rpc/src/v1/impls/eth.rs | 246 ++------------------- rpc/src/v1/impls/eth_filter.rs | 214 ++++++++++++++++++ rpc/src/v1/impls/eth_signing.rs | 111 ++++++++++ rpc/src/v1/impls/mod.rs | 10 +- rpc/src/v1/impls/personal.rs | 2 +- rpc/src/v1/impls/personal_signer.rs | 93 ++++++++ rpc/src/v1/mod.rs | 3 +- rpc/src/v1/tests/eth.rs | 15 +- rpc/src/v1/tests/mocked/eth.rs | 5 +- rpc/src/v1/tests/mocked/eth_signing.rs | 75 +++++++ rpc/src/v1/tests/mocked/mod.rs | 2 + rpc/src/v1/tests/mocked/personal.rs | 2 +- rpc/src/v1/tests/mocked/personal_signer.rs | 169 ++++++++++++++ rpc/src/v1/traits/eth.rs | 25 ++- rpc/src/v1/traits/mod.rs | 6 +- rpc/src/v1/traits/personal.rs | 23 ++ rpc/src/v1/types/mod.rs.in | 2 +- rpc/src/v1/types/transaction_request.rs | 41 +++- signer/Cargo.toml | 8 - signer/build.rs | 27 --- signer/src/lib.rs | 8 - signer/src/signing_queue.rs | 74 ------- signer/src/types/mod.rs | 23 -- signer/src/types/mod.rs.in | 25 --- signer/src/ws_server/mod.rs | 12 +- 35 files changed, 1140 insertions(+), 544 deletions(-) create mode 100644 parity/rpc_apis.rs create mode 100644 rpc/src/v1/helpers/signing_queue.rs create mode 100644 rpc/src/v1/impls/eth_filter.rs create mode 100644 rpc/src/v1/impls/eth_signing.rs create mode 100644 rpc/src/v1/impls/personal_signer.rs create mode 100644 rpc/src/v1/tests/mocked/eth_signing.rs create mode 100644 rpc/src/v1/tests/mocked/personal_signer.rs delete mode 100644 signer/src/signing_queue.rs delete mode 100644 signer/src/types/mod.rs delete mode 100644 signer/src/types/mod.rs.in diff --git a/Cargo.lock b/Cargo.lock index cc2a8ef8c..c81020f66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,12 +358,7 @@ dependencies = [ "ethcore-util 1.2.0", "jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (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.4 (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.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 27c215108..231e7b080 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -52,6 +52,7 @@ extern crate serde_json; extern crate jsonrpc_core; extern crate jsonrpc_http_server; extern crate parity_dapps; +extern crate ethcore_rpc; mod endpoint; mod apps; @@ -66,6 +67,7 @@ use std::net::SocketAddr; use std::collections::HashMap; use jsonrpc_core::{IoHandler, IoDelegate}; use router::auth::{Authorization, NoAuth, HttpBasicAuth}; +use ethcore_rpc::Extendable; static DAPPS_DOMAIN : &'static str = ".parity"; @@ -74,6 +76,12 @@ pub struct ServerBuilder { handler: Arc, } +impl Extendable for ServerBuilder { + fn add_delegate(&self, delegate: IoDelegate) { + self.handler.add_delegate(delegate); + } +} + impl ServerBuilder { /// Construct new dapps server pub fn new() -> Self { @@ -82,11 +90,6 @@ impl ServerBuilder { } } - /// Add io delegate. - pub fn add_delegate(&self, delegate: IoDelegate) where D: Send + Sync + 'static { - self.handler.add_delegate(delegate); - } - /// Asynchronously start server with no authentication, /// returns result with `Server` handle on success or an error. pub fn start_unsecure_http(&self, addr: &SocketAddr) -> Result { diff --git a/parity/dapps.rs b/parity/dapps.rs index 986e3dd07..91742d9e3 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -17,14 +17,9 @@ use std::sync::Arc; use std::str::FromStr; use std::net::SocketAddr; -use ethcore::client::Client; -use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; -use util::RotatingLogger; use util::panics::PanicHandler; -use util::keys::store::AccountService; -use util::network_settings::NetworkSettings; use die::*; +use rpc_apis; #[cfg(feature = "dapps")] pub use ethcore_dapps::Server as WebappServer; @@ -41,13 +36,7 @@ pub struct Configuration { pub struct Dependencies { pub panic_handler: Arc, - pub client: Arc, - pub sync: Arc, - pub secret_store: Arc, - pub miner: Arc, - pub external_miner: Arc, - pub logger: Arc, - pub settings: Arc, + pub apis: Arc, } pub fn new(configuration: Configuration, deps: Dependencies) -> Option { @@ -92,17 +81,10 @@ pub fn setup_dapps_server( url: &SocketAddr, auth: Option<(String, String)> ) -> WebappServer { - use ethcore_rpc::v1::*; use ethcore_dapps as dapps; let server = dapps::ServerBuilder::new(); - server.add_delegate(Web3Client::new().to_delegate()); - server.add_delegate(NetClient::new(&deps.sync).to_delegate()); - server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate()); - server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); - server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner).to_delegate()); - server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()); - + let server = rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::UnsafeContext); let start_result = match auth { None => { server.start_unsecure_http(url) diff --git a/parity/main.rs b/parity/main.rs index 7f16d28a5..cae6aa614 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -67,6 +67,7 @@ mod cli; mod configuration; mod migration; mod signer; +mod rpc_apis; use std::io::{Write, Read, BufReader, BufRead}; use std::ops::Deref; @@ -195,8 +196,9 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Sync let sync = EthSync::register(service.network(), sync_config, client.clone(), miner.clone()); - let dependencies = Arc::new(rpc::Dependencies { - panic_handler: panic_handler.clone(), + let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies { + signer_enabled: conf.args.flag_signer, + signer_queue: Arc::new(rpc_apis::ConfirmationsQueue::default()), client: client.clone(), sync: sync.clone(), secret_store: account_service.clone(), @@ -206,6 +208,11 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) settings: network_settings.clone(), }); + let dependencies = rpc::Dependencies { + panic_handler: panic_handler.clone(), + apis: deps_for_rpc_apis.clone(), + }; + // Setup http rpc let rpc_server = rpc::new_http(rpc::HttpConfiguration { enabled: network_settings.rpc_enabled, @@ -227,26 +234,16 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) pass: conf.args.flag_dapps_pass.clone(), }, dapps::Dependencies { panic_handler: panic_handler.clone(), - client: client.clone(), - sync: sync.clone(), - secret_store: account_service.clone(), - miner: miner.clone(), - external_miner: external_miner.clone(), - logger: logger.clone(), - settings: network_settings.clone(), + apis: deps_for_rpc_apis.clone(), }); // Set up a signer let signer_server = signer::start(signer::Configuration { - enabled: conf.args.flag_signer, + enabled: deps_for_rpc_apis.signer_enabled, port: conf.args.flag_signer_port, }, signer::Dependencies { panic_handler: panic_handler.clone(), - client: client.clone(), - sync: sync.clone(), - secret_store: account_service.clone(), - miner: miner.clone(), - external_miner: external_miner.clone(), + apis: deps_for_rpc_apis.clone(), }); // Register IO handler diff --git a/parity/rpc.rs b/parity/rpc.rs index 60766263b..66f504408 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -15,19 +15,13 @@ // along with Parity. If not, see . -use std::collections::BTreeMap; use std::str::FromStr; use std::sync::Arc; use std::net::SocketAddr; -use ethcore::client::Client; -use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; -use util::RotatingLogger; use util::panics::PanicHandler; -use util::keys::store::AccountService; -use util::network_settings::NetworkSettings; use die::*; use jsonipc; +use rpc_apis; #[cfg(feature = "rpc")] pub use ethcore_rpc::Server as RpcServer; @@ -52,16 +46,10 @@ pub struct IpcConfiguration { pub struct Dependencies { pub panic_handler: Arc, - pub client: Arc, - pub sync: Arc, - pub secret_store: Arc, - pub miner: Arc, - pub external_miner: Arc, - pub logger: Arc, - pub settings: Arc, + pub apis: Arc, } -pub fn new_http(conf: HttpConfiguration, deps: &Arc) -> Option { +pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Option { if !conf.enabled { return None; } @@ -78,58 +66,23 @@ pub fn new_http(conf: HttpConfiguration, deps: &Arc) -> Option) -> Option { +pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Option { if !conf.enabled { return None; } let apis = conf.apis.split(',').collect(); Some(setup_ipc_rpc_server(deps, &conf.socket_addr, apis)) } -fn setup_rpc_server(apis: Vec<&str>, deps: &Arc) -> Server { - use ethcore_rpc::v1::*; - +fn setup_rpc_server(apis: Vec<&str>, deps: &Dependencies) -> Server { + let apis = rpc_apis::from_str(apis); let server = Server::new(); - let mut modules = BTreeMap::new(); - for api in apis.into_iter() { - match api { - "web3" => { - modules.insert("web3".to_owned(), "1.0".to_owned()); - server.add_delegate(Web3Client::new().to_delegate()); - }, - "net" => { - modules.insert("net".to_owned(), "1.0".to_owned()); - server.add_delegate(NetClient::new(&deps.sync).to_delegate()); - }, - "eth" => { - modules.insert("eth".to_owned(), "1.0".to_owned()); - server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate()); - server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); - }, - "personal" => { - modules.insert("personal".to_owned(), "1.0".to_owned()); - server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner).to_delegate()) - }, - "ethcore" => { - modules.insert("ethcore".to_owned(), "1.0".to_owned()); - server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) - }, - "traces" => { - modules.insert("traces".to_owned(), "1.0".to_owned()); - server.add_delegate(TracesClient::new(&deps.client).to_delegate()) - }, - _ => { - die!("{}: Invalid API name to be enabled.", api); - }, - } - } - server.add_delegate(RpcClient::new(modules).to_delegate()); - server + rpc_apis::setup_rpc(server, deps.apis.clone(), rpc_apis::ApiSet::List(apis)) } #[cfg(not(feature = "rpc"))] pub fn setup_http_rpc_server( - _deps: Dependencies, + _deps: &Dependencies, _url: &SocketAddr, - _cors_domain: Option, + _cors_domain: Vec, _apis: Vec<&str>, ) -> ! { die!("Your Parity version has been compiled without JSON-RPC support.") @@ -137,27 +90,31 @@ pub fn setup_http_rpc_server( #[cfg(feature = "rpc")] pub fn setup_http_rpc_server( - dependencies: &Arc, + dependencies: &Dependencies, url: &SocketAddr, cors_domains: Vec, apis: Vec<&str>, ) -> RpcServer { let server = setup_rpc_server(apis, dependencies); let start_result = server.start_http(url, cors_domains); - let deps = dependencies.clone(); + let ph = dependencies.panic_handler.clone(); match start_result { Err(RpcServerError::IoError(err)) => die_with_io_error("RPC", err), Err(e) => die!("RPC: {:?}", e), Ok(server) => { server.set_panic_handler(move || { - deps.panic_handler.notify_all("Panic in RPC thread.".to_owned()); + ph.notify_all("Panic in RPC thread.".to_owned()); }); server }, } } - -pub fn setup_ipc_rpc_server(dependencies: &Arc, addr: &str, apis: Vec<&str>) -> jsonipc::Server { +#[cfg(not(feature = "rpc"))] +pub fn setup_ipc_rpc_server(_dependencies: &Dependencies, _addr: &str, _apis: Vec<&str>) -> ! { + die!("Your Parity version has been compiled without JSON-RPC support.") +} +#[cfg(feature = "rpc")] +pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: Vec<&str>) -> jsonipc::Server { let server = setup_rpc_server(apis, dependencies); match server.start_ipc(addr) { Err(jsonipc::Error::Io(io_error)) => die_with_io_error("RPC", io_error), diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs new file mode 100644 index 000000000..c73a70fee --- /dev/null +++ b/parity/rpc_apis.rs @@ -0,0 +1,168 @@ +// 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 std::collections::BTreeMap; +use std::str::FromStr; +use std::sync::Arc; + +use die::*; +use ethsync::EthSync; +use ethminer::{Miner, ExternalMiner}; +use ethcore::client::Client; +use util::RotatingLogger; +use util::keys::store::AccountService; +use util::network_settings::NetworkSettings; + +#[cfg(feature="rpc")] +pub use ethcore_rpc::ConfirmationsQueue; +#[cfg(not(feature="rpc"))] +#[derive(Default)] +pub struct ConfirmationsQueue; + +#[cfg(feature="rpc")] +use ethcore_rpc::Extendable; + +pub enum Api { + Web3, + Net, + Eth, + Personal, + Ethcore, + Traces, + Rpc, +} + +pub enum ApiError { + UnknownApi(String) +} + +pub enum ApiSet { + SafeContext, + UnsafeContext, + List(Vec), +} + +impl FromStr for Api { + type Err = ApiError; + + fn from_str(s: &str) -> Result { + use self::Api::*; + + match s { + "web3" => Ok(Web3), + "net" => Ok(Net), + "eth" => Ok(Eth), + "personal" => Ok(Personal), + "ethcore" => Ok(Ethcore), + "traces" => Ok(Traces), + "rpc" => Ok(Rpc), + e => Err(ApiError::UnknownApi(e.into())), + } + } +} + +pub struct Dependencies { + pub signer_enabled: bool, + pub signer_queue: Arc, + pub client: Arc, + pub sync: Arc, + pub secret_store: Arc, + pub miner: Arc, + pub external_miner: Arc, + pub logger: Arc, + pub settings: Arc, +} + +fn to_modules(apis: &[Api]) -> BTreeMap { + let mut modules = BTreeMap::new(); + for api in apis { + let (name, version) = match *api { + Api::Web3 => ("web3", "1.0"), + Api::Net => ("net", "1.0"), + Api::Eth => ("eth", "1.0"), + Api::Personal => ("personal", "1.0"), + Api::Ethcore => ("ethcore", "1.0"), + Api::Traces => ("traces", "1.0"), + Api::Rpc => ("rpc", "1.0"), + }; + modules.insert(name.into(), version.into()); + } + modules +} + +pub fn from_str(apis: Vec<&str>) -> Vec { + apis.into_iter() + .map(Api::from_str) + .collect::, ApiError>>() + .unwrap_or_else(|e| match e { + ApiError::UnknownApi(s) => die!("Unknown RPC API specified: {}", s), + }) +} + +fn list_apis(apis: ApiSet, signer_enabled: bool) -> Vec { + match apis { + ApiSet::List(apis) => apis, + ApiSet::UnsafeContext if signer_enabled => { + vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc] + } + _ => { + vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Ethcore, Api::Traces, Api::Rpc] + } + } +} + +pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet) -> T { + use ethcore_rpc::v1::*; + + let apis = list_apis(apis, deps.signer_enabled); + for api in &apis { + match *api { + Api::Web3 => { + server.add_delegate(Web3Client::new().to_delegate()); + }, + Api::Net => { + server.add_delegate(NetClient::new(&deps.sync).to_delegate()); + }, + Api::Eth => { + server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate()); + server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); + + if deps.signer_enabled { + server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue).to_delegate()); + } else { + server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate()); + } + }, + Api::Personal => { + server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner).to_delegate()); + if deps.signer_enabled { + server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_queue).to_delegate()); + } + }, + Api::Ethcore => { + server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) + }, + Api::Traces => { + server.add_delegate(TracesClient::new(&deps.client).to_delegate()) + }, + Api::Rpc => { + let modules = to_modules(&apis); + server.add_delegate(RpcClient::new(modules).to_delegate()); + } + } + } + server +} diff --git a/parity/signer.rs b/parity/signer.rs index 5e3339bcc..d549b89cb 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -15,12 +15,9 @@ // along with Parity. If not, see . use std::sync::Arc; -use ethcore::client::Client; -use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; -use util::keys::store::AccountService; use util::panics::{PanicHandler, ForwardPanic}; use die::*; +use rpc_apis; #[cfg(feature = "ethcore-signer")] use ethcore_signer as signer; @@ -36,11 +33,7 @@ pub struct Configuration { pub struct Dependencies { pub panic_handler: Arc, - pub client: Arc, - pub sync: Arc, - pub secret_store: Arc, - pub miner: Arc, - pub external_miner: Arc, + pub apis: Arc, } pub fn start(conf: Configuration, deps: Dependencies) -> Option { @@ -58,13 +51,8 @@ fn do_start(conf: Configuration, deps: Dependencies) -> SignerServer { }); let start_result = { - use ethcore_rpc::v1::*; let server = signer::ServerBuilder::new(); - server.add_delegate(Web3Client::new().to_delegate()); - server.add_delegate(NetClient::new(&deps.sync).to_delegate()); - server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate()); - server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); - server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner).to_delegate()); + let server = rpc_apis::setup_rpc(server, deps.apis, rpc_apis::ApiSet::SafeContext); server.start(addr) }; diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 24d58819c..607bcf4bd 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -44,12 +44,26 @@ use self::jsonrpc_core::{IoHandler, IoDelegate}; pub use jsonrpc_http_server::{Server, RpcServerError}; pub mod v1; +pub use v1::{SigningQueue, ConfirmationsQueue}; + +/// An object that can be extended with `IoDelegates` +pub trait Extendable { + /// Add `Delegate` to this object. + fn add_delegate(&self, delegate: IoDelegate); +} /// Http server. pub struct RpcServer { handler: Arc, } +impl Extendable for RpcServer { + /// Add io delegate. + fn add_delegate(&self, delegate: IoDelegate) { + self.handler.add_delegate(delegate); + } +} + impl RpcServer { /// Construct new http server object. pub fn new() -> RpcServer { @@ -58,11 +72,6 @@ impl RpcServer { } } - /// Add io delegate. - pub fn add_delegate(&self, delegate: IoDelegate) where D: Send + Sync + 'static { - self.handler.add_delegate(delegate); - } - /// Start http server asynchronously and returns result with `Server` handle on success or an error. pub fn start_http(&self, addr: &SocketAddr, cors_domains: Vec) -> Result { let cors_domains = cors_domains.into_iter() diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index b1a5c05ba..2acf98bf2 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -16,6 +16,8 @@ mod poll_manager; mod poll_filter; +mod signing_queue; pub use self::poll_manager::PollManager; pub use self::poll_filter::PollFilter; +pub use self::signing_queue::{ConfirmationsQueue, SigningQueue}; diff --git a/rpc/src/v1/helpers/signing_queue.rs b/rpc/src/v1/helpers/signing_queue.rs new file mode 100644 index 000000000..eee4328ee --- /dev/null +++ b/rpc/src/v1/helpers/signing_queue.rs @@ -0,0 +1,108 @@ +// 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 std::sync::Mutex; +use std::collections::HashMap; +use v1::types::{TransactionRequest, TransactionConfirmation}; +use util::U256; + +/// A queue of transactions awaiting to be confirmed and signed. +pub trait SigningQueue: Send + Sync { + /// Add new request to the queue. + fn add_request(&self, transaction: TransactionRequest) -> U256; + + /// Remove request from the queue. + fn remove_request(&self, id: U256) -> Option; + + /// Return copy of all the requests in the queue. + fn requests(&self) -> Vec; +} + +/// Queue for all unconfirmed transactions. +pub struct ConfirmationsQueue { + id: Mutex, + queue: Mutex>, +} + +impl Default for ConfirmationsQueue { + fn default() -> Self { + ConfirmationsQueue { + id: Mutex::new(U256::from(0)), + queue: Mutex::new(HashMap::new()), + } + } +} + +impl SigningQueue for ConfirmationsQueue { + fn add_request(&self, transaction: TransactionRequest) -> U256 { + // Increment id + let id = { + let mut last_id = self.id.lock().unwrap(); + *last_id = *last_id + U256::from(1); + *last_id + }; + let mut queue = self.queue.lock().unwrap(); + queue.insert(id, TransactionConfirmation { + id: id, + transaction: transaction, + }); + id + } + + fn remove_request(&self, id: U256) -> Option { + self.queue.lock().unwrap().remove(&id) + } + + fn requests(&self) -> Vec { + let queue = self.queue.lock().unwrap(); + queue.values().cloned().collect() + } +} + + +#[cfg(test)] +mod test { + use util::hash::Address; + use util::numbers::U256; + use v1::types::TransactionRequest; + use super::*; + + #[test] + fn should_work_for_hashset() { + // given + let queue = ConfirmationsQueue::default(); + + let request = TransactionRequest { + from: Address::from(1), + to: Some(Address::from(2)), + gas_price: None, + gas: None, + value: Some(U256::from(10_000_000)), + data: None, + nonce: None, + }; + + // when + queue.add_request(request.clone()); + let all = queue.requests(); + + // then + assert_eq!(all.len(), 1); + let el = all.get(0).unwrap(); + assert_eq!(el.id, U256::from(1)); + assert_eq!(el.transaction, request); + } +} diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a57fc333c..e0225c7e9 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -18,7 +18,6 @@ extern crate ethash; -use std::collections::HashSet; use std::sync::{Arc, Weak, Mutex}; use std::ops::Deref; use ethsync::{SyncProvider, SyncState}; @@ -36,10 +35,9 @@ use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Act use ethcore::log_entry::LogEntry; use ethcore::filter::Filter as EthcoreFilter; use self::ethash::SeedHashCompute; -use v1::traits::{Eth, EthFilter}; -use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, TransactionRequest, CallRequest, OptionalValue, Index, Filter, Log, Receipt}; -use v1::helpers::{PollFilter, PollManager}; -use v1::impls::{dispatch_transaction, sign_and_dispatch}; +use v1::traits::Eth; +use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, OptionalValue, Index, Filter, Log, Receipt}; +use v1::impls::dispatch_transaction; use serde; /// Eth rpc implementation. @@ -170,6 +168,25 @@ impl EthClient where } } +pub fn pending_logs(miner: &M, filter: &EthcoreFilter) -> Vec where M: MinerService { + let receipts = miner.pending_receipts(); + + let pending_logs = receipts.into_iter() + .flat_map(|(hash, r)| r.logs.into_iter().map(|l| (hash.clone(), l)).collect::>()) + .collect::>(); + + let result = pending_logs.into_iter() + .filter(|pair| filter.matches(&pair.1)) + .map(|pair| { + let mut log = Log::from(pair.1); + log.transaction_hash = Some(pair.0); + log + }) + .collect(); + + result +} + const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6. fn params_len(params: &Params) -> usize { @@ -193,25 +210,6 @@ fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNum } } -fn pending_logs(miner: &M, filter: &EthcoreFilter) -> Vec where M: MinerService { - let receipts = miner.pending_receipts(); - - let pending_logs = receipts.into_iter() - .flat_map(|(hash, r)| r.logs.into_iter().map(|l| (hash.clone(), l)).collect::>()) - .collect::>(); - - let result = pending_logs.into_iter() - .filter(|pair| filter.matches(&pair.1)) - .map(|pair| { - let mut log = Log::from(pair.1); - log.transaction_hash = Some(pair.0); - log - }) - .collect(); - - result -} - // must be in range [-32099, -32000] const UNSUPPORTED_REQUEST_CODE: i64 = -32000; @@ -496,23 +494,6 @@ impl Eth for EthClient where }) } - fn sign(&self, params: Params) -> Result { - from_params::<(Address, H256)>(params).and_then(|(addr, msg)| { - to_value(&take_weak!(self.accounts).sign(&addr, &msg).unwrap_or(H520::zero())) - }) - } - - fn send_transaction(&self, params: Params) -> Result { - from_params::<(TransactionRequest, )>(params) - .and_then(|(request, )| { - let accounts = take_weak!(self.accounts); - match accounts.account_secret(&request.from) { - Ok(secret) => sign_and_dispatch(&self.client, &self.miner, request, secret), - Err(_) => to_value(&H256::zero()) - } - }) - } - fn send_raw_transaction(&self, params: Params) -> Result { from_params::<(Bytes, )>(params) .and_then(|(raw_transaction, )| { @@ -563,186 +544,3 @@ impl Eth for EthClient where rpc_unimplemented!() } } - -/// Eth filter rpc implementation. -pub struct EthFilterClient where - C: BlockChainClient, - M: MinerService { - - client: Weak, - miner: Weak, - polls: Mutex>, -} - -impl EthFilterClient where - C: BlockChainClient, - M: MinerService { - - /// Creates new Eth filter client. - pub fn new(client: &Arc, miner: &Arc) -> Self { - EthFilterClient { - client: Arc::downgrade(client), - miner: Arc::downgrade(miner), - polls: Mutex::new(PollManager::new()), - } - } -} - -impl EthFilter for EthFilterClient where - C: BlockChainClient + 'static, - M: MinerService + 'static { - - fn new_filter(&self, params: Params) -> Result { - from_params::<(Filter,)>(params) - .and_then(|(filter,)| { - let mut polls = self.polls.lock().unwrap(); - let block_number = take_weak!(self.client).chain_info().best_block_number; - let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter)); - to_value(&U256::from(id)) - }) - } - - fn new_block_filter(&self, params: Params) -> Result { - match params { - Params::None => { - let mut polls = self.polls.lock().unwrap(); - let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number)); - to_value(&U256::from(id)) - }, - _ => Err(Error::invalid_params()) - } - } - - fn new_pending_transaction_filter(&self, params: Params) -> Result { - match params { - Params::None => { - let mut polls = self.polls.lock().unwrap(); - let pending_transactions = take_weak!(self.miner).pending_transactions_hashes(); - let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions)); - - to_value(&U256::from(id)) - }, - _ => Err(Error::invalid_params()) - } - } - - fn filter_changes(&self, params: Params) -> Result { - let client = take_weak!(self.client); - from_params::<(Index,)>(params) - .and_then(|(index,)| { - let mut polls = self.polls.lock().unwrap(); - match polls.poll_mut(&index.value()) { - None => Ok(Value::Array(vec![] as Vec)), - Some(filter) => match *filter { - PollFilter::Block(ref mut block_number) => { - // + 1, cause we want to return hashes including current block hash. - let current_number = client.chain_info().best_block_number + 1; - let hashes = (*block_number..current_number).into_iter() - .map(BlockID::Number) - .filter_map(|id| client.block_hash(id)) - .collect::>(); - - *block_number = current_number; - - to_value(&hashes) - }, - PollFilter::PendingTransaction(ref mut previous_hashes) => { - // get hashes of pending transactions - let current_hashes = take_weak!(self.miner).pending_transactions_hashes(); - - let new_hashes = - { - let previous_hashes_set = previous_hashes.iter().collect::>(); - - // find all new hashes - current_hashes - .iter() - .filter(|hash| !previous_hashes_set.contains(hash)) - .cloned() - .collect::>() - }; - - // save all hashes of pending transactions - *previous_hashes = current_hashes; - - // return new hashes - to_value(&new_hashes) - }, - PollFilter::Logs(ref mut block_number, ref mut previous_logs, ref filter) => { - // retrive the current block number - let current_number = client.chain_info().best_block_number; - - // check if we need to check pending hashes - let include_pending = filter.to_block == Some(BlockNumber::Pending); - - // build appropriate filter - let mut filter: EthcoreFilter = filter.clone().into(); - filter.from_block = BlockID::Number(*block_number); - filter.to_block = BlockID::Latest; - - // retrieve logs in range from_block..min(BlockID::Latest..to_block) - let mut logs = client.logs(filter.clone()) - .into_iter() - .map(From::from) - .collect::>(); - - // additionally retrieve pending logs - if include_pending { - let pending_logs = pending_logs(take_weak!(self.miner).deref(), &filter); - - // remove logs about which client was already notified about - let new_pending_logs: Vec<_> = pending_logs.iter() - .filter(|p| !previous_logs.contains(p)) - .cloned() - .collect(); - - // save all logs retrieved by client - *previous_logs = pending_logs.into_iter().collect(); - - // append logs array with new pending logs - logs.extend(new_pending_logs); - } - - // save current block number as next from block number - *block_number = current_number; - - to_value(&logs) - } - } - } - }) - } - - fn filter_logs(&self, params: Params) -> Result { - from_params::<(Index,)>(params) - .and_then(|(index,)| { - let mut polls = self.polls.lock().unwrap(); - match polls.poll(&index.value()) { - Some(&PollFilter::Logs(ref _block_number, ref _previous_log, ref filter)) => { - let include_pending = filter.to_block == Some(BlockNumber::Pending); - let filter: EthcoreFilter = filter.clone().into(); - let mut logs = take_weak!(self.client).logs(filter.clone()) - .into_iter() - .map(From::from) - .collect::>(); - - if include_pending { - logs.extend(pending_logs(take_weak!(self.miner).deref(), &filter)); - } - - to_value(&logs) - }, - // just empty array - _ => Ok(Value::Array(vec![] as Vec)), - } - }) - } - - fn uninstall_filter(&self, params: Params) -> Result { - from_params::<(Index,)>(params) - .and_then(|(index,)| { - self.polls.lock().unwrap().remove_poll(&index.value()); - to_value(&true) - }) - } -} diff --git a/rpc/src/v1/impls/eth_filter.rs b/rpc/src/v1/impls/eth_filter.rs new file mode 100644 index 000000000..c6aecdca2 --- /dev/null +++ b/rpc/src/v1/impls/eth_filter.rs @@ -0,0 +1,214 @@ +// 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 . + +//! Eth Filter RPC implementation + +use std::ops::Deref; +use std::sync::{Arc, Weak, Mutex}; +use std::collections::HashSet; +use jsonrpc_core::*; +use util::numbers::*; +use ethminer::MinerService; +use ethcore::filter::Filter as EthcoreFilter; +use ethcore::client::{BlockChainClient, BlockID}; +use v1::traits::EthFilter; +use v1::types::{BlockNumber, Index, Filter, Log}; +use v1::helpers::{PollFilter, PollManager}; +use v1::impls::eth::pending_logs; + + +/// Eth filter rpc implementation. +pub struct EthFilterClient where + C: BlockChainClient, + M: MinerService { + + client: Weak, + miner: Weak, + polls: Mutex>, +} + +impl EthFilterClient where + C: BlockChainClient, + M: MinerService { + + /// Creates new Eth filter client. + pub fn new(client: &Arc, miner: &Arc) -> Self { + EthFilterClient { + client: Arc::downgrade(client), + miner: Arc::downgrade(miner), + polls: Mutex::new(PollManager::new()), + } + } +} + +impl EthFilter for EthFilterClient where + C: BlockChainClient + 'static, + M: MinerService + 'static { + + fn new_filter(&self, params: Params) -> Result { + from_params::<(Filter,)>(params) + .and_then(|(filter,)| { + let mut polls = self.polls.lock().unwrap(); + let block_number = take_weak!(self.client).chain_info().best_block_number; + let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter)); + to_value(&U256::from(id)) + }) + } + + fn new_block_filter(&self, params: Params) -> Result { + match params { + Params::None => { + let mut polls = self.polls.lock().unwrap(); + let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number)); + to_value(&U256::from(id)) + }, + _ => Err(Error::invalid_params()) + } + } + + fn new_pending_transaction_filter(&self, params: Params) -> Result { + match params { + Params::None => { + let mut polls = self.polls.lock().unwrap(); + let pending_transactions = take_weak!(self.miner).pending_transactions_hashes(); + let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions)); + + to_value(&U256::from(id)) + }, + _ => Err(Error::invalid_params()) + } + } + + fn filter_changes(&self, params: Params) -> Result { + let client = take_weak!(self.client); + from_params::<(Index,)>(params) + .and_then(|(index,)| { + let mut polls = self.polls.lock().unwrap(); + match polls.poll_mut(&index.value()) { + None => Ok(Value::Array(vec![] as Vec)), + Some(filter) => match *filter { + PollFilter::Block(ref mut block_number) => { + // + 1, cause we want to return hashes including current block hash. + let current_number = client.chain_info().best_block_number + 1; + let hashes = (*block_number..current_number).into_iter() + .map(BlockID::Number) + .filter_map(|id| client.block_hash(id)) + .collect::>(); + + *block_number = current_number; + + to_value(&hashes) + }, + PollFilter::PendingTransaction(ref mut previous_hashes) => { + // get hashes of pending transactions + let current_hashes = take_weak!(self.miner).pending_transactions_hashes(); + + let new_hashes = + { + let previous_hashes_set = previous_hashes.iter().collect::>(); + + // find all new hashes + current_hashes + .iter() + .filter(|hash| !previous_hashes_set.contains(hash)) + .cloned() + .collect::>() + }; + + // save all hashes of pending transactions + *previous_hashes = current_hashes; + + // return new hashes + to_value(&new_hashes) + }, + PollFilter::Logs(ref mut block_number, ref mut previous_logs, ref filter) => { + // retrive the current block number + let current_number = client.chain_info().best_block_number; + + // check if we need to check pending hashes + let include_pending = filter.to_block == Some(BlockNumber::Pending); + + // build appropriate filter + let mut filter: EthcoreFilter = filter.clone().into(); + filter.from_block = BlockID::Number(*block_number); + filter.to_block = BlockID::Latest; + + // retrieve logs in range from_block..min(BlockID::Latest..to_block) + let mut logs = client.logs(filter.clone()) + .into_iter() + .map(From::from) + .collect::>(); + + // additionally retrieve pending logs + if include_pending { + let pending_logs = pending_logs(take_weak!(self.miner).deref(), &filter); + + // remove logs about which client was already notified about + let new_pending_logs: Vec<_> = pending_logs.iter() + .filter(|p| !previous_logs.contains(p)) + .cloned() + .collect(); + + // save all logs retrieved by client + *previous_logs = pending_logs.into_iter().collect(); + + // append logs array with new pending logs + logs.extend(new_pending_logs); + } + + // save current block number as next from block number + *block_number = current_number; + + to_value(&logs) + } + } + } + }) + } + + fn filter_logs(&self, params: Params) -> Result { + from_params::<(Index,)>(params) + .and_then(|(index,)| { + let mut polls = self.polls.lock().unwrap(); + match polls.poll(&index.value()) { + Some(&PollFilter::Logs(ref _block_number, ref _previous_log, ref filter)) => { + let include_pending = filter.to_block == Some(BlockNumber::Pending); + let filter: EthcoreFilter = filter.clone().into(); + let mut logs = take_weak!(self.client).logs(filter.clone()) + .into_iter() + .map(From::from) + .collect::>(); + + if include_pending { + logs.extend(pending_logs(take_weak!(self.miner).deref(), &filter)); + } + + to_value(&logs) + }, + // just empty array + _ => Ok(Value::Array(vec![] as Vec)), + } + }) + } + + fn uninstall_filter(&self, params: Params) -> Result { + from_params::<(Index,)>(params) + .and_then(|(index,)| { + self.polls.lock().unwrap().remove_poll(&index.value()); + to_value(&true) + }) + } +} diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs new file mode 100644 index 000000000..04011902b --- /dev/null +++ b/rpc/src/v1/impls/eth_signing.rs @@ -0,0 +1,111 @@ +// 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 . + +//! Eth Signing RPC implementation. + +use std::sync::{Arc, Weak}; +use jsonrpc_core::*; +use ethminer::MinerService; +use ethcore::client::BlockChainClient; +use util::numbers::*; +use util::keys::store::AccountProvider; +use v1::helpers::{SigningQueue, ConfirmationsQueue}; +use v1::traits::EthSigning; +use v1::types::TransactionRequest; +use v1::impls::sign_and_dispatch; + + +/// Implementation of functions that require signing when no trusted signer is used. +pub struct EthSigningQueueClient { + queue: Weak, +} + +impl EthSigningQueueClient { + /// Creates a new signing queue client given shared signing queue. + pub fn new(queue: &Arc) -> Self { + EthSigningQueueClient { + queue: Arc::downgrade(queue), + } + } +} + +impl EthSigning for EthSigningQueueClient { + + fn sign(&self, _params: Params) -> Result { + // TODO [ToDr] Implement sign when rest of the signing queue is ready. + rpc_unimplemented!() + } + + fn send_transaction(&self, params: Params) -> Result { + from_params::<(TransactionRequest, )>(params) + .and_then(|(request, )| { + let queue = take_weak!(self.queue); + queue.add_request(request); + // TODO [ToDr] Block and wait for confirmation? + to_value(&H256::zero()) + }) + } +} + +/// Implementation of functions that require signing when no trusted signer is used. +pub struct EthSigningUnsafeClient where + C: BlockChainClient, + A: AccountProvider, + M: MinerService { + client: Weak, + accounts: Weak, + miner: Weak, +} + +impl EthSigningUnsafeClient where + C: BlockChainClient, + A: AccountProvider, + M: MinerService { + + /// Creates new EthClient. + pub fn new(client: &Arc, accounts: &Arc, miner: &Arc) + -> Self { + EthSigningUnsafeClient { + client: Arc::downgrade(client), + miner: Arc::downgrade(miner), + accounts: Arc::downgrade(accounts), + } + } +} + +impl EthSigning for EthSigningUnsafeClient where + C: BlockChainClient + 'static, + A: AccountProvider + 'static, + M: MinerService + 'static { + + fn sign(&self, params: Params) -> Result { + from_params::<(Address, H256)>(params).and_then(|(addr, msg)| { + to_value(&take_weak!(self.accounts).sign(&addr, &msg).unwrap_or(H520::zero())) + }) + } + + fn send_transaction(&self, params: Params) -> Result { + from_params::<(TransactionRequest, )>(params) + .and_then(|(request, )| { + let accounts = take_weak!(self.accounts); + match accounts.account_secret(&request.from) { + Ok(secret) => sign_and_dispatch(&self.client, &self.miner, request, secret), + Err(_) => to_value(&H256::zero()) + } + }) + } + +} diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 7ee8b8b8a..975a5fa77 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -31,16 +31,22 @@ macro_rules! rpc_unimplemented { mod web3; mod eth; +mod eth_filter; +mod eth_signing; mod net; mod personal; +mod personal_signer; mod ethcore; mod traces; mod rpc; pub use self::web3::Web3Client; -pub use self::eth::{EthClient, EthFilterClient}; +pub use self::eth::EthClient; +pub use self::eth_filter::EthFilterClient; +pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient}; pub use self::net::NetClient; pub use self::personal::PersonalClient; +pub use self::personal_signer::SignerClient; pub use self::ethcore::EthcoreClient; pub use self::traces::TracesClient; pub use self::rpc::RpcClient; @@ -92,4 +98,4 @@ fn sign_and_dispatch(client: &Weak, miner: &Weak, request: Transacti trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); dispatch_transaction(&*client, &*miner, signed_transaction) -} \ No newline at end of file +} diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 19e902996..30d541772 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -20,7 +20,7 @@ use jsonrpc_core::*; use v1::traits::Personal; use v1::types::TransactionRequest; use v1::impls::sign_and_dispatch; -use util::keys::store::*; +use util::keys::store::AccountProvider; use util::numbers::*; use ethcore::client::BlockChainClient; use ethminer::MinerService; diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs new file mode 100644 index 000000000..cf4e927ac --- /dev/null +++ b/rpc/src/v1/impls/personal_signer.rs @@ -0,0 +1,93 @@ +// 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 . + +//! Transactions Confirmations (personal) rpc implementation + +use std::sync::{Arc, Weak}; +use jsonrpc_core::*; +use v1::traits::PersonalSigner; +use v1::types::TransactionModification; +use v1::impls::sign_and_dispatch; +use v1::helpers::{SigningQueue, ConfirmationsQueue}; +use util::keys::store::AccountProvider; +use util::numbers::*; +use ethcore::client::BlockChainClient; +use ethminer::MinerService; + +/// Transactions confirmation (personal) rpc implementation. +pub struct SignerClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { + queue: Weak, + accounts: Weak, + client: Weak, + miner: Weak, +} + +impl SignerClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { + + /// Create new instance of signer client. + pub fn new(store: &Arc, client: &Arc, miner: &Arc, queue: &Arc) -> Self { + SignerClient { + queue: Arc::downgrade(queue), + accounts: Arc::downgrade(store), + client: Arc::downgrade(client), + miner: Arc::downgrade(miner), + } + } +} + +impl PersonalSigner for SignerClient + where A: AccountProvider, C: BlockChainClient, M: MinerService { + + fn transactions_to_confirm(&self, _params: Params) -> Result { + let queue = take_weak!(self.queue); + to_value(&queue.requests()) + } + + fn confirm_transaction(&self, params: Params) -> Result { + from_params::<(U256, TransactionModification, String)>(params).and_then( + |(id, modification, pass)| { + let accounts = take_weak!(self.accounts); + let queue = take_weak!(self.queue); + queue.remove_request(id) + .and_then(|confirmation| { + let mut request = confirmation.transaction; + // apply modification + if let Some(gas_price) = modification.gas_price { + request.gas_price = Some(gas_price); + } + match accounts.locked_account_secret(&request.from, &pass) { + Ok(secret) => Some(sign_and_dispatch(&self.client, &self.miner, request, secret)), + Err(_) => None + } + }) + .unwrap_or_else(|| to_value(&H256::zero())) + } + ) + } + + fn reject_transaction(&self, params: Params) -> Result { + from_params::<(U256, )>(params).and_then( + |(id, )| { + let queue = take_weak!(self.queue); + let res = queue.remove_request(id); + to_value(&res.is_some()) + } + ) + } +} + diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index b1ab256c0..54628d892 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -25,5 +25,6 @@ pub mod traits; pub mod tests; pub mod types; -pub use self::traits::{Web3, Eth, EthFilter, Personal, Net, Ethcore, Traces, Rpc}; +pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Personal, PersonalSigner, Net, Ethcore, Traces, Rpc}; pub use self::impls::*; +pub use self::helpers::{SigningQueue, ConfirmationsQueue}; diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 30815b8a8..80aa8ce33 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -35,8 +35,8 @@ use util::keys::{AccountProvider, TestAccount, TestAccountProvider}; use jsonrpc_core::IoHandler; use ethjson::blockchain::BlockChain; -use v1::traits::eth::Eth; -use v1::impls::EthClient; +use v1::traits::eth::{Eth, EthSigning}; +use v1::impls::{EthClient, EthSigningUnsafeClient}; use v1::tests::helpers::{TestSyncProvider, Config}; fn account_provider() -> Arc { @@ -109,10 +109,15 @@ impl EthTester { &miner_service, &external_miner ); + let eth_sign = EthSigningUnsafeClient::new( + &client, + &account_provider, + &miner_service + ); let handler = IoHandler::new(); - let delegate = eth_client.to_delegate(); - handler.add_delegate(delegate); + handler.add_delegate(eth_client.to_delegate()); + handler.add_delegate(eth_sign.to_delegate()); EthTester { _miner: miner_service, @@ -352,4 +357,4 @@ fn verify_transaction_counts(name: String, chain: BlockChain) { register_test!(eth_transaction_count_1, verify_transaction_counts, "BlockchainTests/bcWalletTest"); register_test!(eth_transaction_count_2, verify_transaction_counts, "BlockchainTests/bcTotalDifficultyTest"); -register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/bcGasPricerTest"); \ No newline at end of file +register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/bcGasPricerTest"); diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index c51d6d7da..49ca54cef 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -27,7 +27,7 @@ use ethcore::receipt::LocalizedReceipt; use ethcore::transaction::{Transaction, Action}; use ethminer::{ExternalMiner, MinerService}; use ethsync::SyncState; -use v1::{Eth, EthClient}; +use v1::{Eth, EthClient, EthSigning, EthSigningUnsafeClient}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService}; use rustc_serialize::hex::ToHex; @@ -72,8 +72,11 @@ impl Default for EthTester { let hashrates = Arc::new(RwLock::new(HashMap::new())); let external_miner = Arc::new(ExternalMiner::new(hashrates.clone())); let eth = EthClient::new(&client, &sync, &ap, &miner, &external_miner).to_delegate(); + let sign = EthSigningUnsafeClient::new(&client, &ap, &miner).to_delegate(); let io = IoHandler::new(); io.add_delegate(eth); + io.add_delegate(sign); + EthTester { client: client, sync: sync, diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs new file mode 100644 index 000000000..6eb6e3fd6 --- /dev/null +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -0,0 +1,75 @@ +// 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 std::sync::Arc; +use jsonrpc_core::IoHandler; +use v1::impls::EthSigningQueueClient; +use v1::traits::EthSigning; +use v1::helpers::{ConfirmationsQueue, SigningQueue}; +use util::keys::TestAccount; + +struct EthSigningTester { + pub queue: Arc, + pub io: IoHandler, +} + +impl Default for EthSigningTester { + fn default() -> Self { + let queue = Arc::new(ConfirmationsQueue::default()); + let io = IoHandler::new(); + io.add_delegate(EthSigningQueueClient::new(&queue).to_delegate()); + + EthSigningTester { + queue: queue, + io: io, + } + } +} + +fn eth_signing() -> EthSigningTester { + EthSigningTester::default() +} + + +#[test] +fn should_add_transaction_to_queue() { + // given + let tester = eth_signing(); + let account = TestAccount::new("123"); + let address = account.address(); + assert_eq!(tester.queue.requests().len(), 0); + + // when + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_sendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":"0x0000000000000000000000000000000000000000000000000000000000000000","id":1}"#; + + + // then + assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.queue.requests().len(), 1); + +} diff --git a/rpc/src/v1/tests/mocked/mod.rs b/rpc/src/v1/tests/mocked/mod.rs index dc09d998d..986dbfdef 100644 --- a/rpc/src/v1/tests/mocked/mod.rs +++ b/rpc/src/v1/tests/mocked/mod.rs @@ -18,8 +18,10 @@ //! method calls properly. mod eth; +mod eth_signing; mod net; mod web3; mod personal; +mod personal_signer; mod ethcore; mod rpc; diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 991b13cba..8bc3ab3c8 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -176,4 +176,4 @@ fn sign_and_send_transaction() { 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)); -} \ No newline at end of file +} diff --git a/rpc/src/v1/tests/mocked/personal_signer.rs b/rpc/src/v1/tests/mocked/personal_signer.rs new file mode 100644 index 000000000..cd1f81d9a --- /dev/null +++ b/rpc/src/v1/tests/mocked/personal_signer.rs @@ -0,0 +1,169 @@ +// 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 std::sync::Arc; +use std::str::FromStr; +use std::collections::HashMap; +use jsonrpc_core::IoHandler; +use util::numbers::*; +use util::keys::{TestAccount, TestAccountProvider}; +use ethcore::client::TestBlockChainClient; +use ethcore::transaction::{Transaction, Action}; +use v1::{SignerClient, PersonalSigner}; +use v1::tests::helpers::TestMinerService; +use v1::helpers::{SigningQueue, ConfirmationsQueue}; +use v1::types::TransactionRequest; + + +struct PersonalSignerTester { + queue: Arc, + accounts: Arc, + io: IoHandler, + miner: Arc, + // these unused fields are necessary to keep the data alive + // as the handler has only weak pointers. + _client: Arc, +} + +fn blockchain_client() -> Arc { + let client = TestBlockChainClient::new(); + Arc::new(client) +} + +fn accounts_provider() -> Arc { + let accounts = HashMap::new(); + let ap = TestAccountProvider::new(accounts); + Arc::new(ap) +} + +fn miner_service() -> Arc { + Arc::new(TestMinerService::default()) +} + +fn signer_tester() -> PersonalSignerTester { + let queue = Arc::new(ConfirmationsQueue::default()); + let accounts = accounts_provider(); + let client = blockchain_client(); + let miner = miner_service(); + + let io = IoHandler::new(); + io.add_delegate(SignerClient::new(&accounts, &client, &miner, &queue).to_delegate()); + + PersonalSignerTester { + queue: queue, + accounts: accounts, + io: io, + miner: miner, + _client: client, + } +} + + +#[test] +fn should_return_list_of_transactions_in_queue() { + // given + let tester = signer_tester(); + tester.queue.add_request(TransactionRequest { + from: Address::from(1), + to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + gas_price: Some(U256::from(10_000)), + gas: Some(U256::from(10_000_000)), + value: Some(U256::from(1)), + data: None, + nonce: None, + }); + + // when + let request = r#"{"jsonrpc":"2.0","method":"personal_transactionsToConfirm","params":[],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[{"id":"0x01","transaction":{"data":null,"from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x01"}}],"id":1}"#; + + // then + assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); +} + + +#[test] +fn should_reject_transaction_from_queue_without_dispatching() { + // given + let tester = signer_tester(); + tester.queue.add_request(TransactionRequest { + from: Address::from(1), + to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + gas_price: Some(U256::from(10_000)), + gas: Some(U256::from(10_000_000)), + value: Some(U256::from(1)), + data: None, + nonce: None, + }); + assert_eq!(tester.queue.requests().len(), 1); + + // when + let request = r#"{"jsonrpc":"2.0","method":"personal_rejectTransaction","params":["0x01"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + + // then + assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.queue.requests().len(), 0); + assert_eq!(tester.miner.imported_transactions.lock().unwrap().len(), 0); +} + +#[test] +fn should_confirm_transaction_and_dispatch() { + // given + let tester = signer_tester(); + let account = TestAccount::new("test"); + let address = account.address(); + let secret = account.secret.clone(); + let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(); + tester.accounts.accounts + .write() + .unwrap() + .insert(address, account); + tester.queue.add_request(TransactionRequest { + from: address, + to: Some(recipient), + gas_price: Some(U256::from(10_000)), + gas: Some(U256::from(10_000_000)), + value: Some(U256::from(1)), + data: None, + nonce: None, + }); + let t = Transaction { + nonce: U256::zero(), + gas_price: U256::from(0x1000), + gas: U256::from(10_000_000), + action: Action::Call(recipient), + value: U256::from(0x1), + data: vec![] + }.sign(&secret); + + assert_eq!(tester.queue.requests().len(), 1); + + // when + let request = r#"{ + "jsonrpc":"2.0", + "method":"personal_confirmTransaction", + "params":["0x01", {"gasPrice":"0x1000"}, "test"], + "id":1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; + + // then + assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); + assert_eq!(tester.queue.requests().len(), 0); + assert_eq!(tester.miner.imported_transactions.lock().unwrap().len(), 1); +} + diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 1577053f4..c4369ff2a 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -74,12 +74,6 @@ pub trait Eth: Sized + Send + Sync + 'static { /// Returns the code at given address at given time (block number). fn code_at(&self, _: Params) -> Result; - /// Signs the data with given address signature. - fn sign(&self, _: Params) -> Result; - - /// Sends transaction. - fn send_transaction(&self, _: Params) -> Result; - /// Sends signed transaction. fn send_raw_transaction(&self, _: Params) -> Result; @@ -150,8 +144,6 @@ pub trait Eth: Sized + Send + Sync + 'static { delegate.add_method("eth_getUncleCountByBlockHash", Eth::block_uncles_count_by_hash); delegate.add_method("eth_getUncleCountByBlockNumber", Eth::block_uncles_count_by_number); 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_sendRawTransaction", Eth::send_raw_transaction); delegate.add_method("eth_call", Eth::call); delegate.add_method("eth_estimateGas", Eth::estimate_gas); @@ -208,3 +200,20 @@ pub trait EthFilter: Sized + Send + Sync + 'static { delegate } } + +/// Signing methods implementation relying on unlocked accounts. +pub trait EthSigning: Sized + Send + Sync + 'static { + /// Signs the data with given address signature. + fn sign(&self, _: Params) -> Result; + + /// Sends transaction. + fn send_transaction(&self, _: Params) -> Result; + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("eth_sign", EthSigning::sign); + delegate.add_method("eth_sendTransaction", EthSigning::send_transaction); + delegate + } +} diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs index 0728fd06a..d994ffc24 100644 --- a/rpc/src/v1/traits/mod.rs +++ b/rpc/src/v1/traits/mod.rs @@ -25,9 +25,11 @@ pub mod traces; pub mod rpc; pub use self::web3::Web3; -pub use self::eth::{Eth, EthFilter}; +pub use self::eth::{Eth, EthFilter, EthSigning}; pub use self::net::Net; -pub use self::personal::Personal; +pub use self::personal::{Personal, PersonalSigner}; pub use self::ethcore::Ethcore; pub use self::traces::Traces; pub use self::rpc::Rpc; + + diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index d66161c54..a36358766 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -43,3 +43,26 @@ pub trait Personal: Sized + Send + Sync + 'static { delegate } } + +/// Personal extension for transactions confirmations rpc interface. +pub trait PersonalSigner: Sized + Send + Sync + 'static { + + /// Returns a list of transactions to confirm. + fn transactions_to_confirm(&self, _: Params) -> Result; + + /// Confirm and send a specific transaction. + fn confirm_transaction(&self, _: Params) -> Result; + + /// Reject the transaction request. + fn reject_transaction(&self, _: Params) -> Result; + + /// Should be used to convert object to io delegate. + fn to_delegate(self) -> IoDelegate { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("personal_transactionsToConfirm", PersonalSigner::transactions_to_confirm); + delegate.add_method("personal_confirmTransaction", PersonalSigner::confirm_transaction); + delegate.add_method("personal_rejectTransaction", PersonalSigner::reject_transaction); + delegate + } +} + diff --git a/rpc/src/v1/types/mod.rs.in b/rpc/src/v1/types/mod.rs.in index 824a061ef..b4e82a28b 100644 --- a/rpc/src/v1/types/mod.rs.in +++ b/rpc/src/v1/types/mod.rs.in @@ -38,7 +38,7 @@ pub use self::log::Log; 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::transaction_request::{TransactionRequest, TransactionConfirmation, TransactionModification}; pub use self::call_request::CallRequest; pub use self::receipt::Receipt; pub use self::trace::Trace; diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index 1b51e6b12..93d6a479b 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -21,7 +21,7 @@ use util::numbers::U256; use v1::types::bytes::Bytes; /// Transaction request coming from RPC -#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Deserialize)] +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Serialize, Deserialize)] pub struct TransactionRequest { /// Sender pub from: Address, @@ -40,6 +40,24 @@ pub struct TransactionRequest { pub nonce: Option, } +/// Transaction confirmation waiting in a queue +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Serialize)] +pub struct TransactionConfirmation { + /// Id of this confirmation + pub id: U256, + /// TransactionRequest + pub transaction: TransactionRequest, +} + +/// Possible modifications to the confirmed transaction sent by SystemUI +#[derive(Debug, PartialEq, Deserialize)] +pub struct TransactionModification { + /// Modified gas price + #[serde(rename="gasPrice")] + pub gas_price: Option, +} + + #[cfg(test)] mod tests { use std::str::FromStr; @@ -135,5 +153,26 @@ mod tests { nonce: None, }); } + + #[test] + fn should_deserialize_modification() { + // given + let s1 = r#"{ + "gasPrice":"0x0ba43b7400" + }"#; + let s2 = r#"{}"#; + + // when + let res1: TransactionModification = serde_json::from_str(s1).unwrap(); + let res2: TransactionModification = serde_json::from_str(s2).unwrap(); + + // then + assert_eq!(res1, TransactionModification { + gas_price: Some(U256::from_str("0ba43b7400").unwrap()), + }); + assert_eq!(res2, TransactionModification { + gas_price: None, + }); + } } diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 51b1b1e8d..170c9320e 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -9,13 +9,8 @@ build = "build.rs" [build-dependencies] rustc_version = "0.1" -serde_codegen = { version = "0.7.0", optional = true } -syntex = "^0.32.0" [dependencies] -serde = "0.7.0" -serde_json = "0.7.0" -rustc-serialize = "0.3" jsonrpc-core = "2.0" log = "0.3" env_logger = "0.3" @@ -23,10 +18,7 @@ ws = "0.4.7" ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc" } -serde_macros = { version = "0.7.0", optional = true } clippy = { version = "0.0.69", optional = true} [features] -default = ["serde_codegen"] -nightly = ["serde_macros"] dev = ["clippy"] diff --git a/signer/build.rs b/signer/build.rs index 2bcfc7da5..41b9a1b3e 100644 --- a/signer/build.rs +++ b/signer/build.rs @@ -19,34 +19,7 @@ extern crate rustc_version; use rustc_version::{version_meta, Channel}; fn main() { - serde::main(); if let Channel::Nightly = version_meta().channel { println!("cargo:rustc-cfg=nightly"); } } - -#[cfg(not(feature = "serde_macros"))] -mod serde { - 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/types/mod.rs.in"); - let dst = Path::new(&out_dir).join("mod.rs"); - - let mut registry = syntex::Registry::new(); - - serde_codegen::register(&mut registry); - registry.expand("", &src, &dst).unwrap(); - } -} - -#[cfg(feature = "serde_macros")] -mod serde { - pub fn main() {} -} diff --git a/signer/src/lib.rs b/signer/src/lib.rs index f3a963ac7..e2df72bcc 100644 --- a/signer/src/lib.rs +++ b/signer/src/lib.rs @@ -17,8 +17,6 @@ #![warn(missing_docs)] #![cfg_attr(all(nightly, feature="dev"), feature(plugin))] #![cfg_attr(all(nightly, feature="dev"), plugin(clippy))] -// Generated by serde -#![cfg_attr(all(nightly, feature="dev"), allow(redundant_closure_call))] //! Signer module //! @@ -45,18 +43,12 @@ extern crate log; extern crate env_logger; -extern crate serde; -extern crate serde_json; -extern crate rustc_serialize; - extern crate ethcore_util as util; extern crate ethcore_rpc as rpc; extern crate jsonrpc_core; extern crate ws; -mod signing_queue; mod ws_server; - pub use ws_server::*; #[cfg(test)] diff --git a/signer/src/signing_queue.rs b/signer/src/signing_queue.rs deleted file mode 100644 index 611d467c2..000000000 --- a/signer/src/signing_queue.rs +++ /dev/null @@ -1,74 +0,0 @@ -// 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 std::collections::HashSet; -use rpc::v1::types::TransactionRequest; - -pub trait SigningQueue { - fn add_request(&mut self, transaction: TransactionRequest); - - fn remove_request(&mut self, id: TransactionRequest); - - fn requests(&self) -> &HashSet; -} - -impl SigningQueue for HashSet { - fn add_request(&mut self, transaction: TransactionRequest) { - self.insert(transaction); - } - - fn remove_request(&mut self, id: TransactionRequest) { - self.remove(&id); - } - - fn requests(&self) -> &HashSet { - self - } -} - - -#[cfg(test)] -mod test { - use std::collections::HashSet; - use util::hash::Address; - use util::numbers::U256; - use rpc::v1::types::TransactionRequest; - use super::*; - - #[test] - fn should_work_for_hashset() { - // given - let mut queue = HashSet::new(); - - let request = TransactionRequest { - from: Address::from(1), - to: Some(Address::from(2)), - gas_price: None, - gas: None, - value: Some(U256::from(10_000_000)), - data: None, - nonce: None, - }; - - // when - queue.add_request(request.clone()); - let all = queue.requests(); - - // then - assert_eq!(all.len(), 1); - assert!(all.contains(&request)); - } -} diff --git a/signer/src/types/mod.rs b/signer/src/types/mod.rs deleted file mode 100644 index d5e15046a..000000000 --- a/signer/src/types/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 . - -//! Reusable types with JSON Serialization. - -#[cfg(feature = "serde_macros")] -include!("mod.rs.in"); - -#[cfg(not(feature = "serde_macros"))] -include!(concat!(env!("OUT_DIR"), "/mod.rs")); diff --git a/signer/src/types/mod.rs.in b/signer/src/types/mod.rs.in deleted file mode 100644 index a59f81ece..000000000 --- a/signer/src/types/mod.rs.in +++ /dev/null @@ -1,25 +0,0 @@ -// 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 . - - - - - - - - - -// TODO [ToDr] Types are empty for now. But they are about to come. diff --git a/signer/src/ws_server/mod.rs b/signer/src/ws_server/mod.rs index bb10bc5c1..bc8fb33f8 100644 --- a/signer/src/ws_server/mod.rs +++ b/signer/src/ws_server/mod.rs @@ -25,6 +25,7 @@ use std::sync::Arc; use std::net::SocketAddr; use util::panics::{PanicHandler, OnPanicListener, MayPanic}; use jsonrpc_core::{IoHandler, IoDelegate}; +use rpc::Extendable; mod session; @@ -57,6 +58,12 @@ impl Default for ServerBuilder { } } +impl Extendable for ServerBuilder { + fn add_delegate(&self, delegate: IoDelegate) { + self.handler.add_delegate(delegate); + } +} + impl ServerBuilder { /// Creates new `ServerBuilder` pub fn new() -> Self { @@ -65,11 +72,6 @@ impl ServerBuilder { } } - /// Adds rpc delegate - pub fn add_delegate(&self, delegate: IoDelegate) where D: Send + Sync + 'static { - self.handler.add_delegate(delegate); - } - /// Starts a new `WebSocket` server in separate thread. /// Returns a `Server` handle which closes the server when droped. pub fn start(self, addr: SocketAddr) -> Result { From c370bcaded498e1e4c42b9c8d42674881f344ade Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 19:57:34 +0200 Subject: [PATCH 41/43] merge fixes --- parity/rpc_apis.rs | 2 +- rpc/src/v1/impls/eth.rs | 183 ---------------------------- rpc/src/v1/impls/eth_filter.rs | 2 +- rpc/src/v1/impls/eth_signing.rs | 10 +- rpc/src/v1/impls/personal_signer.rs | 10 +- 5 files changed, 12 insertions(+), 195 deletions(-) diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index c73a70fee..d9f0cd4eb 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use die::*; use ethsync::EthSync; -use ethminer::{Miner, ExternalMiner}; +use ethcore::miner::{Miner, ExternalMiner}; use ethcore::client::Client; use util::RotatingLogger; use util::keys::store::AccountService; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 1af4491f2..83a788599 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -544,186 +544,3 @@ impl Eth for EthClient where rpc_unimplemented!() } } - -/// Eth filter rpc implementation. -pub struct EthFilterClient where - C: MiningBlockChainClient, - M: MinerService { - - client: Weak, - miner: Weak, - polls: Mutex>, -} - -impl EthFilterClient where - C: MiningBlockChainClient, - M: MinerService { - - /// Creates new Eth filter client. - pub fn new(client: &Arc, miner: &Arc) -> Self { - EthFilterClient { - client: Arc::downgrade(client), - miner: Arc::downgrade(miner), - polls: Mutex::new(PollManager::new()), - } - } -} - -impl EthFilter for EthFilterClient where - C: MiningBlockChainClient + 'static, - M: MinerService + 'static { - - fn new_filter(&self, params: Params) -> Result { - from_params::<(Filter,)>(params) - .and_then(|(filter,)| { - let mut polls = self.polls.lock().unwrap(); - let block_number = take_weak!(self.client).chain_info().best_block_number; - let id = polls.create_poll(PollFilter::Logs(block_number, Default::default(), filter)); - to_value(&U256::from(id)) - }) - } - - fn new_block_filter(&self, params: Params) -> Result { - match params { - Params::None => { - let mut polls = self.polls.lock().unwrap(); - let id = polls.create_poll(PollFilter::Block(take_weak!(self.client).chain_info().best_block_number)); - to_value(&U256::from(id)) - }, - _ => Err(Error::invalid_params()) - } - } - - fn new_pending_transaction_filter(&self, params: Params) -> Result { - match params { - Params::None => { - let mut polls = self.polls.lock().unwrap(); - let pending_transactions = take_weak!(self.miner).pending_transactions_hashes(); - let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions)); - - to_value(&U256::from(id)) - }, - _ => Err(Error::invalid_params()) - } - } - - fn filter_changes(&self, params: Params) -> Result { - let client = take_weak!(self.client); - from_params::<(Index,)>(params) - .and_then(|(index,)| { - let mut polls = self.polls.lock().unwrap(); - match polls.poll_mut(&index.value()) { - None => Ok(Value::Array(vec![] as Vec)), - Some(filter) => match *filter { - PollFilter::Block(ref mut block_number) => { - // + 1, cause we want to return hashes including current block hash. - let current_number = client.chain_info().best_block_number + 1; - let hashes = (*block_number..current_number).into_iter() - .map(BlockID::Number) - .filter_map(|id| client.block_hash(id)) - .collect::>(); - - *block_number = current_number; - - to_value(&hashes) - }, - PollFilter::PendingTransaction(ref mut previous_hashes) => { - // get hashes of pending transactions - let current_hashes = take_weak!(self.miner).pending_transactions_hashes(); - - let new_hashes = - { - let previous_hashes_set = previous_hashes.iter().collect::>(); - - // find all new hashes - current_hashes - .iter() - .filter(|hash| !previous_hashes_set.contains(hash)) - .cloned() - .collect::>() - }; - - // save all hashes of pending transactions - *previous_hashes = current_hashes; - - // return new hashes - to_value(&new_hashes) - }, - PollFilter::Logs(ref mut block_number, ref mut previous_logs, ref filter) => { - // retrive the current block number - let current_number = client.chain_info().best_block_number; - - // check if we need to check pending hashes - let include_pending = filter.to_block == Some(BlockNumber::Pending); - - // build appropriate filter - let mut filter: EthcoreFilter = filter.clone().into(); - filter.from_block = BlockID::Number(*block_number); - filter.to_block = BlockID::Latest; - - // retrieve logs in range from_block..min(BlockID::Latest..to_block) - let mut logs = client.logs(filter.clone()) - .into_iter() - .map(From::from) - .collect::>(); - - // additionally retrieve pending logs - if include_pending { - let pending_logs = pending_logs(take_weak!(self.miner).deref(), &filter); - - // remove logs about which client was already notified about - let new_pending_logs: Vec<_> = pending_logs.iter() - .filter(|p| !previous_logs.contains(p)) - .cloned() - .collect(); - - // save all logs retrieved by client - *previous_logs = pending_logs.into_iter().collect(); - - // append logs array with new pending logs - logs.extend(new_pending_logs); - } - - // save current block number as next from block number - *block_number = current_number; - - to_value(&logs) - } - } - } - }) - } - - fn filter_logs(&self, params: Params) -> Result { - from_params::<(Index,)>(params) - .and_then(|(index,)| { - let mut polls = self.polls.lock().unwrap(); - match polls.poll(&index.value()) { - Some(&PollFilter::Logs(ref _block_number, ref _previous_log, ref filter)) => { - let include_pending = filter.to_block == Some(BlockNumber::Pending); - let filter: EthcoreFilter = filter.clone().into(); - let mut logs = take_weak!(self.client).logs(filter.clone()) - .into_iter() - .map(From::from) - .collect::>(); - - if include_pending { - logs.extend(pending_logs(take_weak!(self.miner).deref(), &filter)); - } - - to_value(&logs) - }, - // just empty array - _ => Ok(Value::Array(vec![] as Vec)), - } - }) - } - - fn uninstall_filter(&self, params: Params) -> Result { - from_params::<(Index,)>(params) - .and_then(|(index,)| { - self.polls.lock().unwrap().remove_poll(&index.value()); - to_value(&true) - }) - } -} diff --git a/rpc/src/v1/impls/eth_filter.rs b/rpc/src/v1/impls/eth_filter.rs index c6aecdca2..4f44f5193 100644 --- a/rpc/src/v1/impls/eth_filter.rs +++ b/rpc/src/v1/impls/eth_filter.rs @@ -21,7 +21,7 @@ use std::sync::{Arc, Weak, Mutex}; use std::collections::HashSet; use jsonrpc_core::*; use util::numbers::*; -use ethminer::MinerService; +use ethcore::miner::MinerService; use ethcore::filter::Filter as EthcoreFilter; use ethcore::client::{BlockChainClient, BlockID}; use v1::traits::EthFilter; diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index 04011902b..f0973484f 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -18,8 +18,8 @@ use std::sync::{Arc, Weak}; use jsonrpc_core::*; -use ethminer::MinerService; -use ethcore::client::BlockChainClient; +use ethcore::miner::MinerService; +use ethcore::client::MiningBlockChainClient; use util::numbers::*; use util::keys::store::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; @@ -62,7 +62,7 @@ impl EthSigning for EthSigningQueueClient { /// Implementation of functions that require signing when no trusted signer is used. pub struct EthSigningUnsafeClient where - C: BlockChainClient, + C: MiningBlockChainClient, A: AccountProvider, M: MinerService { client: Weak, @@ -71,7 +71,7 @@ pub struct EthSigningUnsafeClient where } impl EthSigningUnsafeClient where - C: BlockChainClient, + C: MiningBlockChainClient, A: AccountProvider, M: MinerService { @@ -87,7 +87,7 @@ impl EthSigningUnsafeClient where } impl EthSigning for EthSigningUnsafeClient where - C: BlockChainClient + 'static, + C: MiningBlockChainClient + 'static, A: AccountProvider + 'static, M: MinerService + 'static { diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs index cf4e927ac..2d52e07f9 100644 --- a/rpc/src/v1/impls/personal_signer.rs +++ b/rpc/src/v1/impls/personal_signer.rs @@ -24,12 +24,12 @@ use v1::impls::sign_and_dispatch; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use util::keys::store::AccountProvider; use util::numbers::*; -use ethcore::client::BlockChainClient; -use ethminer::MinerService; +use ethcore::client::MiningBlockChainClient; +use ethcore::miner::MinerService; /// Transactions confirmation (personal) rpc implementation. pub struct SignerClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { queue: Weak, accounts: Weak, client: Weak, @@ -37,7 +37,7 @@ pub struct SignerClient } impl SignerClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { /// Create new instance of signer client. pub fn new(store: &Arc, client: &Arc, miner: &Arc, queue: &Arc) -> Self { @@ -51,7 +51,7 @@ impl SignerClient } impl PersonalSigner for SignerClient - where A: AccountProvider, C: BlockChainClient, M: MinerService { + where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { fn transactions_to_confirm(&self, _params: Params) -> Result { let queue = take_weak!(self.queue); From b7ada4dee02ec2fc08415a2a3302c8aea92729e9 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 1 Jun 2016 20:10:51 +0200 Subject: [PATCH 42/43] update readme (#1201) * update readme [ci skip] * minor fixes * mention dapps server. [ci skip] --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 903794e80..193cbeb8f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# ethcore +# [Parity](https://ethcore.io/parity.html) +### Fast, light, and robust Ethereum implementation [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Join the chat at https://gitter.im/trogdoro/xiki][gitter-image]][gitter-url] [![GPLv3][license-image]][license-url] @@ -11,30 +12,64 @@ [license-image]: https://img.shields.io/badge/license-GPL%20v3-green.svg [license-url]: http://www.gnu.org/licenses/gpl-3.0.en.html -[Documentation](http://ethcore.github.io/parity/ethcore/index.html) +[Internal Documentation](http://ethcore.github.io/parity/ethcore/index.html) -### Building from source +---- -First (if you don't already have it) get multirust: +## About Parity + +Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and +cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs. + +By default, Parity will run a JSONRPC server on `127.0.0.1:8545`. This is fully configurable and supports a number +of RPC APIs. + +Parity also runs a server for running decentralized apps, or "Dapps", on `http://127.0.0.1:8080`. +This includes a few useful Dapps, including Ethereum Wallet, Maker OTC, and a node status page. +In a near-future release, it will be easy to install Dapps and use them through this web interface. + +If you run into an issue while using parity, feel free to file one in this repository +or hop on our [gitter chat room]([gitter-url]) to ask a question. We are glad to help! + +Parity's current release is 1.1. You can download it at https://ethcore.io/parity.html or follow the instructions +below to build from source. + +---- + +## Building from source + +Parity is fully compatible with Stable Rust. + +We recommend installing Rust through [multirust](https://github.com/brson/multirust). If you don't already have multirust, you can install it like this: - Linux: ```bash -curl -sf https://raw.githubusercontent.com/brson/multirust/master/quick-install.sh | sh +$ curl -sf https://raw.githubusercontent.com/brson/multirust/master/quick-install.sh | sh ``` - OSX with Homebrew: ```bash -brew update && brew install multirust -multirust default stable +$ brew update && brew install multirust +$ multirust default stable ``` Then, download and build Parity: ```bash # download Parity code -git clone https://github.com/ethcore/parity -cd parity +$ git clone https://github.com/ethcore/parity +$ cd parity # build in release mode -cargo build --release +$ cargo build --release ``` + +This will produce an executable in the `target/release` subdirectory. +Either run `cd target/release`, or copy `target/release/parity` to another location. + +To get started, just run +```bash +$ parity +``` + +and parity will begin syncing the Ethereum blockchain. \ No newline at end of file From 626acda6a3275df74578826f1538d53362926720 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Wed, 1 Jun 2016 20:11:05 +0200 Subject: [PATCH 43/43] fix warnings --- parity/dapps.rs | 4 ---- parity/rpc.rs | 4 ---- parity/signer.rs | 4 ---- 3 files changed, 12 deletions(-) diff --git a/parity/dapps.rs b/parity/dapps.rs index 6a0a8cea7..91742d9e3 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -17,10 +17,6 @@ use std::sync::Arc; use std::str::FromStr; use std::net::SocketAddr; -use ethcore::client::Client; -use ethsync::EthSync; -use ethcore::miner::{Miner, ExternalMiner}; -use util::RotatingLogger; use util::panics::PanicHandler; use die::*; use rpc_apis; diff --git a/parity/rpc.rs b/parity/rpc.rs index 65e6b72e1..66f504408 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -18,10 +18,6 @@ use std::str::FromStr; use std::sync::Arc; use std::net::SocketAddr; -use ethcore::client::Client; -use ethsync::EthSync; -use ethcore::miner::{Miner, ExternalMiner}; -use util::RotatingLogger; use util::panics::PanicHandler; use die::*; use jsonipc; diff --git a/parity/signer.rs b/parity/signer.rs index c250771eb..d549b89cb 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -15,10 +15,6 @@ // along with Parity. If not, see . use std::sync::Arc; -use ethcore::client::Client; -use ethsync::EthSync; -use ethcore::miner::{Miner, ExternalMiner}; -use util::keys::store::AccountService; use util::panics::{PanicHandler, ForwardPanic}; use die::*; use rpc_apis;