diff --git a/src/bin/client.rs b/src/bin/client.rs index 0af81e47f..e25248673 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -1,15 +1,28 @@ extern crate ethcore_util as util; +extern crate ethcore; +extern crate rustc_serialize; use std::io::*; +use std::env; +use std::sync::Arc; +use rustc_serialize::hex::FromHex; +use util::hash::*; use util::network::{NetworkService}; - +use ethcore::client::Client; +use ethcore::sync::EthSync; fn main() { - let _service = NetworkService::start().unwrap(); + let mut service = NetworkService::start().unwrap(); + let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a059262c330941f3fe2a34d16d6e3c7b30d2ceb37c6a0e9a994c494ee1a61d2410885aa4c8bf8e56e264c0c0".from_hex().unwrap(); + let mut dir = env::temp_dir(); + dir.push(H32::random().hex()); + let client = Arc::new(Client::new(&genesis, &dir)); + let sync = Box::new(EthSync::new(client)); + service.register_protocol(sync, "eth", &[62u8, 63u8]).expect("Error registering eth protocol handler"); loop { let mut cmd = String::new(); stdin().read_line(&mut cmd).unwrap(); - if cmd == "quit" || cmd == "exit" || cmd == "q" { + if cmd == "quit\n" || cmd == "exit\n" || cmd == "q\n" { break; } } diff --git a/src/blockchain.rs b/src/blockchain.rs index f64d81189..8eee914db 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -1,9 +1,9 @@ //! Fast access to blockchain data. use std::collections::HashMap; -use std::cell::RefCell; use std::path::Path; use std::hash::Hash; +use std::sync::RwLock; use rocksdb::{DB, WriteBatch, Writable}; use heapsize::HeapSizeOf; use util::hash::*; @@ -62,17 +62,17 @@ impl BestBlock { /// /// **Does not do input data verification.** pub struct BlockChain { - best_block: RefCell, + best_block: RwLock, // block cache - blocks: RefCell>, + blocks: RwLock>, // extra caches - block_details: RefCell>, - block_hashes: RefCell>, - transaction_addresses: RefCell>, - block_logs: RefCell>, - blocks_blooms: RefCell>, + block_details: RwLock>, + block_hashes: RwLock>, + transaction_addresses: RwLock>, + block_logs: RwLock>, + blocks_blooms: RwLock>, extras_db: DB, blocks_db: DB @@ -117,13 +117,13 @@ impl BlockChain { let blocks_db = DB::open_default(blocks_path.to_str().unwrap()).unwrap(); let bc = BlockChain { - best_block: RefCell::new(BestBlock::new()), - blocks: RefCell::new(HashMap::new()), - block_details: RefCell::new(HashMap::new()), - block_hashes: RefCell::new(HashMap::new()), - transaction_addresses: RefCell::new(HashMap::new()), - block_logs: RefCell::new(HashMap::new()), - blocks_blooms: RefCell::new(HashMap::new()), + best_block: RwLock::new(BestBlock::new()), + blocks: RwLock::new(HashMap::new()), + block_details: RwLock::new(HashMap::new()), + block_hashes: RwLock::new(HashMap::new()), + transaction_addresses: RwLock::new(HashMap::new()), + block_logs: RwLock::new(HashMap::new()), + blocks_blooms: RwLock::new(HashMap::new()), extras_db: extras_db, blocks_db: blocks_db }; @@ -158,7 +158,7 @@ impl BlockChain { }; { - let mut best_block = bc.best_block.borrow_mut(); + let mut best_block = bc.best_block.write().unwrap(); best_block.number = bc.block_number(&best_block_hash).unwrap(); best_block.total_difficulty = bc.block_details(&best_block_hash).unwrap().total_difficulty; best_block.hash = best_block_hash; @@ -272,7 +272,7 @@ impl BlockChain { // create views onto rlp let block = BlockView::new(bytes); let header = block.header_view(); - let hash = block.sha3(); + let hash = header.sha3(); if self.is_known(&hash) { return; @@ -283,13 +283,13 @@ impl BlockChain { let (batch, new_best) = self.block_to_extras_insert_batch(bytes); // update best block - let mut best_block = self.best_block.borrow_mut(); + let mut best_block = self.best_block.write().unwrap(); if let Some(b) = new_best { *best_block = b; } // update caches - let mut write = self.block_details.borrow_mut(); + let mut write = self.block_details.write().unwrap(); write.remove(&header.parent_hash()); // update extras database @@ -425,17 +425,17 @@ impl BlockChain { /// Get best block hash. pub fn best_block_hash(&self) -> H256 { - self.best_block.borrow().hash.clone() + self.best_block.read().unwrap().hash.clone() } /// Get best block number. pub fn best_block_number(&self) -> U256 { - self.best_block.borrow().number + self.best_block.read().unwrap().number } /// Get best block total difficulty. pub fn best_block_total_difficulty(&self) -> U256 { - self.best_block.borrow().total_difficulty + self.best_block.read().unwrap().total_difficulty } /// Get the number of given block's hash. @@ -448,9 +448,10 @@ impl BlockChain { self.query_extras(hash, &self.block_logs) } - fn block(&self, hash: &H256) -> Option { + /// Get raw block data + pub fn block(&self, hash: &H256) -> Option { { - let read = self.blocks.borrow(); + let read = self.blocks.read().unwrap(); match read.get(hash) { Some(v) => return Some(v.clone()), None => () @@ -463,7 +464,7 @@ impl BlockChain { match opt { Some(b) => { let bytes: Bytes = b.to_vec(); - let mut write = self.blocks.borrow_mut(); + let mut write = self.blocks.write().unwrap(); write.insert(hash.clone(), bytes.clone()); Some(bytes) }, @@ -471,11 +472,11 @@ impl BlockChain { } } - fn query_extras(&self, hash: &K, cache: &RefCell>) -> Option where + fn query_extras(&self, hash: &K, cache: &RwLock>) -> Option where T: Clone + Decodable + ExtrasIndexable, K: ExtrasSliceConvertable + Eq + Hash + Clone { { - let read = cache.borrow(); + let read = cache.read().unwrap(); match read.get(hash) { Some(v) => return Some(v.clone()), None => () @@ -483,17 +484,17 @@ impl BlockChain { } self.extras_db.get_extras(hash).map(| t: T | { - let mut write = cache.borrow_mut(); + let mut write = cache.write().unwrap(); write.insert(hash.clone(), t.clone()); t }) } - fn query_extras_exist(&self, hash: &K, cache: &RefCell>) -> bool where + fn query_extras_exist(&self, hash: &K, cache: &RwLock>) -> bool where K: ExtrasSliceConvertable + Eq + Hash + Clone, T: ExtrasIndexable { { - let read = cache.borrow(); + let read = cache.read().unwrap(); match read.get(hash) { Some(_) => return true, None => () @@ -506,21 +507,21 @@ impl BlockChain { /// Get current cache size. pub fn cache_size(&self) -> CacheSize { CacheSize { - blocks: self.blocks.heap_size_of_children(), - block_details: self.block_details.heap_size_of_children(), - transaction_addresses: self.transaction_addresses.heap_size_of_children(), - block_logs: self.block_logs.heap_size_of_children(), - blocks_blooms: self.blocks_blooms.heap_size_of_children() + blocks: self.blocks.read().unwrap().heap_size_of_children(), + block_details: self.block_details.read().unwrap().heap_size_of_children(), + transaction_addresses: self.transaction_addresses.read().unwrap().heap_size_of_children(), + block_logs: self.block_logs.read().unwrap().heap_size_of_children(), + blocks_blooms: self.blocks_blooms.read().unwrap().heap_size_of_children() } } /// Tries to squeeze the cache if its too big. pub fn squeeze_to_fit(&self, size: CacheSize) { - self.blocks.borrow_mut().squeeze(size.blocks); - self.block_details.borrow_mut().squeeze(size.block_details); - self.transaction_addresses.borrow_mut().squeeze(size.transaction_addresses); - self.block_logs.borrow_mut().squeeze(size.block_logs); - self.blocks_blooms.borrow_mut().squeeze(size.blocks_blooms); + self.blocks.write().unwrap().squeeze(size.blocks); + self.block_details.write().unwrap().squeeze(size.block_details); + self.transaction_addresses.write().unwrap().squeeze(size.transaction_addresses); + self.block_logs.write().unwrap().squeeze(size.block_logs); + self.blocks_blooms.write().unwrap().squeeze(size.blocks_blooms); } } diff --git a/src/eth.rs b/src/eth.rs index 4ddcaa3f6..97183d983 100644 --- a/src/eth.rs +++ b/src/eth.rs @@ -27,8 +27,8 @@ pub struct BlockChainInfo { pub total_difficulty: U256, pub pending_total_difficulty: U256, pub genesis_hash: H256, - pub last_block_hash: H256, - pub last_block_number: BlockNumber + pub best_block_hash: H256, + pub best_block_number: BlockNumber } pub struct BlockQueueStatus { @@ -37,21 +37,21 @@ pub struct BlockQueueStatus { pub type TreeRoute = ::blockchain::TreeRoute; -pub type BlockNumber = u32; +pub type BlockNumber = u64; pub trait BlockChainClient : Sync { - fn block_header(&self, h: &H256) -> Option; - fn block_body(&self, h: &H256) -> Option; - fn block(&self, h: &H256) -> Option; - fn block_status(&self, h: &H256) -> BlockStatus; + fn block_header(&self, hash: &H256) -> Option; + fn block_body(&self, hash: &H256) -> Option; + fn block(&self, hash: &H256) -> Option; + fn block_status(&self, hash: &H256) -> BlockStatus; fn block_header_at(&self, n: BlockNumber) -> Option; fn block_body_at(&self, n: BlockNumber) -> Option; fn block_at(&self, n: BlockNumber) -> Option; fn block_status_at(&self, n: BlockNumber) -> BlockStatus; fn tree_route(&self, from: &H256, to: &H256) -> TreeRoute; - fn state_data(&self, h: &H256) -> Option; - fn block_receipts(&self, h: &H256) -> Option; - fn import_block(&mut self, b: &[u8]) -> ImportResult; + fn state_data(&self, hash: &H256) -> Option; + fn block_receipts(&self, hash: &H256) -> Option; + fn import_block(&mut self, byte: &[u8]) -> ImportResult; fn queue_status(&self) -> BlockQueueStatus; fn clear_queue(&mut self); fn info(&self) -> BlockChainInfo; diff --git a/src/lib.rs b/src/lib.rs index df0b0d8b6..0268b9935 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,8 @@ pub mod genesis; pub mod views; pub mod blockchain; pub mod extras; +pub mod client; pub mod eth; pub mod sync; + diff --git a/src/sync/chain.rs b/src/sync/chain.rs index 5d89115e3..4d2a6f990 100644 --- a/src/sync/chain.rs +++ b/src/sync/chain.rs @@ -202,7 +202,7 @@ impl ChainSync { self.highest_block = 0; self.have_common_block = false; io.chain().clear_queue(); - self.starting_block = io.chain().info().last_block_number; + self.starting_block = io.chain().info().best_block_number; self.state = SyncState::NotSynced; } @@ -516,7 +516,7 @@ impl ChainSync { if !self.have_common_block { // download backwards until common block is found 1 header at a time let chain_info = io.chain().info(); - start = chain_info.last_block_number as usize; + start = chain_info.best_block_number as usize; if !self.headers.is_empty() { start = min(start, self.headers.range_iter().next().unwrap().0 as usize - 1); } @@ -724,7 +724,7 @@ impl ChainSync { packet.append(&(PROTOCOL_VERSION as u32)); packet.append(&0u32); //TODO: network id packet.append(&chain.total_difficulty); - packet.append(&chain.last_block_hash); + packet.append(&chain.best_block_hash); packet.append(&chain.genesis_hash); //TODO: handle timeout for status request match io.send(*peer_id, STATUS_PACKET, packet.out()) { @@ -742,7 +742,7 @@ impl ChainSync { let max_headers: usize = r.val_at(1); let skip: usize = r.val_at(2); let reverse: bool = r.val_at(3); - let last = io.chain().info().last_block_number; + let last = io.chain().info().best_block_number; let mut number = if r.at(0).size() == 32 { // id is a hash let hash: H256 = r.val_at(0); diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 03a03f49d..a72aa5245 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs @@ -63,6 +63,13 @@ pub struct EthSync { pub use self::chain::SyncStatus; impl EthSync { + pub fn new(chain: Arc) -> EthSync { + EthSync { + chain: chain, + sync: ChainSync::new(), + } + } + pub fn is_syncing(&self) -> bool { self.sync.is_syncing() } diff --git a/src/sync/range_collection.rs b/src/sync/range_collection.rs index 5d19d0fd8..5aeadf75f 100644 --- a/src/sync/range_collection.rs +++ b/src/sync/range_collection.rs @@ -180,7 +180,7 @@ impl RangeCollection for Vec<(K, Vec)> where K: Ord + PartialEq + fn test_range() { use std::cmp::{Ordering}; - let mut ranges: Vec<(u32, Vec)> = Vec::new(); + let mut ranges: Vec<(u64, Vec)> = Vec::new(); assert_eq!(ranges.range_iter().next(), None); assert_eq!(ranges.find_item(&1), None); assert!(!ranges.have_item(&1)); diff --git a/src/sync/tests.rs b/src/sync/tests.rs index e5c8dfe43..7902d2270 100644 --- a/src/sync/tests.rs +++ b/src/sync/tests.rs @@ -169,8 +169,8 @@ impl BlockChainClient for TestBlockChainClient { total_difficulty: self.difficulty, pending_total_difficulty: self.difficulty, genesis_hash: self.genesis_hash.clone(), - last_block_hash: self.last_hash.clone(), - last_block_number: self.blocks.len() as BlockNumber - 1, + best_block_hash: self.last_hash.clone(), + best_block_number: self.blocks.len() as BlockNumber - 1, } } }