Fetch changes trie roots + CHT-based proof for these roots (#896)

* build CHT for changes tries roots

* collect chnages tries roots proof in key_changes_proof

* flush check_changes_proof

* fixed compilation

* LightDataChecker now has a ref to the blockchain

* continue passing proofs

* new light db tests

* more CHT tests

* more tests for key changes proof when headers are missing

* lost files
This commit is contained in:
Svyatoslav Nikolsky
2018-11-14 18:06:10 +03:00
committed by Gav Wood
parent 7f8ee0f53b
commit fa84cec382
19 changed files with 1035 additions and 313 deletions
+87 -3
View File
@@ -48,8 +48,11 @@ pub trait Storage<Block: BlockT>: BlockchainHeaderBackend<Block> {
/// Get last finalized header.
fn last_finalized(&self) -> ClientResult<Block::Hash>;
/// Get CHT root for given block. Fails if the block is not pruned (not a part of any CHT).
fn cht_root(&self, cht_size: u64, block: NumberFor<Block>) -> ClientResult<Block::Hash>;
/// 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<Block>) -> ClientResult<Block::Hash>;
/// 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<Block>) -> ClientResult<Block::Hash>;
/// Get storage cache.
fn cache(&self) -> Option<&BlockchainCache<Block>>;
@@ -106,7 +109,7 @@ impl<S, F, Block> BlockchainHeaderBackend<Block> for Blockchain<S, F> where Bloc
self.fetcher().upgrade().ok_or(ClientErrorKind::NotAvailableOnLightClient)?
.remote_header(RemoteHeaderRequest {
cht_root: self.storage.cht_root(cht::SIZE, number)?,
cht_root: self.storage.header_cht_root(cht::SIZE, number)?,
block: number,
retry_count: None,
})
@@ -155,3 +158,84 @@ impl<S, F, Block> BlockchainBackend<Block> for Blockchain<S, F> where Block: Blo
unimplemented!()
}
}
#[cfg(test)]
pub mod tests {
use std::collections::HashMap;
use test_client::runtime::{Hash, Block, Header};
use blockchain::Info;
use light::fetcher::tests::OkCallFetcher;
use super::*;
pub type DummyBlockchain = Blockchain<DummyStorage, OkCallFetcher>;
pub struct DummyStorage {
pub changes_tries_cht_roots: HashMap<u64, Hash>,
}
impl DummyStorage {
pub fn new() -> Self {
DummyStorage {
changes_tries_cht_roots: HashMap::new(),
}
}
}
impl BlockchainHeaderBackend<Block> for DummyStorage {
fn header(&self, _id: BlockId<Block>) -> ClientResult<Option<Header>> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn info(&self) -> ClientResult<Info<Block>> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn status(&self, _id: BlockId<Block>) -> ClientResult<BlockStatus> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn number(&self, _hash: Hash) -> ClientResult<Option<NumberFor<Block>>> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn hash(&self, _number: u64) -> ClientResult<Option<Hash>> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
}
impl Storage<Block> for DummyStorage {
fn import_header(
&self,
_header: Header,
_authorities: Option<Vec<AuthorityId>>,
_state: NewBlockState,
) -> ClientResult<()> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn finalize_header(&self, _block: BlockId<Block>) -> ClientResult<()> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn last_finalized(&self) -> ClientResult<Hash> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn header_cht_root(&self, _cht_size: u64, _block: u64) -> ClientResult<Hash> {
Err(ClientErrorKind::Backend("Test error".into()).into())
}
fn changes_trie_cht_root(&self, cht_size: u64, block: u64) -> ClientResult<Hash> {
cht::block_to_cht_number(cht_size, block)
.and_then(|cht_num| self.changes_tries_cht_roots.get(&cht_num))
.cloned()
.ok_or_else(|| ClientErrorKind::Backend(
format!("Test error: CHT for block #{} not found", block)
).into())
}
fn cache(&self) -> Option<&BlockchainCache<Block>> {
None
}
}
}