Client app

This commit is contained in:
arkpar 2016-01-07 16:08:12 +01:00
parent aff4e24775
commit 2a4d470039
8 changed files with 83 additions and 60 deletions

View File

@ -1,15 +1,28 @@
extern crate ethcore_util as util; extern crate ethcore_util as util;
extern crate ethcore;
extern crate rustc_serialize;
use std::io::*; use std::io::*;
use std::env;
use std::sync::Arc;
use rustc_serialize::hex::FromHex;
use util::hash::*;
use util::network::{NetworkService}; use util::network::{NetworkService};
use ethcore::client::Client;
use ethcore::sync::EthSync;
fn main() { 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 { loop {
let mut cmd = String::new(); let mut cmd = String::new();
stdin().read_line(&mut cmd).unwrap(); stdin().read_line(&mut cmd).unwrap();
if cmd == "quit" || cmd == "exit" || cmd == "q" { if cmd == "quit\n" || cmd == "exit\n" || cmd == "q\n" {
break; break;
} }
} }

View File

@ -1,9 +1,9 @@
//! Fast access to blockchain data. //! Fast access to blockchain data.
use std::collections::HashMap; use std::collections::HashMap;
use std::cell::RefCell;
use std::path::Path; use std::path::Path;
use std::hash::Hash; use std::hash::Hash;
use std::sync::RwLock;
use rocksdb::{DB, WriteBatch, Writable}; use rocksdb::{DB, WriteBatch, Writable};
use heapsize::HeapSizeOf; use heapsize::HeapSizeOf;
use util::hash::*; use util::hash::*;
@ -62,17 +62,17 @@ impl BestBlock {
/// ///
/// **Does not do input data verification.** /// **Does not do input data verification.**
pub struct BlockChain { pub struct BlockChain {
best_block: RefCell<BestBlock>, best_block: RwLock<BestBlock>,
// block cache // block cache
blocks: RefCell<HashMap<H256, Bytes>>, blocks: RwLock<HashMap<H256, Bytes>>,
// extra caches // extra caches
block_details: RefCell<HashMap<H256, BlockDetails>>, block_details: RwLock<HashMap<H256, BlockDetails>>,
block_hashes: RefCell<HashMap<U256, H256>>, block_hashes: RwLock<HashMap<U256, H256>>,
transaction_addresses: RefCell<HashMap<H256, TransactionAddress>>, transaction_addresses: RwLock<HashMap<H256, TransactionAddress>>,
block_logs: RefCell<HashMap<H256, BlockLogBlooms>>, block_logs: RwLock<HashMap<H256, BlockLogBlooms>>,
blocks_blooms: RefCell<HashMap<H256, BlocksBlooms>>, blocks_blooms: RwLock<HashMap<H256, BlocksBlooms>>,
extras_db: DB, extras_db: DB,
blocks_db: DB blocks_db: DB
@ -117,13 +117,13 @@ impl BlockChain {
let blocks_db = DB::open_default(blocks_path.to_str().unwrap()).unwrap(); let blocks_db = DB::open_default(blocks_path.to_str().unwrap()).unwrap();
let bc = BlockChain { let bc = BlockChain {
best_block: RefCell::new(BestBlock::new()), best_block: RwLock::new(BestBlock::new()),
blocks: RefCell::new(HashMap::new()), blocks: RwLock::new(HashMap::new()),
block_details: RefCell::new(HashMap::new()), block_details: RwLock::new(HashMap::new()),
block_hashes: RefCell::new(HashMap::new()), block_hashes: RwLock::new(HashMap::new()),
transaction_addresses: RefCell::new(HashMap::new()), transaction_addresses: RwLock::new(HashMap::new()),
block_logs: RefCell::new(HashMap::new()), block_logs: RwLock::new(HashMap::new()),
blocks_blooms: RefCell::new(HashMap::new()), blocks_blooms: RwLock::new(HashMap::new()),
extras_db: extras_db, extras_db: extras_db,
blocks_db: blocks_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.number = bc.block_number(&best_block_hash).unwrap();
best_block.total_difficulty = bc.block_details(&best_block_hash).unwrap().total_difficulty; best_block.total_difficulty = bc.block_details(&best_block_hash).unwrap().total_difficulty;
best_block.hash = best_block_hash; best_block.hash = best_block_hash;
@ -272,7 +272,7 @@ impl BlockChain {
// create views onto rlp // create views onto rlp
let block = BlockView::new(bytes); let block = BlockView::new(bytes);
let header = block.header_view(); let header = block.header_view();
let hash = block.sha3(); let hash = header.sha3();
if self.is_known(&hash) { if self.is_known(&hash) {
return; return;
@ -283,13 +283,13 @@ impl BlockChain {
let (batch, new_best) = self.block_to_extras_insert_batch(bytes); let (batch, new_best) = self.block_to_extras_insert_batch(bytes);
// update best block // 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 { if let Some(b) = new_best {
*best_block = b; *best_block = b;
} }
// update caches // update caches
let mut write = self.block_details.borrow_mut(); let mut write = self.block_details.write().unwrap();
write.remove(&header.parent_hash()); write.remove(&header.parent_hash());
// update extras database // update extras database
@ -425,17 +425,17 @@ impl BlockChain {
/// Get best block hash. /// Get best block hash.
pub fn best_block_hash(&self) -> H256 { pub fn best_block_hash(&self) -> H256 {
self.best_block.borrow().hash.clone() self.best_block.read().unwrap().hash.clone()
} }
/// Get best block number. /// Get best block number.
pub fn best_block_number(&self) -> U256 { pub fn best_block_number(&self) -> U256 {
self.best_block.borrow().number self.best_block.read().unwrap().number
} }
/// Get best block total difficulty. /// Get best block total difficulty.
pub fn best_block_total_difficulty(&self) -> U256 { 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. /// Get the number of given block's hash.
@ -448,9 +448,10 @@ impl BlockChain {
self.query_extras(hash, &self.block_logs) self.query_extras(hash, &self.block_logs)
} }
fn block(&self, hash: &H256) -> Option<Bytes> { /// Get raw block data
pub fn block(&self, hash: &H256) -> Option<Bytes> {
{ {
let read = self.blocks.borrow(); let read = self.blocks.read().unwrap();
match read.get(hash) { match read.get(hash) {
Some(v) => return Some(v.clone()), Some(v) => return Some(v.clone()),
None => () None => ()
@ -463,7 +464,7 @@ impl BlockChain {
match opt { match opt {
Some(b) => { Some(b) => {
let bytes: Bytes = b.to_vec(); 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()); write.insert(hash.clone(), bytes.clone());
Some(bytes) Some(bytes)
}, },
@ -471,11 +472,11 @@ impl BlockChain {
} }
} }
fn query_extras<K, T>(&self, hash: &K, cache: &RefCell<HashMap<K, T>>) -> Option<T> where fn query_extras<K, T>(&self, hash: &K, cache: &RwLock<HashMap<K, T>>) -> Option<T> where
T: Clone + Decodable + ExtrasIndexable, T: Clone + Decodable + ExtrasIndexable,
K: ExtrasSliceConvertable + Eq + Hash + Clone { K: ExtrasSliceConvertable + Eq + Hash + Clone {
{ {
let read = cache.borrow(); let read = cache.read().unwrap();
match read.get(hash) { match read.get(hash) {
Some(v) => return Some(v.clone()), Some(v) => return Some(v.clone()),
None => () None => ()
@ -483,17 +484,17 @@ impl BlockChain {
} }
self.extras_db.get_extras(hash).map(| t: T | { 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()); write.insert(hash.clone(), t.clone());
t t
}) })
} }
fn query_extras_exist<K, T>(&self, hash: &K, cache: &RefCell<HashMap<K, T>>) -> bool where fn query_extras_exist<K, T>(&self, hash: &K, cache: &RwLock<HashMap<K, T>>) -> bool where
K: ExtrasSliceConvertable + Eq + Hash + Clone, K: ExtrasSliceConvertable + Eq + Hash + Clone,
T: ExtrasIndexable { T: ExtrasIndexable {
{ {
let read = cache.borrow(); let read = cache.read().unwrap();
match read.get(hash) { match read.get(hash) {
Some(_) => return true, Some(_) => return true,
None => () None => ()
@ -506,21 +507,21 @@ impl BlockChain {
/// Get current cache size. /// Get current cache size.
pub fn cache_size(&self) -> CacheSize { pub fn cache_size(&self) -> CacheSize {
CacheSize { CacheSize {
blocks: self.blocks.heap_size_of_children(), blocks: self.blocks.read().unwrap().heap_size_of_children(),
block_details: self.block_details.heap_size_of_children(), block_details: self.block_details.read().unwrap().heap_size_of_children(),
transaction_addresses: self.transaction_addresses.heap_size_of_children(), transaction_addresses: self.transaction_addresses.read().unwrap().heap_size_of_children(),
block_logs: self.block_logs.heap_size_of_children(), block_logs: self.block_logs.read().unwrap().heap_size_of_children(),
blocks_blooms: self.blocks_blooms.heap_size_of_children() blocks_blooms: self.blocks_blooms.read().unwrap().heap_size_of_children()
} }
} }
/// Tries to squeeze the cache if its too big. /// Tries to squeeze the cache if its too big.
pub fn squeeze_to_fit(&self, size: CacheSize) { pub fn squeeze_to_fit(&self, size: CacheSize) {
self.blocks.borrow_mut().squeeze(size.blocks); self.blocks.write().unwrap().squeeze(size.blocks);
self.block_details.borrow_mut().squeeze(size.block_details); self.block_details.write().unwrap().squeeze(size.block_details);
self.transaction_addresses.borrow_mut().squeeze(size.transaction_addresses); self.transaction_addresses.write().unwrap().squeeze(size.transaction_addresses);
self.block_logs.borrow_mut().squeeze(size.block_logs); self.block_logs.write().unwrap().squeeze(size.block_logs);
self.blocks_blooms.borrow_mut().squeeze(size.blocks_blooms); self.blocks_blooms.write().unwrap().squeeze(size.blocks_blooms);
} }
} }

View File

@ -27,8 +27,8 @@ pub struct BlockChainInfo {
pub total_difficulty: U256, pub total_difficulty: U256,
pub pending_total_difficulty: U256, pub pending_total_difficulty: U256,
pub genesis_hash: H256, pub genesis_hash: H256,
pub last_block_hash: H256, pub best_block_hash: H256,
pub last_block_number: BlockNumber pub best_block_number: BlockNumber
} }
pub struct BlockQueueStatus { pub struct BlockQueueStatus {
@ -37,21 +37,21 @@ pub struct BlockQueueStatus {
pub type TreeRoute = ::blockchain::TreeRoute; pub type TreeRoute = ::blockchain::TreeRoute;
pub type BlockNumber = u32; pub type BlockNumber = u64;
pub trait BlockChainClient : Sync { pub trait BlockChainClient : Sync {
fn block_header(&self, h: &H256) -> Option<Bytes>; fn block_header(&self, hash: &H256) -> Option<Bytes>;
fn block_body(&self, h: &H256) -> Option<Bytes>; fn block_body(&self, hash: &H256) -> Option<Bytes>;
fn block(&self, h: &H256) -> Option<Bytes>; fn block(&self, hash: &H256) -> Option<Bytes>;
fn block_status(&self, h: &H256) -> BlockStatus; fn block_status(&self, hash: &H256) -> BlockStatus;
fn block_header_at(&self, n: BlockNumber) -> Option<Bytes>; fn block_header_at(&self, n: BlockNumber) -> Option<Bytes>;
fn block_body_at(&self, n: BlockNumber) -> Option<Bytes>; fn block_body_at(&self, n: BlockNumber) -> Option<Bytes>;
fn block_at(&self, n: BlockNumber) -> Option<Bytes>; fn block_at(&self, n: BlockNumber) -> Option<Bytes>;
fn block_status_at(&self, n: BlockNumber) -> BlockStatus; fn block_status_at(&self, n: BlockNumber) -> BlockStatus;
fn tree_route(&self, from: &H256, to: &H256) -> TreeRoute; fn tree_route(&self, from: &H256, to: &H256) -> TreeRoute;
fn state_data(&self, h: &H256) -> Option<Bytes>; fn state_data(&self, hash: &H256) -> Option<Bytes>;
fn block_receipts(&self, h: &H256) -> Option<Bytes>; fn block_receipts(&self, hash: &H256) -> Option<Bytes>;
fn import_block(&mut self, b: &[u8]) -> ImportResult; fn import_block(&mut self, byte: &[u8]) -> ImportResult;
fn queue_status(&self) -> BlockQueueStatus; fn queue_status(&self) -> BlockQueueStatus;
fn clear_queue(&mut self); fn clear_queue(&mut self);
fn info(&self) -> BlockChainInfo; fn info(&self) -> BlockChainInfo;

View File

@ -104,6 +104,8 @@ pub mod genesis;
pub mod views; pub mod views;
pub mod blockchain; pub mod blockchain;
pub mod extras; pub mod extras;
pub mod client;
pub mod eth; pub mod eth;
pub mod sync; pub mod sync;

View File

@ -202,7 +202,7 @@ impl ChainSync {
self.highest_block = 0; self.highest_block = 0;
self.have_common_block = false; self.have_common_block = false;
io.chain().clear_queue(); 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; self.state = SyncState::NotSynced;
} }
@ -516,7 +516,7 @@ impl ChainSync {
if !self.have_common_block { if !self.have_common_block {
// download backwards until common block is found 1 header at a time // download backwards until common block is found 1 header at a time
let chain_info = io.chain().info(); 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() { if !self.headers.is_empty() {
start = min(start, self.headers.range_iter().next().unwrap().0 as usize - 1); 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(&(PROTOCOL_VERSION as u32));
packet.append(&0u32); //TODO: network id packet.append(&0u32); //TODO: network id
packet.append(&chain.total_difficulty); packet.append(&chain.total_difficulty);
packet.append(&chain.last_block_hash); packet.append(&chain.best_block_hash);
packet.append(&chain.genesis_hash); packet.append(&chain.genesis_hash);
//TODO: handle timeout for status request //TODO: handle timeout for status request
match io.send(*peer_id, STATUS_PACKET, packet.out()) { match io.send(*peer_id, STATUS_PACKET, packet.out()) {
@ -742,7 +742,7 @@ impl ChainSync {
let max_headers: usize = r.val_at(1); let max_headers: usize = r.val_at(1);
let skip: usize = r.val_at(2); let skip: usize = r.val_at(2);
let reverse: bool = r.val_at(3); 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 { let mut number = if r.at(0).size() == 32 {
// id is a hash // id is a hash
let hash: H256 = r.val_at(0); let hash: H256 = r.val_at(0);

View File

@ -63,6 +63,13 @@ pub struct EthSync {
pub use self::chain::SyncStatus; pub use self::chain::SyncStatus;
impl EthSync { impl EthSync {
pub fn new(chain: Arc<BlockChainClient+Send+Sized>) -> EthSync {
EthSync {
chain: chain,
sync: ChainSync::new(),
}
}
pub fn is_syncing(&self) -> bool { pub fn is_syncing(&self) -> bool {
self.sync.is_syncing() self.sync.is_syncing()
} }

View File

@ -180,7 +180,7 @@ impl<K, V> RangeCollection<K, V> for Vec<(K, Vec<V>)> where K: Ord + PartialEq +
fn test_range() { fn test_range() {
use std::cmp::{Ordering}; use std::cmp::{Ordering};
let mut ranges: Vec<(u32, Vec<char>)> = Vec::new(); let mut ranges: Vec<(u64, Vec<char>)> = Vec::new();
assert_eq!(ranges.range_iter().next(), None); assert_eq!(ranges.range_iter().next(), None);
assert_eq!(ranges.find_item(&1), None); assert_eq!(ranges.find_item(&1), None);
assert!(!ranges.have_item(&1)); assert!(!ranges.have_item(&1));

View File

@ -169,8 +169,8 @@ impl BlockChainClient for TestBlockChainClient {
total_difficulty: self.difficulty, total_difficulty: self.difficulty,
pending_total_difficulty: self.difficulty, pending_total_difficulty: self.difficulty,
genesis_hash: self.genesis_hash.clone(), genesis_hash: self.genesis_hash.clone(),
last_block_hash: self.last_hash.clone(), best_block_hash: self.last_hash.clone(),
last_block_number: self.blocks.len() as BlockNumber - 1, best_block_number: self.blocks.len() as BlockNumber - 1,
} }
} }
} }