// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see .
//! Light client blockchin backend. Only stores headers and justifications of recent
//! blocks. CHT roots are stored for headers of ancient blocks.
use std::sync::Weak;
use futures::{Future, IntoFuture};
use parking_lot::Mutex;
use primitives::AuthorityId;
use runtime_primitives::{Justification, generic::BlockId};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT,NumberFor, Zero};
use backend::NewBlockState;
use blockchain::{Backend as BlockchainBackend, BlockStatus, Cache as BlockchainCache,
HeaderBackend as BlockchainHeaderBackend, Info as BlockchainInfo};
use cht;
use error::{ErrorKind as ClientErrorKind, Result as ClientResult};
use light::fetcher::{Fetcher, RemoteHeaderRequest};
/// Light client blockchain storage.
pub trait Storage: BlockchainHeaderBackend {
/// Store new header. Should refuse to revert any finalized blocks.
fn import_header(
&self,
header: Block::Header,
authorities: Option>,
state: NewBlockState,
) -> ClientResult<()>;
/// Mark historic header as finalized.
fn finalize_header(&self, block: BlockId) -> ClientResult<()>;
/// Get last finalized header.
fn last_finalized(&self) -> ClientResult;
/// Get headers CHT root for given block. Fails if the block is not pruned (not a part of any CHT).
fn header_cht_root(&self, cht_size: u64, block: NumberFor) -> ClientResult;
/// Get changes trie CHT root for given block. Fails if the block is not pruned (not a part of any CHT).
fn changes_trie_cht_root(&self, cht_size: u64, block: NumberFor) -> ClientResult;
/// Get storage cache.
fn cache(&self) -> Option<&BlockchainCache>;
}
/// Light client blockchain.
pub struct Blockchain {
fetcher: Mutex>,
storage: S,
}
impl Blockchain {
/// Create new light blockchain backed with given storage.
pub fn new(storage: S) -> Self {
Self {
fetcher: Mutex::new(Default::default()),
storage,
}
}
/// Sets fetcher reference.
pub fn set_fetcher(&self, fetcher: Weak) {
*self.fetcher.lock() = fetcher;
}
/// Get fetcher weak reference.
pub fn fetcher(&self) -> Weak {
self.fetcher.lock().clone()
}
/// Get storage reference.
pub fn storage(&self) -> &S {
&self.storage
}
}
impl BlockchainHeaderBackend for Blockchain where Block: BlockT, S: Storage, F: Fetcher {
fn header(&self, id: BlockId) -> ClientResult