Client app
This commit is contained in:
parent
aff4e24775
commit
2a4d470039
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<BestBlock>,
|
||||
best_block: RwLock<BestBlock>,
|
||||
|
||||
// block cache
|
||||
blocks: RefCell<HashMap<H256, Bytes>>,
|
||||
blocks: RwLock<HashMap<H256, Bytes>>,
|
||||
|
||||
// extra caches
|
||||
block_details: RefCell<HashMap<H256, BlockDetails>>,
|
||||
block_hashes: RefCell<HashMap<U256, H256>>,
|
||||
transaction_addresses: RefCell<HashMap<H256, TransactionAddress>>,
|
||||
block_logs: RefCell<HashMap<H256, BlockLogBlooms>>,
|
||||
blocks_blooms: RefCell<HashMap<H256, BlocksBlooms>>,
|
||||
block_details: RwLock<HashMap<H256, BlockDetails>>,
|
||||
block_hashes: RwLock<HashMap<U256, H256>>,
|
||||
transaction_addresses: RwLock<HashMap<H256, TransactionAddress>>,
|
||||
block_logs: RwLock<HashMap<H256, BlockLogBlooms>>,
|
||||
blocks_blooms: RwLock<HashMap<H256, BlocksBlooms>>,
|
||||
|
||||
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<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) {
|
||||
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<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,
|
||||
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<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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
20
src/eth.rs
20
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<Bytes>;
|
||||
fn block_body(&self, h: &H256) -> Option<Bytes>;
|
||||
fn block(&self, h: &H256) -> Option<Bytes>;
|
||||
fn block_status(&self, h: &H256) -> BlockStatus;
|
||||
fn block_header(&self, hash: &H256) -> Option<Bytes>;
|
||||
fn block_body(&self, hash: &H256) -> Option<Bytes>;
|
||||
fn block(&self, hash: &H256) -> Option<Bytes>;
|
||||
fn block_status(&self, hash: &H256) -> BlockStatus;
|
||||
fn block_header_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_status_at(&self, n: BlockNumber) -> BlockStatus;
|
||||
fn tree_route(&self, from: &H256, to: &H256) -> TreeRoute;
|
||||
fn state_data(&self, h: &H256) -> Option<Bytes>;
|
||||
fn block_receipts(&self, h: &H256) -> Option<Bytes>;
|
||||
fn import_block(&mut self, b: &[u8]) -> ImportResult;
|
||||
fn state_data(&self, hash: &H256) -> Option<Bytes>;
|
||||
fn block_receipts(&self, hash: &H256) -> Option<Bytes>;
|
||||
fn import_block(&mut self, byte: &[u8]) -> ImportResult;
|
||||
fn queue_status(&self) -> BlockQueueStatus;
|
||||
fn clear_queue(&mut self);
|
||||
fn info(&self) -> BlockChainInfo;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -63,6 +63,13 @@ pub struct EthSync {
|
||||
pub use self::chain::SyncStatus;
|
||||
|
||||
impl EthSync {
|
||||
pub fn new(chain: Arc<BlockChainClient+Send+Sized>) -> EthSync {
|
||||
EthSync {
|
||||
chain: chain,
|
||||
sync: ChainSync::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_syncing(&self) -> bool {
|
||||
self.sync.is_syncing()
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ impl<K, V> RangeCollection<K, V> for Vec<(K, Vec<V>)> where K: Ord + PartialEq +
|
||||
fn test_range() {
|
||||
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.find_item(&1), None);
|
||||
assert!(!ranges.have_item(&1));
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user