Changes tries: support forks (#950)

* forks support in changes trie storage

* moved convert_hash to primitives

* optimize ChangesTrieRootsStorage::root when anchor is canonicalized
This commit is contained in:
Svyatoslav Nikolsky
2018-11-13 14:17:14 +03:00
committed by Gav Wood
parent 037f9dde10
commit 6e3c56c135
25 changed files with 276 additions and 138 deletions
+2 -3
View File
@@ -27,7 +27,7 @@ use hash_db;
use heapsize::HeapSizeOf;
use trie;
use primitives::H256;
use primitives::{H256, convert_hash};
use runtime_primitives::traits::{As, Header as HeaderT, SimpleArithmetic, One};
use state_machine::backend::InMemory as InMemoryState;
use state_machine::{prove_read, read_proof_check};
@@ -113,8 +113,7 @@ pub fn check_proof<Header, Hasher>(
Hasher: hash_db::Hasher,
Hasher::Out: Ord + HeapSizeOf,
{
let mut root: Hasher::Out = Default::default();
root.as_mut().copy_from_slice(local_root.as_ref());
let root: Hasher::Out = convert_hash(&local_root);
let local_cht_key = encode_cht_key(local_number);
let local_cht_value = read_proof_check::<Hasher>(root, remote_proof,
&local_cht_key).map_err(|e| ClientError::from(e))?;
+11 -5
View File
@@ -30,14 +30,14 @@ use consensus::{ImportBlock, ImportResult, BlockOrigin};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight, BlockNumberToHash};
use runtime_primitives::{ApplyResult, BuildStorage};
use runtime_api as api;
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration};
use primitives::{Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash};
use primitives::storage::{StorageKey, StorageData};
use primitives::storage::well_known_keys;
use codec::{Encode, Decode};
use state_machine::{
Backend as StateBackend, CodeExecutor,
ExecutionStrategy, ExecutionManager, prove_read,
key_changes, key_changes_proof, OverlayedChanges
ExecutionStrategy, ExecutionManager, ChangesTrieAnchorBlockId,
prove_read, key_changes, key_changes_proof, OverlayedChanges
};
use backend::{self, BlockImportOperation};
@@ -355,7 +355,10 @@ impl<B, E, Block> Client<B, E, Block> where
config,
storage,
self.require_block_number_from_id(&BlockId::Hash(first))?.as_(),
self.require_block_number_from_id(&BlockId::Hash(last))?.as_(),
&ChangesTrieAnchorBlockId {
hash: convert_hash(&last),
number: self.require_block_number_from_id(&BlockId::Hash(last))?.as_(),
},
self.backend.blockchain().info()?.best_number.as_(),
key)
.map_err(|err| error::ErrorKind::ChangesTrieAccessFailed(err).into())
@@ -388,7 +391,10 @@ impl<B, E, Block> Client<B, E, Block> where
config,
storage,
self.require_block_number_from_id(&BlockId::Hash(first))?.as_(),
self.require_block_number_from_id(&BlockId::Hash(last))?.as_(),
&ChangesTrieAnchorBlockId {
hash: convert_hash(&last),
number: self.require_block_number_from_id(&BlockId::Hash(last))?.as_(),
},
max_number.as_(),
key)
.map_err(|err| error::ErrorKind::ChangesTrieAccessFailed(err).into())
@@ -21,6 +21,7 @@ use std::marker::PhantomData;
use std::sync::Arc;
use futures::{IntoFuture, Future};
use primitives::convert_hash;
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use state_machine::{Backend as StateBackend, CodeExecutor, OverlayedChanges,
@@ -136,8 +137,7 @@ pub fn check_execution_proof<Header, E, H>(
{
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 root: H::Out = convert_hash(&local_state_root);
let mut changes = OverlayedChanges::default();
let local_result = execution_proof_check::<H, _>(
+12 -13
View File
@@ -21,10 +21,10 @@ use futures::IntoFuture;
use hash_db::Hasher;
use heapsize::HeapSizeOf;
use primitives::ChangesTrieConfiguration;
use primitives::{ChangesTrieConfiguration, convert_hash};
use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, NumberFor};
use state_machine::{CodeExecutor, ChangesTrieRootsStorage, read_proof_check,
key_changes_proof_check};
use state_machine::{CodeExecutor, ChangesTrieRootsStorage, ChangesTrieAnchorBlockId,
read_proof_check, key_changes_proof_check};
use call_executor::CallResult;
use cht;
@@ -192,9 +192,8 @@ impl<E, Block, H> FetchChecker<Block> for LightDataChecker<E, H>
request: &RemoteReadRequest<Block::Header>,
remote_proof: Vec<Vec<u8>>
) -> 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>(root, remote_proof, &request.key).map_err(Into::into)
read_proof_check::<H>(convert_hash(request.header.state_root()), remote_proof, &request.key)
.map_err(Into::into)
}
fn check_execution_proof(
@@ -229,7 +228,10 @@ impl<E, Block, H> FetchChecker<Block> for LightDataChecker<E, H>
},
remote_proof,
first_number,
request.last_block.0.as_(),
&ChangesTrieAnchorBlockId {
hash: convert_hash(&request.last_block.1),
number: request.last_block.0.as_(),
},
remote_max.as_(),
&request.key)
.map(|pairs| pairs.into_iter().map(|(b, x)| (As::sa(b), x)).collect())
@@ -248,15 +250,12 @@ impl<'a, H, Hash> ChangesTrieRootsStorage<H> for RootsStorage<'a, Hash>
H: Hasher,
Hash: 'a + Send + Sync + Clone + AsRef<[u8]>,
{
fn root(&self, block: u64) -> Result<Option<H::Out>, String> {
fn root(&self, _anchor: &ChangesTrieAnchorBlockId<H::Out>, block: u64) -> Result<Option<H::Out>, String> {
// we can't ask for roots from parallel forks here => ignore anchor
Ok(block.checked_sub(self.first)
.and_then(|index| self.roots.get(index as usize))
.cloned()
.map(|root| {
let mut hasher_root: H::Out = Default::default();
hasher_root.as_mut().copy_from_slice(root.as_ref());
hasher_root
}))
.map(|root| convert_hash(&root)))
}
}