light: search for common ancestor with peers
This commit is contained in:
parent
8c64400654
commit
6fb71527e4
@ -276,7 +276,7 @@ mod tests {
|
|||||||
header.set_timestamp(rolling_timestamp);
|
header.set_timestamp(rolling_timestamp);
|
||||||
header.set_difficulty(*genesis_header.difficulty() * i.into());
|
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();
|
parent_hash = header.hash();
|
||||||
rolling_timestamp += 10;
|
rolling_timestamp += 10;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
use ethcore::block_import_error::BlockImportError;
|
use ethcore::block_import_error::BlockImportError;
|
||||||
use ethcore::block_status::BlockStatus;
|
use ethcore::block_status::BlockStatus;
|
||||||
|
use ethcore::ids::BlockId;
|
||||||
use ethcore::verification::queue::{self, HeaderQueue};
|
use ethcore::verification::queue::{self, HeaderQueue};
|
||||||
use ethcore::transaction::SignedTransaction;
|
use ethcore::transaction::SignedTransaction;
|
||||||
use ethcore::blockchain_info::BlockChainInfo;
|
use ethcore::blockchain_info::BlockChainInfo;
|
||||||
@ -33,7 +34,7 @@ use request;
|
|||||||
|
|
||||||
use self::header_chain::HeaderChain;
|
use self::header_chain::HeaderChain;
|
||||||
|
|
||||||
mod cht;
|
pub mod cht;
|
||||||
mod header_chain;
|
mod header_chain;
|
||||||
|
|
||||||
/// Configuration for the light client.
|
/// Configuration for the light client.
|
||||||
@ -84,16 +85,8 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the header queue info.
|
/// Get the chain info.
|
||||||
pub fn queue_info(&self) -> queue::QueueInfo {
|
pub fn chain_info(&self) -> BlockChainInfo {
|
||||||
self.queue.queue_info()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// dummy implementation -- may draw from canonical cache further on.
|
|
||||||
impl Provider for Client {
|
|
||||||
fn chain_info(&self) -> BlockChainInfo {
|
|
||||||
let best_block = self.chain.best_block();
|
let best_block = self.chain.best_block();
|
||||||
let first_block = self.chain.first_block();
|
let first_block = self.chain.first_block();
|
||||||
let genesis_hash = self.chain.genesis_hash();
|
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<Bytes> {
|
||||||
|
self.chain.get_header(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `i`th CHT root.
|
||||||
|
pub fn cht_root(&self, i: usize) -> Option<H256> {
|
||||||
|
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<u64> {
|
fn reorg_depth(&self, _a: &H256, _b: &H256) -> Option<u64> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ use request::{self, HashOrNumber, Request};
|
|||||||
|
|
||||||
use self::buffer_flow::{Buffer, FlowParams};
|
use self::buffer_flow::{Buffer, FlowParams};
|
||||||
use self::context::Ctx;
|
use self::context::Ctx;
|
||||||
use self::error::{Error, Punishment};
|
use self::error::Punishment;
|
||||||
|
|
||||||
mod buffer_flow;
|
mod buffer_flow;
|
||||||
mod context;
|
mod context;
|
||||||
@ -48,6 +48,7 @@ mod status;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
pub use self::error::Error;
|
||||||
pub use self::context::{EventContext, IoContext};
|
pub use self::context::{EventContext, IoContext};
|
||||||
pub use self::status::{Status, Capabilities, Announcement};
|
pub use self::status::{Status, Capabilities, Announcement};
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ extern crate ethcore_ipc as ipc;
|
|||||||
mod chain;
|
mod chain;
|
||||||
mod blocks;
|
mod blocks;
|
||||||
mod block_sync;
|
mod block_sync;
|
||||||
|
mod light_sync;
|
||||||
mod sync_io;
|
mod sync_io;
|
||||||
mod snapshot;
|
mod snapshot;
|
||||||
mod transactions_stats;
|
mod transactions_stats;
|
||||||
|
@ -28,12 +28,14 @@ use std::collections::{BinaryHeap, HashMap};
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use light::client::{Client, BlockDescriptor};
|
use ethcore::header::Header;
|
||||||
use light::net::{Error as NetError, Handler, EventContext, Capabilities, ReqId};
|
|
||||||
|
use light::client::Client;
|
||||||
|
use light::net::{Announcement, Error as NetError, Handler, EventContext, Capabilities, ReqId, Status};
|
||||||
use light::request;
|
use light::request;
|
||||||
use network::PeerId;
|
use network::PeerId;
|
||||||
use rlp::{UntrustedRlp, View};
|
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
|
// How many headers we request at a time when searching for best
|
||||||
// common ancestor with peer.
|
// common ancestor with peer.
|
||||||
@ -53,6 +55,12 @@ enum Error {
|
|||||||
ProtocolLevel(NetError),
|
ProtocolLevel(NetError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<NetError> for Error {
|
||||||
|
fn from(net_error: NetError) -> Self {
|
||||||
|
Error::ProtocolLevel(net_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
@ -87,13 +95,13 @@ impl UnconfirmedPeer {
|
|||||||
fn create(ctx: &EventContext, chain_info: ChainInfo, best_num: u64) -> Result<Self, Error> {
|
fn create(ctx: &EventContext, chain_info: ChainInfo, best_num: u64) -> Result<Self, Error> {
|
||||||
let this = ctx.peer();
|
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.
|
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 {
|
let req_id = try!(ctx.request_from(this, request::Request::Headers(request::Headers {
|
||||||
start: best_num.into(),
|
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,
|
skip: 0,
|
||||||
reverse: true,
|
reverse: true,
|
||||||
})));
|
})));
|
||||||
@ -101,7 +109,7 @@ impl UnconfirmedPeer {
|
|||||||
Ok(UnconfirmedPeer {
|
Ok(UnconfirmedPeer {
|
||||||
chain_info: chain_info,
|
chain_info: chain_info,
|
||||||
last_batched: best_num,
|
last_batched: best_num,
|
||||||
req_id: ReqId,
|
req_id: req_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,13 +150,15 @@ impl UnconfirmedPeer {
|
|||||||
// nothing found, nothing prehistoric.
|
// nothing found, nothing prehistoric.
|
||||||
// send the next request.
|
// send the next request.
|
||||||
let req_id = try!(ctx.request_from(this, request::Request::Headers(request::Headers {
|
let req_id = try!(ctx.request_from(this, request::Request::Headers(request::Headers {
|
||||||
start: cur_num,
|
start: cur_num.into(),
|
||||||
max: ::std::cmp::min(cur_num, UNCONFIRMED_SEARCH_SIZE),
|
max: ::std::cmp::min(cur_num, UNCONFIRMED_SEARCH_SIZE) as usize,
|
||||||
skip: 0,
|
skip: 0,
|
||||||
reverse: true,
|
reverse: true,
|
||||||
})));
|
})));
|
||||||
|
|
||||||
self.req_id = req_id;
|
self.req_id = req_id;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,13 +178,13 @@ pub struct LightSync {
|
|||||||
best_seen: Mutex<Option<(H256, U256)>>, // best seen block on the network.
|
best_seen: Mutex<Option<(H256, U256)>>, // best seen block on the network.
|
||||||
peers: RwLock<HashMap<PeerId, Peer>>, // peers which are relevant to synchronization.
|
peers: RwLock<HashMap<PeerId, Peer>>, // peers which are relevant to synchronization.
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
downloader: Downloader,
|
|
||||||
assigned_requests: HashMap<ReqId, HeaderRequest>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handler for LightSync {
|
impl Handler for LightSync {
|
||||||
fn on_connect(&self, ctx: &EventContext, status: &Status, capabilities: &Capabilities) {
|
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());
|
trace!(target: "sync", "Ignoring irrelevant peer: {}", ctx.peer());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -184,7 +194,6 @@ impl Handler for LightSync {
|
|||||||
head_hash: status.head_hash,
|
head_hash: status.head_hash,
|
||||||
head_num: status.head_num,
|
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) {
|
let unconfirmed = match UnconfirmedPeer::create(ctx, chain_info, our_best) {
|
||||||
Ok(unconfirmed) => unconfirmed,
|
Ok(unconfirmed) => unconfirmed,
|
||||||
Err(e) => {
|
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<Client>) -> Self {
|
pub fn new(client: Arc<Client>) -> Self {
|
||||||
LightSync {
|
LightSync {
|
||||||
best_seen: Mutex::new(None),
|
best_seen: Mutex::new(None),
|
||||||
peers: HashMap::new(),
|
peers: RwLock::new(HashMap::new()),
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user