Switch to shiny new fast, RLP-less trie (#795)

* Bump codec

* Fix tests

* Patricia trie builds

* Introduce trie

* Some yak shaving.

* Some fixes

* Remove RLP ref

* Fixes

* It builds!

* Some tests fixed

* Another test fix

* Rejig more hashes

* substrate-trie::iterator_works test

* Update lock

* Polish

* Docs

* Undo incorrect "fix" for tests

* Fix nits
This commit is contained in:
Gav Wood
2018-09-25 15:32:22 +01:00
committed by Arkadiy Paronyan
parent b02c274374
commit 82d6ca3484
90 changed files with 1977 additions and 1129 deletions
+12 -13
View File
@@ -31,9 +31,8 @@ use blockchain::HeaderBackend as BlockchainHeaderBackend;
use error::{Error as ClientError, ErrorKind as ClientErrorKind, Result as ClientResult};
use light::blockchain::{Blockchain, Storage as BlockchainStorage};
use light::fetcher::{Fetcher, RemoteReadRequest};
use patricia_trie::NodeCodec;
use hashdb::Hasher;
use memorydb::MemoryDB;
use hash_db::Hasher;
use trie::MemoryDB;
use heapsize::HeapSizeOf;
/// Light client backend.
@@ -69,12 +68,12 @@ impl<S, F> Backend<S, F> {
}
}
impl<S, F, Block, H, C> ClientBackend<Block, H, C> for Backend<S, F> where
impl<S, F, Block, H> ClientBackend<Block, H> for Backend<S, F> where
Block: BlockT,
S: BlockchainStorage<Block>,
F: Fetcher<Block>,
H: Hasher,
C: NodeCodec<H>,
H::Out: HeapSizeOf,
{
type BlockImportOperation = ImportOperation<Block, S, F>;
@@ -131,23 +130,23 @@ impl<S, F, Block, H, C> ClientBackend<Block, H, C> for Backend<S, F> where
}
}
impl<S, F, Block, H, C> RemoteBackend<Block, H, C> for Backend<S, F>
impl<S, F, Block, H> RemoteBackend<Block, H> for Backend<S, F>
where
Block: BlockT,
S: BlockchainStorage<Block>,
F: Fetcher<Block>,
H: Hasher,
H::Out: HeapSizeOf,
C: NodeCodec<H>,
{}
impl<S, F, Block, H, C> BlockImportOperation<Block, H, C> for ImportOperation<Block, S, F>
impl<S, F, Block, H> BlockImportOperation<Block, H> for ImportOperation<Block, S, F>
where
Block: BlockT,
F: Fetcher<Block>,
S: BlockchainStorage<Block>,
H: Hasher,
C: NodeCodec<H>,
{
type State = OnDemandState<Block, S, F>;
@@ -172,7 +171,7 @@ where
self.authorities = Some(authorities);
}
fn update_storage(&mut self, _update: <Self::State as StateBackend<H, C>>::Transaction) -> ClientResult<()> {
fn update_storage(&mut self, _update: <Self::State as StateBackend<H>>::Transaction) -> ClientResult<()> {
// we're not storing anything locally => ignore changes
Ok(())
}
@@ -188,13 +187,13 @@ where
}
}
impl<Block, S, F, H, C> StateBackend<H, C> for OnDemandState<Block, S, F>
impl<Block, S, F, H> StateBackend<H> for OnDemandState<Block, S, F>
where
Block: BlockT,
S: BlockchainStorage<Block>,
F: Fetcher<Block>,
H: Hasher,
C: NodeCodec<H>,
{
type Error = ClientError;
type Transaction = ();
@@ -234,7 +233,7 @@ impl<Block, S, F, H, C> StateBackend<H, C> for OnDemandState<Block, S, F>
Vec::new()
}
fn try_into_trie_backend(self) -> Option<TrieBackend<Self::TrieBackendStorage, H, C>> {
fn try_into_trie_backend(self) -> Option<TrieBackend<Self::TrieBackendStorage, H>> {
None
}
}
@@ -25,9 +25,7 @@ use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use state_machine::{Backend as StateBackend, CodeExecutor, OverlayedChanges,
execution_proof_check, ExecutionManager};
use patricia_trie::NodeCodec;
use hashdb::Hasher;
use rlp::Encodable;
use hash_db::Hasher;
use blockchain::Backend as ChainBackend;
use call_executor::{CallExecutor, CallResult};
@@ -36,43 +34,41 @@ use light::fetcher::{Fetcher, RemoteCallRequest};
use executor::RuntimeVersion;
use codec::Decode;
use heapsize::HeapSizeOf;
use memorydb::MemoryDB;
use trie::MemoryDB;
/// Call executor that executes methods on remote node, querying execution proof
/// and checking proof by re-executing locally.
pub struct RemoteCallExecutor<B, F, H, C> {
pub struct RemoteCallExecutor<B, F, H> {
blockchain: Arc<B>,
fetcher: Arc<F>,
_hasher: PhantomData<H>,
_codec: PhantomData<C>,
}
impl<B, F, H, C> Clone for RemoteCallExecutor<B, F, H, C> {
impl<B, F, H> Clone for RemoteCallExecutor<B, F, H> {
fn clone(&self) -> Self {
RemoteCallExecutor {
blockchain: self.blockchain.clone(),
fetcher: self.fetcher.clone(),
_hasher: Default::default(),
_codec: Default::default(),
}
}
}
impl<B, F, H, C> RemoteCallExecutor<B, F, H, C> {
impl<B, F, H> RemoteCallExecutor<B, F, H> {
/// Creates new instance of remote call executor.
pub fn new(blockchain: Arc<B>, fetcher: Arc<F>) -> Self {
RemoteCallExecutor { blockchain, fetcher, _hasher: PhantomData, _codec: PhantomData }
RemoteCallExecutor { blockchain, fetcher, _hasher: PhantomData }
}
}
impl<B, F, Block, H, C> CallExecutor<Block, H, C> for RemoteCallExecutor<B, F, H, C>
impl<B, F, Block, H> CallExecutor<Block, H> for RemoteCallExecutor<B, F, H>
where
Block: BlockT,
B: ChainBackend<Block>,
F: Fetcher<Block>,
H: Hasher,
H::Out: Ord + Encodable,
C: NodeCodec<H>
H::Out: Ord,
{
type Error = ClientError;
@@ -100,7 +96,7 @@ where
}
fn call_at_state<
S: StateBackend<H, C>,
S: StateBackend<H>,
FF: FnOnce(Result<Vec<u8>, Self::Error>, Result<Vec<u8>, Self::Error>) -> Result<Vec<u8>, Self::Error>
>(&self,
_state: &S,
@@ -112,7 +108,7 @@ where
Err(ClientErrorKind::NotAvailableOnLightClient.into())
}
fn prove_at_state<S: StateBackend<H, C>>(
fn prove_at_state<S: StateBackend<H>>(
&self,
_state: S,
_changes: &mut OverlayedChanges,
@@ -128,7 +124,7 @@ where
}
/// Check remote execution proof using given backend.
pub fn check_execution_proof<Header, E, H, C>(
pub fn check_execution_proof<Header, E, H>(
executor: &E,
request: &RemoteCallRequest<Header>,
remote_proof: Vec<Vec<u8>>
@@ -137,15 +133,15 @@ pub fn check_execution_proof<Header, E, H, C>(
Header: HeaderT,
E: CodeExecutor<H>,
H: Hasher,
H::Out: Ord + Encodable + HeapSizeOf,
C: NodeCodec<H>,
H::Out: Ord + HeapSizeOf,
{
let local_state_root = request.header.state_root();
let mut root: H::Out = Default::default();
root.as_mut().copy_from_slice(local_state_root.as_ref());
let mut changes = OverlayedChanges::default();
let local_result = execution_proof_check::<H, C, _>(
let local_result = execution_proof_check::<H, _>(
root,
remote_proof,
&mut changes,
@@ -161,7 +157,6 @@ mod tests {
use test_client;
use executor::NativeExecutionDispatch;
use super::*;
use primitives::RlpCodec;
#[test]
fn execution_proof_is_generated_and_checked() {
@@ -176,7 +171,7 @@ mod tests {
// check remote execution proof locally
let local_executor = test_client::LocalExecutor::new();
check_execution_proof::<_, _, _, RlpCodec>(&local_executor, &RemoteCallRequest {
check_execution_proof(&local_executor, &RemoteCallRequest {
block: test_client::runtime::Hash::default(),
header: test_client::runtime::Header {
state_root: remote_block_storage_root.into(),
+12 -16
View File
@@ -18,9 +18,7 @@
use futures::IntoFuture;
use hashdb::Hasher;
use patricia_trie::NodeCodec;
use rlp::Encodable;
use hash_db::Hasher;
use heapsize::HeapSizeOf;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use state_machine::{CodeExecutor, read_proof_check};
@@ -115,28 +113,26 @@ pub trait FetchChecker<Block: BlockT>: Send + Sync {
}
/// Remote data checker.
pub struct LightDataChecker<E, H, C> {
pub struct LightDataChecker<E, H> {
executor: E,
_hasher: PhantomData<H>,
_codec: PhantomData<C>,
}
impl<E, H, C> LightDataChecker<E, H, C> {
impl<E, H> LightDataChecker<E, H> {
/// Create new light data checker.
pub fn new(executor: E) -> Self {
Self {
executor, _hasher: PhantomData, _codec: PhantomData
executor, _hasher: PhantomData
}
}
}
impl<E, Block, H, C> FetchChecker<Block> for LightDataChecker<E, H, C>
impl<E, Block, H> FetchChecker<Block> for LightDataChecker<E, H>
where
Block: BlockT,
E: CodeExecutor<H>,
H: Hasher,
C: NodeCodec<H> + Sync + Send,
H::Out: Ord + Encodable + HeapSizeOf,
H::Out: Ord + HeapSizeOf,
{
fn check_header_proof(
&self,
@@ -147,7 +143,7 @@ impl<E, Block, H, C> FetchChecker<Block> for LightDataChecker<E, H, C>
let remote_header = remote_header.ok_or_else(||
ClientError::from(ClientErrorKind::InvalidHeaderProof))?;
let remote_header_hash = remote_header.hash();
cht::check_proof::<Block::Header, H, C>(
cht::check_proof::<Block::Header, H>(
request.cht_root,
request.block,
remote_header_hash,
@@ -162,7 +158,7 @@ impl<E, Block, H, C> FetchChecker<Block> for LightDataChecker<E, H, C>
) -> ClientResult<Option<Vec<u8>>> {
let mut root: H::Out = Default::default();
root.as_mut().copy_from_slice(request.header.state_root().as_ref());
read_proof_check::<H, C>(root, remote_proof, &request.key).map_err(Into::into)
read_proof_check::<H>(root, remote_proof, &request.key).map_err(Into::into)
}
fn check_execution_proof(
@@ -170,7 +166,7 @@ impl<E, Block, H, C> FetchChecker<Block> for LightDataChecker<E, H, C>
request: &RemoteCallRequest<Block::Header>,
remote_proof: Vec<Vec<u8>>
) -> ClientResult<CallResult> {
check_execution_proof::<_, _, H, C>(&self.executor, request, remote_proof)
check_execution_proof::<_, _, H>(&self.executor, request, remote_proof)
}
}
@@ -186,7 +182,7 @@ pub mod tests {
use in_mem::{Blockchain as InMemoryBlockchain};
use light::fetcher::{Fetcher, FetchChecker, LightDataChecker,
RemoteCallRequest, RemoteHeaderRequest};
use primitives::{Blake2Hasher, RlpCodec};
use primitives::{Blake2Hasher};
use primitives::storage::well_known_keys;
use runtime_primitives::generic::BlockId;
use state_machine::Backend;
@@ -213,7 +209,7 @@ pub mod tests {
}
fn prepare_for_read_proof_check() -> (
LightDataChecker<executor::NativeExecutor<test_client::LocalExecutor>, Blake2Hasher, RlpCodec>,
LightDataChecker<executor::NativeExecutor<test_client::LocalExecutor>, Blake2Hasher>,
Header, Vec<Vec<u8>>, usize)
{
// prepare remote client
@@ -242,7 +238,7 @@ pub mod tests {
}
fn prepare_for_header_proof_check(insert_cht: bool) -> (
LightDataChecker<executor::NativeExecutor<test_client::LocalExecutor>, Blake2Hasher, RlpCodec>,
LightDataChecker<executor::NativeExecutor<test_client::LocalExecutor>, Blake2Hasher>,
Hash, Header, Vec<Vec<u8>>)
{
// prepare remote client
+6 -7
View File
@@ -23,7 +23,7 @@ pub mod fetcher;
use std::sync::Arc;
use primitives::{Blake2Hasher, RlpCodec};
use primitives::{Blake2Hasher};
use runtime_primitives::BuildStorage;
use runtime_primitives::traits::Block as BlockT;
use state_machine::{CodeExecutor, ExecutionStrategy};
@@ -34,8 +34,7 @@ use light::backend::Backend;
use light::blockchain::{Blockchain, Storage as BlockchainStorage};
use light::call_executor::RemoteCallExecutor;
use light::fetcher::{Fetcher, LightDataChecker};
use hashdb::Hasher;
use patricia_trie::NodeCodec;
use hash_db::Hasher;
/// Create an instance of light client blockchain backend.
pub fn new_light_blockchain<B: BlockT, S: BlockchainStorage<B>, F>(storage: S) -> Arc<Blockchain<S, F>> {
@@ -53,7 +52,7 @@ pub fn new_light<B, S, F, GS>(
backend: Arc<Backend<S, F>>,
fetcher: Arc<F>,
genesis_storage: GS,
) -> ClientResult<Client<Backend<S, F>, RemoteCallExecutor<Blockchain<S, F>, F, Blake2Hasher, RlpCodec>, B>>
) -> ClientResult<Client<Backend<S, F>, RemoteCallExecutor<Blockchain<S, F>, F, Blake2Hasher>, B>>
where
B: BlockT,
S: BlockchainStorage<B>,
@@ -65,13 +64,13 @@ pub fn new_light<B, S, F, GS>(
}
/// Create an instance of fetch data checker.
pub fn new_fetch_checker<E, H, C>(
pub fn new_fetch_checker<E, H>(
executor: E,
) -> LightDataChecker<E, H, C>
) -> LightDataChecker<E, H>
where
E: CodeExecutor<H>,
H: Hasher,
C: NodeCodec<H>,
{
LightDataChecker::new(executor)
}