From 6fb71527e48605325070f7df2d1a6640ce98eebb Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 13 Dec 2016 21:09:57 +0100 Subject: [PATCH] light: search for common ancestor with peers --- ethcore/light/src/client/header_chain.rs | 2 +- ethcore/light/src/client/mod.rs | 37 +++++++++++++++++------- ethcore/light/src/net/mod.rs | 3 +- sync/src/lib.rs | 1 + sync/src/light_sync/mod.rs | 37 +++++++++++++++--------- 5 files changed, 53 insertions(+), 27 deletions(-) diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index f350f19ca..847b0251f 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -276,7 +276,7 @@ mod tests { header.set_timestamp(rolling_timestamp); header.set_difficulty(*genesis_header.difficulty() * i.into()); - chain.insert(::rlp::encode(&header).to_vec()); + chain.insert(::rlp::encode(&header).to_vec()).unwrap(); parent_hash = header.hash(); rolling_timestamp += 10; diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 32725cc1a..1ddcb0515 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -18,6 +18,7 @@ use ethcore::block_import_error::BlockImportError; use ethcore::block_status::BlockStatus; +use ethcore::ids::BlockId; use ethcore::verification::queue::{self, HeaderQueue}; use ethcore::transaction::SignedTransaction; use ethcore::blockchain_info::BlockChainInfo; @@ -33,7 +34,7 @@ use request; use self::header_chain::HeaderChain; -mod cht; +pub mod cht; mod header_chain; /// Configuration for the light client. @@ -84,16 +85,8 @@ impl Client { } } - /// Get the header queue info. - pub fn queue_info(&self) -> queue::QueueInfo { - self.queue.queue_info() - } - -} - -// dummy implementation -- may draw from canonical cache further on. -impl Provider for Client { - fn chain_info(&self) -> BlockChainInfo { + /// Get the chain info. + pub fn chain_info(&self) -> BlockChainInfo { let best_block = self.chain.best_block(); let first_block = self.chain.first_block(); let genesis_hash = self.chain.genesis_hash(); @@ -111,6 +104,28 @@ impl Provider for Client { } } + /// Get the header queue info. + pub fn queue_info(&self) -> queue::QueueInfo { + self.queue.queue_info() + } + + /// Get a block header by Id. + pub fn get_header(&self, id: BlockId) -> Option { + self.chain.get_header(id) + } + + /// Get the `i`th CHT root. + pub fn cht_root(&self, i: usize) -> Option { + self.chain.cht_root(i) + } +} + +// dummy implementation -- may draw from canonical cache further on. +impl Provider for Client { + fn chain_info(&self) -> BlockChainInfo { + Client::chain_info(self) + } + fn reorg_depth(&self, _a: &H256, _b: &H256) -> Option { None } diff --git a/ethcore/light/src/net/mod.rs b/ethcore/light/src/net/mod.rs index 326c234ca..6da964f99 100644 --- a/ethcore/light/src/net/mod.rs +++ b/ethcore/light/src/net/mod.rs @@ -38,7 +38,7 @@ use request::{self, HashOrNumber, Request}; use self::buffer_flow::{Buffer, FlowParams}; use self::context::Ctx; -use self::error::{Error, Punishment}; +use self::error::Punishment; mod buffer_flow; mod context; @@ -48,6 +48,7 @@ mod status; #[cfg(test)] mod tests; +pub use self::error::Error; pub use self::context::{EventContext, IoContext}; pub use self::status::{Status, Capabilities, Announcement}; diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 0ff3bfe66..fc9e5de74 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -54,6 +54,7 @@ extern crate ethcore_ipc as ipc; mod chain; mod blocks; mod block_sync; +mod light_sync; mod sync_io; mod snapshot; mod transactions_stats; diff --git a/sync/src/light_sync/mod.rs b/sync/src/light_sync/mod.rs index d49b0dc17..15e4d72d4 100644 --- a/sync/src/light_sync/mod.rs +++ b/sync/src/light_sync/mod.rs @@ -28,12 +28,14 @@ use std::collections::{BinaryHeap, HashMap}; use std::fmt; use std::sync::Arc; -use light::client::{Client, BlockDescriptor}; -use light::net::{Error as NetError, Handler, EventContext, Capabilities, ReqId}; +use ethcore::header::Header; + +use light::client::Client; +use light::net::{Announcement, Error as NetError, Handler, EventContext, Capabilities, ReqId, Status}; use light::request; use network::PeerId; use rlp::{UntrustedRlp, View}; -use util::{U256, H256}; +use util::{Bytes, U256, H256, Mutex, RwLock}; // How many headers we request at a time when searching for best // common ancestor with peer. @@ -53,6 +55,12 @@ enum Error { ProtocolLevel(NetError), } +impl From for Error { + fn from(net_error: NetError) -> Self { + Error::ProtocolLevel(net_error) + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -87,13 +95,13 @@ impl UnconfirmedPeer { fn create(ctx: &EventContext, chain_info: ChainInfo, best_num: u64) -> Result { let this = ctx.peer(); - if ctx.max_requests(this, request::Kind::Headers) < UNCONFIRMED_SEARCH_SIZE { + if ctx.max_requests(this, request::Kind::Headers) < UNCONFIRMED_SEARCH_SIZE as usize { return Err(Error::UselessPeer); // a peer which allows this few header reqs isn't useful anyway. } let req_id = try!(ctx.request_from(this, request::Request::Headers(request::Headers { start: best_num.into(), - max: ::std::cmp::min(best_num, UNCONFIRMED_SEARCH_SIZE), + max: ::std::cmp::min(best_num, UNCONFIRMED_SEARCH_SIZE) as usize, skip: 0, reverse: true, }))); @@ -101,7 +109,7 @@ impl UnconfirmedPeer { Ok(UnconfirmedPeer { chain_info: chain_info, last_batched: best_num, - req_id: ReqId, + req_id: req_id, }) } @@ -142,13 +150,15 @@ impl UnconfirmedPeer { // nothing found, nothing prehistoric. // send the next request. let req_id = try!(ctx.request_from(this, request::Request::Headers(request::Headers { - start: cur_num, - max: ::std::cmp::min(cur_num, UNCONFIRMED_SEARCH_SIZE), + start: cur_num.into(), + max: ::std::cmp::min(cur_num, UNCONFIRMED_SEARCH_SIZE) as usize, skip: 0, reverse: true, }))); self.req_id = req_id; + + Ok(None) } } @@ -168,13 +178,13 @@ pub struct LightSync { best_seen: Mutex>, // best seen block on the network. peers: RwLock>, // peers which are relevant to synchronization. client: Arc, - downloader: Downloader, - assigned_requests: HashMap, } impl Handler for LightSync { fn on_connect(&self, ctx: &EventContext, status: &Status, capabilities: &Capabilities) { - if !capabilities.serve_headers || status.head_num <= self.client.best_block().number { + let our_best = self.client.chain_info().best_block_number; + + if !capabilities.serve_headers || status.head_num <= our_best { trace!(target: "sync", "Ignoring irrelevant peer: {}", ctx.peer()); return; } @@ -184,7 +194,6 @@ impl Handler for LightSync { head_hash: status.head_hash, head_num: status.head_num, }; - let our_best = self.client.chain_info().best_block_number; let unconfirmed = match UnconfirmedPeer::create(ctx, chain_info, our_best) { Ok(unconfirmed) => unconfirmed, Err(e) => { @@ -193,7 +202,7 @@ impl Handler for LightSync { } }; - self.peers.write().insert(ctx.peer(), Mutex::new(unconfirmed)); + self.peers.write().insert(ctx.peer(), Peer::SearchCommon(Mutex::new(unconfirmed))); } } @@ -206,7 +215,7 @@ impl LightSync { pub fn new(client: Arc) -> Self { LightSync { best_seen: Mutex::new(None), - peers: HashMap::new(), + peers: RwLock::new(HashMap::new()), client: client, } }