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
+16 -20
View File
@@ -23,11 +23,9 @@
//! root has. A correct proof implies that the claimed block is identical to the one
//! we discarded.
use hashdb;
use hash_db;
use heapsize::HeapSizeOf;
use patricia_trie::NodeCodec;
use rlp::Encodable;
use triehash;
use trie;
use primitives::H256;
use runtime_primitives::traits::{As, Header as HeaderT, SimpleArithmetic, One};
@@ -68,16 +66,16 @@ pub fn compute_root<Header, Hasher, I>(
) -> Option<Hasher::Out>
where
Header: HeaderT,
Hasher: hashdb::Hasher,
Hasher::Out: Ord + Encodable,
Hasher: hash_db::Hasher,
Hasher::Out: Ord,
I: IntoIterator<Item=Option<Header::Hash>>,
{
build_pairs::<Header, I>(cht_size, cht_num, hashes)
.map(|pairs| triehash::trie_root::<Hasher, _, _, _>(pairs))
.map(|pairs| trie::trie_root::<Hasher, _, _, _>(pairs))
}
/// Build CHT-based header proof.
pub fn build_proof<Header, Hasher, Codec, I>(
pub fn build_proof<Header, Hasher, I>(
cht_size: u64,
cht_num: Header::Number,
block_num: Header::Number,
@@ -85,16 +83,15 @@ pub fn build_proof<Header, Hasher, Codec, I>(
) -> Option<Vec<Vec<u8>>>
where
Header: HeaderT,
Hasher: hashdb::Hasher,
Hasher::Out: Ord + Encodable + HeapSizeOf,
Codec: NodeCodec<Hasher>,
Hasher: hash_db::Hasher,
Hasher::Out: Ord + HeapSizeOf,
I: IntoIterator<Item=Option<Header::Hash>>,
{
let transaction = build_pairs::<Header, I>(cht_size, cht_num, hashes)?
.into_iter()
.map(|(k, v)| (k, Some(v)))
.collect::<Vec<_>>();
let storage = InMemoryState::<Hasher, Codec>::default().update(transaction);
let storage = InMemoryState::<Hasher>::default().update(transaction);
let (value, proof) = prove_read(storage, &encode_cht_key(block_num)).ok()?;
if value.is_none() {
None
@@ -104,7 +101,7 @@ pub fn build_proof<Header, Hasher, Codec, I>(
}
/// Check CHT-based header proof.
pub fn check_proof<Header, Hasher, Codec>(
pub fn check_proof<Header, Hasher>(
local_root: Header::Hash,
local_number: Header::Number,
remote_hash: Header::Hash,
@@ -113,14 +110,13 @@ pub fn check_proof<Header, Hasher, Codec>(
where
Header: HeaderT,
Header::Hash: AsRef<[u8]>,
Hasher: hashdb::Hasher,
Hasher::Out: Ord + Encodable + HeapSizeOf,
Codec: NodeCodec<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 local_cht_key = encode_cht_key(local_number);
let local_cht_value = read_proof_check::<Hasher, Codec>(root, remote_proof,
let local_cht_value = read_proof_check::<Hasher>(root, remote_proof,
&local_cht_key).map_err(|e| ClientError::from(e))?;
let local_cht_value = local_cht_value.ok_or_else(|| ClientErrorKind::InvalidHeaderProof)?;
let local_hash = decode_cht_value(&local_cht_value).ok_or_else(|| ClientErrorKind::InvalidHeaderProof)?;
@@ -214,7 +210,7 @@ pub fn decode_cht_value(value: &[u8]) -> Option<H256> {
#[cfg(test)]
mod tests {
use primitives::{Blake2Hasher, RlpCodec};
use primitives::{Blake2Hasher};
use test_client::runtime::Header;
use super::*;
@@ -263,13 +259,13 @@ mod tests {
#[test]
fn build_proof_fails_when_querying_wrong_block() {
assert!(build_proof::<Header, Blake2Hasher, RlpCodec, _>(
assert!(build_proof::<Header, Blake2Hasher, _>(
SIZE, 0, (SIZE * 1000) as u64, vec![Some(1.into()); SIZE as usize]).is_none());
}
#[test]
fn build_proof_works() {
assert!(build_proof::<Header, Blake2Hasher, RlpCodec, _>(
assert!(build_proof::<Header, Blake2Hasher, _>(
SIZE, 0, (SIZE / 2) as u64, vec![Some(1.into()); SIZE as usize]).is_some());
}
}