// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see .
//! Light client implementation. Stores data from light sync
use std::sync::{Weak, Arc};
use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage};
use ethcore::engines::{epoch, Engine, EpochChange, EpochTransition, Proof};
use ethcore::verification::queue::{self, HeaderQueue};
use ethcore::spec::{Spec, SpecHardcodedSync};
use io::IoChannel;
use parking_lot::{Mutex, RwLock};
use ethereum_types::{H256, U256};
use futures::{IntoFuture, Future};
use common_types::{
BlockNumber,
block_status::BlockStatus,
blockchain_info::BlockChainInfo,
encoded,
errors::EthcoreError as Error,
errors::EthcoreResult,
header::Header,
ids::BlockId,
verification_queue_info::VerificationQueueInfo as BlockQueueInfo,
};
use kvdb::KeyValueDB;
use self::fetch::ChainDataFetcher;
use self::header_chain::{AncestryIter, HeaderChain, HardcodedSync};
use cache::Cache;
pub use self::service::Service;
mod header_chain;
mod service;
pub mod fetch;
/// Configuration for the light client.
#[derive(Debug, Clone)]
pub struct Config {
/// Verification queue config.
pub queue: queue::Config,
/// Chain column in database.
pub chain_column: Option,
/// Should it do full verification of blocks?
pub verify_full: bool,
/// Should it check the seal of blocks?
pub check_seal: bool,
/// Disable hardcoded sync.
pub no_hardcoded_sync: bool,
}
impl Default for Config {
fn default() -> Config {
Config {
queue: Default::default(),
chain_column: None,
verify_full: true,
check_seal: true,
no_hardcoded_sync: false,
}
}
}
/// Trait for interacting with the header chain abstractly.
pub trait LightChainClient: Send + Sync {
/// Adds a new `LightChainNotify` listener.
fn add_listener(&self, listener: Weak);
/// Get chain info.
fn chain_info(&self) -> BlockChainInfo;
/// Queue header to be verified. Required that all headers queued have their
/// parent queued prior.
fn queue_header(&self, header: Header) -> EthcoreResult;
/// Attempt to get a block hash by block id.
fn block_hash(&self, id: BlockId) -> Option;
/// Get block queue information.
fn queue_info(&self) -> BlockQueueInfo;
/// Attempt to get block header by block id.
fn block_header(&self, id: BlockId) -> Option;
/// Get the best block header.
fn best_block_header(&self) -> encoded::Header;
/// Get a block's chain score by ID.
fn score(&self, id: BlockId) -> Option;
/// Get an iterator over a block and its ancestry.
fn ancestry_iter<'a>(&'a self, start: BlockId) -> Box + 'a>;
/// Get the signing chain ID.
fn signing_chain_id(&self) -> Option;
/// Get environment info for execution at a given block.
/// Fails if that block's header is not stored.
fn env_info(&self, id: BlockId) -> Option;
/// Get a handle to the consensus engine.
fn engine(&self) -> &Arc;
/// Query whether a block is known.
fn is_known(&self, hash: &H256) -> bool;
/// Set the chain via a spec name.
fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()>;
/// Clear the queue.
fn clear_queue(&self);
/// Flush the queue.
fn flush_queue(&self);
/// Get the `i`th CHT root.
fn cht_root(&self, i: usize) -> Option;
/// Get a report of import activity since the last call.
fn report(&self) -> ClientReport;
}
/// An actor listening to light chain events.
pub trait LightChainNotify: Send + Sync {
/// Notifies about imported headers.
fn new_headers(&self, good: &[H256]);
}
/// Something which can be treated as a `LightChainClient`.
pub trait AsLightClient {
/// The kind of light client this can be treated as.
type Client: LightChainClient;
/// Access the underlying light client.
fn as_light_client(&self) -> &Self::Client;
}
impl AsLightClient for T {
type Client = Self;
fn as_light_client(&self) -> &Self { self }
}
/// Light client implementation.
pub struct Client {
queue: HeaderQueue,
engine: Arc,
chain: HeaderChain,
report: RwLock,
import_lock: Mutex<()>,
db: Arc,
listeners: RwLock>>,
fetcher: T,
verify_full: bool,
/// A closure to call when we want to restart the client
exit_handler: Mutex