From 5346539ef83cfa2b3720265c0fcdddae9c6dc761 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Thu, 15 Dec 2016 18:45:11 +0100 Subject: [PATCH] minimal header import and client service --- ethcore/light/src/client/mod.rs | 29 +++++++++++- ethcore/light/src/client/service.rs | 73 +++++++++++++++++++++++++++++ sync/src/light_sync/sync_round.rs | 3 +- 3 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 ethcore/light/src/client/service.rs diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 4b8a37366..d51f2c484 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -35,13 +35,18 @@ use request; use self::header_chain::HeaderChain; +pub use self::service::Service; + pub mod cht; + mod header_chain; +mod service; /// Configuration for the light client. #[derive(Debug, Default, Clone)] pub struct Config { - queue: queue::Config, + /// Verification queue config. + pub queue: queue::Config, } /// Trait for interacting with the header chain abstractly. @@ -139,6 +144,28 @@ impl Client { pub fn cht_root(&self, i: usize) -> Option { self.chain.cht_root(i) } + + /// Import a set of pre-verified headers from the queue. + pub fn import_verified(&self) { + const MAX: usize = 256; + + let mut bad = Vec::new(); + let mut good = Vec::new(); + for verified_header in self.queue.drain(MAX) { + let hash = verified_header.hash(); + + match self.chain.insert(::rlp::encode(&verified_header).to_vec()) { + Ok(()) => good.push(hash), + Err(e) => { + debug!(target: "client", "Error importing header {}: {}", hash, e); + bad.push(hash); + } + } + } + + self.queue.mark_as_bad(&bad); + self.queue.mark_as_good(&good); + } } impl LightChainClient for Client { diff --git a/ethcore/light/src/client/service.rs b/ethcore/light/src/client/service.rs new file mode 100644 index 000000000..79c53bac6 --- /dev/null +++ b/ethcore/light/src/client/service.rs @@ -0,0 +1,73 @@ +// Copyright 2015, 2016 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Minimal IO service for light client. +//! Just handles block import messages and passes them to the client. + +use std::sync::Arc; + +use ethcore::service::ClientIoMessage; +use ethcore::spec::Spec; +use io::{IoContext, IoError, IoHandler, IoService}; + +use super::{Client, Config as ClientConfig}; + +/// Light client service. +pub struct Service { + client: Arc, + _io_service: IoService, +} + +impl Service { + /// Start the service: initialize I/O workers and client itself. + pub fn start(config: ClientConfig, spec: &Spec) -> Result { + let io_service = try!(IoService::::start()); + let client = Arc::new(Client::new(config, spec, io_service.channel())); + try!(io_service.register_handler(Arc::new(ImportBlocks(client.clone())))); + + Ok(Service { + client: client, + _io_service: io_service, + }) + } + + /// Get a handle to the client. + pub fn client(&self) -> &Arc { + &self.client + } +} + +struct ImportBlocks(Arc); + +impl IoHandler for ImportBlocks { + fn message(&self, _io: &IoContext, message: &ClientIoMessage) { + if let ClientIoMessage::BlockVerified = *message { + self.0.import_verified(); + } + } +} + +#[cfg(test)] +mod tests { + use super::Service; + use ethcore::spec::Spec; + + #[test] + fn it_works() { + let spec = Spec::new_test(); + Service::start(Default::default(), &spec).unwrap(); + } +} diff --git a/sync/src/light_sync/sync_round.rs b/sync/src/light_sync/sync_round.rs index 0442cc5ce..5f121d00c 100644 --- a/sync/src/light_sync/sync_round.rs +++ b/sync/src/light_sync/sync_round.rs @@ -225,6 +225,7 @@ impl Fetcher { } self.complete_requests.insert(subchain_parent, request); + self.collect_ready(); } // state transition not triggered until drain is finished. @@ -267,8 +268,6 @@ impl Fetcher { } fn drain(mut self, headers: &mut Vec
, max: usize) -> SyncRound { - self.collect_ready(); - let max = ::std::cmp::min(max, self.ready.len()); headers.extend(self.ready.drain(0..max));