The storage runtime interface should not enforce a hash type (#4231)

* The storage runtime interface should not enforce a hash type

Currently the runtime interface enforces `H256` as hash type, but in the
future people could use whatever they want as hash type. The hash type
always needs to match between the runtime and the node, but that is
already required.

* Update primitives/externalities/src/lib.rs

Co-Authored-By: thiolliere <gui.thiolliere@gmail.com>
This commit is contained in:
Bastian Köcher
2019-11-28 01:00:29 +01:00
committed by Gavin Wood
parent 39388b826b
commit 3e26fceda4
29 changed files with 253 additions and 165 deletions
-1
View File
@@ -5986,7 +5986,6 @@ name = "substrate-externalities"
version = "2.0.0"
dependencies = [
"environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-std 2.0.0",
"substrate-primitives-storage 2.0.0",
]
+2 -2
View File
@@ -913,7 +913,7 @@ mod tests {
None,
).0.unwrap();
assert!(t.ext().storage_changes_root(GENESIS_HASH.into()).unwrap().is_some());
assert!(t.ext().storage_changes_root(&GENESIS_HASH.encode()).unwrap().is_some());
}
#[test]
@@ -929,7 +929,7 @@ mod tests {
None,
).0.unwrap();
assert!(t.ext().storage_changes_root(GENESIS_HASH.into()).unwrap().is_some());
assert!(t.ext().storage_changes_root(&GENESIS_HASH.encode()).unwrap().is_some());
}
#[test]
+4 -2
View File
@@ -174,7 +174,7 @@ impl<B: BlockT> StateBackend<Blake2Hasher> for RefTrackingState<B> {
self.state.storage_root(delta)
}
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H256, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
{
@@ -193,7 +193,9 @@ impl<B: BlockT> StateBackend<Blake2Hasher> for RefTrackingState<B> {
self.state.child_keys(child_key, prefix)
}
fn as_trie_backend(&mut self) -> Option<&state_machine::TrieBackend<Self::TrieBackendStorage, Blake2Hasher>> {
fn as_trie_backend(
&mut self,
) -> Option<&state_machine::TrieBackend<Self::TrieBackendStorage, Blake2Hasher>> {
self.state.as_trie_backend()
}
}
+1 -1
View File
@@ -568,7 +568,7 @@ impl<H: Hasher, S: StateBackend<H>, B: BlockT> StateBackend<H> for CachingState<
self.state.storage_root(delta)
}
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord
@@ -425,7 +425,7 @@ impl_wasm_host_interface! {
context.read_memory_into(parent_hash_data, &mut parent_hash[..])
.map_err(|_| "Invalid attempt to get parent_hash in ext_storage_changes_root")?;
if let Some(r) = runtime_io::storage::changes_root(parent_hash) {
if let Some(r) = runtime_io::storage::changes_root(&parent_hash) {
context.write_memory(result, &r[..])
.map_err(|_| "Invalid attempt to set memory in ext_storage_changes_root")?;
Ok(1)
@@ -26,7 +26,7 @@ use log::{trace, warn};
use codec::Decode;
use primitives::{storage::well_known_keys, traits::Externalities, H256};
use primitives::{storage::well_known_keys, traits::Externalities};
use runtime_version::RuntimeVersion;
use std::{collections::hash_map::{Entry, HashMap}, panic::AssertUnwindSafe};
@@ -82,7 +82,7 @@ pub struct RuntimesCache {
/// A cache of runtime instances along with metadata, ready to be reused.
///
/// Instances are keyed by the Wasm execution method and the hash of their code.
instances: HashMap<(WasmExecutionMethod, [u8; 32]), Result<VersionedRuntime, WasmError>>,
instances: HashMap<(WasmExecutionMethod, Vec<u8>), Result<VersionedRuntime, WasmError>>,
}
impl RuntimesCache {
@@ -128,7 +128,7 @@ impl RuntimesCache {
wasm_method: WasmExecutionMethod,
default_heap_pages: u64,
host_functions: &[&'static dyn Function],
) -> Result<(&mut (dyn WasmRuntime + 'static), &RuntimeVersion, H256), Error> {
) -> Result<(&mut (dyn WasmRuntime + 'static), &RuntimeVersion, Vec<u8>), Error> {
let code_hash = ext
.original_storage_hash(well_known_keys::CODE)
.ok_or(Error::InvalidCode("`CODE` not found in storage.".into()))?;
@@ -138,7 +138,7 @@ impl RuntimesCache {
.and_then(|pages| u64::decode(&mut &pages[..]).ok())
.unwrap_or(default_heap_pages);
let result = match self.instances.entry((wasm_method, code_hash.into())) {
let result = match self.instances.entry((wasm_method, code_hash.clone())) {
Entry::Occupied(o) => {
let result = o.into_mut();
if let Ok(ref mut cached_runtime) = result {
@@ -198,10 +198,10 @@ impl RuntimesCache {
pub fn invalidate_runtime(
&mut self,
wasm_method: WasmExecutionMethod,
code_hash: H256,
code_hash: Vec<u8>,
) {
// Just remove the instance, it will be re-created the next time it is requested.
self.instances.remove(&(wasm_method, code_hash.into()));
self.instances.remove(&(wasm_method, code_hash));
}
}
+3 -3
View File
@@ -92,7 +92,7 @@ pub fn build_proof<Header, Hasher, BlocksI, HashesI>(
where
Header: HeaderT,
Hasher: hash_db::Hasher,
Hasher::Out: Ord,
Hasher::Out: Ord + codec::Codec,
BlocksI: IntoIterator<Item=Header::Number>,
HashesI: IntoIterator<Item=ClientResult<Option<Header::Hash>>>,
{
@@ -119,7 +119,7 @@ pub fn check_proof<Header, Hasher>(
where
Header: HeaderT,
Hasher: hash_db::Hasher,
Hasher::Out: Ord,
Hasher::Out: Ord + codec::Codec,
{
do_check_proof::<Header, Hasher, _>(
local_root,
@@ -148,7 +148,7 @@ pub fn check_proof_on_proving_backend<Header, Hasher>(
where
Header: HeaderT,
Hasher: hash_db::Hasher,
Hasher::Out: Ord,
Hasher::Out: Ord + codec::Codec,
{
do_check_proof::<Header, Hasher, _>(
local_root,
+6 -4
View File
@@ -21,7 +21,9 @@ use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::RwLock;
use state_machine::{Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState, ChangesTrieTransaction};
use state_machine::{
Backend as StateBackend, TrieBackend, backend::InMemory as InMemoryState, ChangesTrieTransaction
};
use primitives::offchain::storage::InMemOffchainStorage;
use sr_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay};
use sr_primitives::traits::{Block as BlockT, NumberFor, Zero, Header};
@@ -341,7 +343,7 @@ impl<H: Hasher> std::fmt::Debug for GenesisOrUnavailableState<H> {
impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
where
H::Out: Ord,
H::Out: Ord + codec::Codec,
{
type Error = ClientError;
type Transaction = ();
@@ -409,7 +411,7 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
}
}
fn child_storage_root<I>(&self, key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>
{
@@ -418,7 +420,7 @@ impl<H: Hasher> StateBackend<H> for GenesisOrUnavailableState<H>
let (root, is_equal, _) = state.child_storage_root(key, delta);
(root, is_equal, ())
},
GenesisOrUnavailableState::Unavailable => (H::Out::default().as_ref().to_vec(), true, ()),
GenesisOrUnavailableState::Unavailable => (H::Out::default(), true, ()),
}
}
+2 -2
View File
@@ -70,7 +70,7 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
) -> ClientResult<Vec<(NumberFor<B>, u32)>>
where
H: Hasher,
H::Out: Ord,
H::Out: Ord + codec::Codec,
{
// since we need roots of all changes tries for the range begin..max
// => remote node can't use max block greater that one that we have passed
@@ -148,7 +148,7 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
) -> ClientResult<()>
where
H: Hasher,
H::Out: Ord,
H::Out: Ord + codec::Codec,
{
// all the checks are sharing the same storage
let storage = create_proof_check_backend_storage(remote_roots_proof);
+7 -3
View File
@@ -668,13 +668,17 @@ impl<T: Trait> Module<T> {
}
}
let storage_root = T::Hashing::storage_root();
let storage_changes_root = T::Hashing::storage_changes_root(parent_hash);
let storage_root = T::Hash::decode(&mut &runtime_io::storage::root()[..])
.expect("Node is configured to use the same hash; qed");
let storage_changes_root = runtime_io::storage::changes_root(&parent_hash.encode());
// we can't compute changes trie root earlier && put it to the Digest
// because it will include all currently existing temporaries.
if let Some(storage_changes_root) = storage_changes_root {
let item = generic::DigestItem::ChangesTrieRoot(storage_changes_root);
let item = generic::DigestItem::ChangesTrieRoot(
T::Hash::decode(&mut &storage_changes_root[..])
.expect("Node is configured to use the same hash; qed")
);
digest.push(item);
}
@@ -6,7 +6,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
primitive-types = { version = "0.6", features = ["codec"] }
primitives-storage = { package = "substrate-primitives-storage", path = "../core/storage" }
rstd = { package = "sr-std", path = "../sr-std" }
environmental = { version = "1.0.2" }
+35 -9
View File
@@ -22,8 +22,6 @@
//!
//! This crate exposes the main [`Externalities`] trait.
use primitive_types::H256;
use std::any::{Any, TypeId};
use primitives_storage::ChildStorageKey;
@@ -42,26 +40,40 @@ pub trait Externalities: ExtensionStore {
fn storage(&self, key: &[u8]) -> Option<Vec<u8>>;
/// Get storage value hash. This may be optimized for large values.
fn storage_hash(&self, key: &[u8]) -> Option<H256>;
fn storage_hash(&self, key: &[u8]) -> Option<Vec<u8>>;
/// Get child storage value hash. This may be optimized for large values.
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256>;
///
/// Returns an `Option` that holds the SCALE encoded hash.
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>>;
/// Read original runtime storage, ignoring any overlayed changes.
fn original_storage(&self, key: &[u8]) -> Option<Vec<u8>>;
/// Read original runtime child storage, ignoring any overlayed changes.
///
/// Returns an `Option` that holds the SCALE encoded hash.
fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>>;
/// Get original storage value hash, ignoring any overlayed changes.
/// This may be optimized for large values.
fn original_storage_hash(&self, key: &[u8]) -> Option<H256>;
///
/// Returns an `Option` that holds the SCALE encoded hash.
fn original_storage_hash(&self, key: &[u8]) -> Option<Vec<u8>>;
/// Get original child storage value hash, ignoring any overlayed changes.
/// This may be optimized for large values.
fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256>;
///
/// Returns an `Option` that holds the SCALE encoded hash.
fn original_child_storage_hash(
&self,
storage_key: ChildStorageKey,
key: &[u8],
) -> Option<Vec<u8>>;
/// Read child runtime storage.
///
/// Returns an `Option` that holds the SCALE encoded hash.
fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>>;
/// Set storage entry `key` of current contract being called (effective immediately).
@@ -107,14 +119,23 @@ pub trait Externalities: ExtensionStore {
fn place_storage(&mut self, key: Vec<u8>, value: Option<Vec<u8>>);
/// Set or clear a child storage entry. Return whether the operation succeeds.
fn place_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec<u8>, value: Option<Vec<u8>>);
fn place_child_storage(
&mut self,
storage_key: ChildStorageKey,
key: Vec<u8>,
value: Option<Vec<u8>>,
);
/// Get the identity of the chain.
fn chain_id(&self) -> u64;
/// Get the trie root of the current storage map. This will also update all child storage keys
/// in the top-level storage map.
fn storage_root(&mut self) -> H256;
///
/// The hash is defined by the `Block`.
///
/// Returns the SCALE encoded hash.
fn storage_root(&mut self) -> Vec<u8>;
/// Get the trie root of a child storage map. This will also update the value of the child
/// storage keys in the top-level storage map.
@@ -123,7 +144,12 @@ pub trait Externalities: ExtensionStore {
fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec<u8>;
/// Get the change trie root of the current storage overlay at a block with given parent.
fn storage_changes_root(&mut self, parent: H256) -> Result<Option<H256>, ()>;
/// `parent` is expects a SCALE endcoded hash.
///
/// The hash is defined by the `Block`.
///
/// Returns the SCALE encoded hash.
fn storage_changes_root(&mut self, parent: &[u8]) -> Result<Option<Vec<u8>>, ()>;
}
/// Extension for the [`Externalities`] trait.
+24 -6
View File
@@ -50,7 +50,7 @@ use primitives::{
};
#[cfg(feature = "std")]
use trie::{TrieConfiguration, trie_types::Layout};
use ::trie::{TrieConfiguration, trie_types::Layout};
use runtime_interface::{runtime_interface, Pointer};
@@ -186,28 +186,45 @@ pub trait Storage {
}
/// "Commit" all existing operations and compute the resulting storage root.
fn root(&mut self) -> H256 {
///
/// The hashing algorithm is defined by the `Block`.
///
/// Returns the SCALE encoded hash.
fn root(&mut self) -> Vec<u8> {
self.storage_root()
}
/// "Commit" all existing operations and compute the resulting child storage root.
///
/// The hashing algorithm is defined by the `Block`.
///
/// Returns the SCALE encoded hash.
fn child_root(&mut self, child_storage_key: &[u8]) -> Vec<u8> {
let storage_key = child_storage_key_or_panic(child_storage_key);
self.child_storage_root(storage_key)
}
/// "Commit" all existing operations and get the resulting storage change root.
fn changes_root(&mut self, parent_hash: [u8; 32]) -> Option<H256> {
self.storage_changes_root(parent_hash.into()).ok().and_then(|h| h)
/// `parent_hash` is a SCALE encoded hash.
///
/// The hashing algorithm is defined by the `Block`.
///
/// Returns an `Option` that holds the SCALE encoded hash.
fn changes_root(&mut self, parent_hash: &[u8]) -> Option<Vec<u8>> {
self.storage_changes_root(parent_hash).ok().and_then(|h| h)
}
}
/// Interface that provides trie related functionality.
#[runtime_interface]
pub trait Trie {
/// A trie root formed from the iterated items.
fn blake2_256_trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
fn blake2_256_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
Layout::<primitives::Blake2Hasher>::trie_root(input)
}
/// A trie root formed from the enumerated items.
fn blake2_256_ordered_trie_root(input: Vec<Vec<u8>>) -> H256 {
fn blake2_256_ordered_root(input: Vec<Vec<u8>>) -> H256 {
Layout::<primitives::Blake2Hasher>::ordered_trie_root(input)
}
}
@@ -779,6 +796,7 @@ pub type SubstrateHostFunctions = (
allocator::HostFunctions,
logging::HostFunctions,
sandbox::HostFunctions,
crate::trie::HostFunctions,
);
#[cfg(test)]
@@ -384,12 +384,6 @@ pub trait Hash: 'static + MaybeSerializeDeserialize + Debug + Clone + Eq + Parti
/// The Patricia tree root of the given mapping.
fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> Self::Output;
/// Acquire the global storage root.
fn storage_root() -> Self::Output;
/// Acquire the global storage changes root.
fn storage_changes_root(parent_hash: Self::Output) -> Option<Self::Output>;
}
/// Blake2-256 Hash implementation.
@@ -405,19 +399,11 @@ impl Hash for BlakeTwo256 {
}
fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> Self::Output {
runtime_io::storage::blake2_256_trie_root(input)
runtime_io::trie::blake2_256_root(input)
}
fn ordered_trie_root(input: Vec<Vec<u8>>) -> Self::Output {
runtime_io::storage::blake2_256_ordered_trie_root(input)
}
fn storage_root() -> Self::Output {
runtime_io::storage::root().into()
}
fn storage_changes_root(parent_hash: Self::Output) -> Option<Self::Output> {
runtime_io::storage::changes_root(parent_hash.into()).map(Into::into)
runtime_io::trie::blake2_256_ordered_root(input)
}
}
@@ -25,6 +25,7 @@ use trie::{
TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration,
trie_types::{TrieDBMut, Layout},
};
use codec::{Encode, Codec};
/// A state backend is used to read state data and can have changes committed
/// to it.
@@ -95,7 +96,7 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
/// Calculate the child storage root, with given delta over what is already stored in
/// the backend, and produce a "transaction" that can be used to commit. The second argument
/// is true if child storage root equals default storage root.
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord;
@@ -134,7 +135,7 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
I1: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
I2i: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
I2: IntoIterator<Item=(Vec<u8>, I2i)>,
<H as Hasher>::Out: Ord,
H::Out: Ord + Encode,
{
let mut txs: Self::Transaction = Default::default();
let mut child_roots: Vec<_> = Default::default();
@@ -146,7 +147,7 @@ pub trait Backend<H: Hasher>: std::fmt::Debug {
if empty {
child_roots.push((storage_key, None));
} else {
child_roots.push((storage_key, Some(child_root)));
child_roots.push((storage_key, Some(child_root.encode())));
}
}
let (root, parent_txs) = self.storage_root(
@@ -190,7 +191,7 @@ impl<'a, T: Backend<H>, H: Hasher> Backend<H> for &'a T {
(*self).storage_root(delta)
}
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord,
@@ -287,7 +288,7 @@ impl<H: Hasher> PartialEq for InMemory<H> {
}
}
impl<H: Hasher> InMemory<H> {
impl<H: Hasher> InMemory<H> where H::Out: Codec {
/// Copy the state, with applied updates
pub fn update(&self, changes: <Self as Backend<H>>::Transaction) -> Self {
let mut inner: HashMap<_, _> = self.inner.clone();
@@ -362,7 +363,7 @@ impl<H: Hasher> InMemory<H> {
}
}
impl<H: Hasher> Backend<H> for InMemory<H> {
impl<H: Hasher> Backend<H> for InMemory<H> where H::Out: Codec {
type Error = Void;
type Transaction = Vec<(Option<Vec<u8>>, Vec<u8>, Option<Vec<u8>>)>;
type TrieBackendStorage = MemoryDB<H>;
@@ -418,7 +419,7 @@ impl<H: Hasher> Backend<H> for InMemory<H> {
(root, full_transaction)
}
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord
+18 -13
View File
@@ -26,9 +26,10 @@ use primitives::{
well_known_keys::is_child_storage_key, ChildStorageKey, StorageOverlay,
ChildrenStorageOverlay
},
traits::Externalities, Blake2Hasher, hash::H256,
traits::Externalities, Blake2Hasher,
};
use log::warn;
use codec::Encode;
/// Simple HashMap-based Externalities impl.
#[derive(Debug)]
@@ -118,15 +119,15 @@ impl Externalities for BasicExternalities {
self.top.get(key).cloned()
}
fn storage_hash(&self, key: &[u8]) -> Option<H256> {
self.storage(key).map(|v| Blake2Hasher::hash(&v))
fn storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
self.storage(key).map(|v| Blake2Hasher::hash(&v).encode())
}
fn original_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
self.storage(key)
}
fn original_storage_hash(&self, key: &[u8]) -> Option<H256> {
fn original_storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
self.storage_hash(key)
}
@@ -134,11 +135,15 @@ impl Externalities for BasicExternalities {
self.children.get(storage_key.as_ref()).and_then(|child| child.get(key)).cloned()
}
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v))
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v).encode())
}
fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
fn original_child_storage_hash(
&self,
storage_key: ChildStorageKey,
key: &[u8],
) -> Option<Vec<u8>> {
self.child_storage_hash(storage_key, key)
}
@@ -196,7 +201,7 @@ impl Externalities for BasicExternalities {
fn chain_id(&self) -> u64 { 42 }
fn storage_root(&mut self) -> H256 {
fn storage_root(&mut self) -> Vec<u8> {
let mut top = self.top.clone();
let keys: Vec<_> = self.children.keys().map(|k| k.to_vec()).collect();
// Single child trie implementation currently allows using the same child
@@ -215,7 +220,7 @@ impl Externalities for BasicExternalities {
}
}
Layout::<Blake2Hasher>::trie_root(self.top.clone())
Layout::<Blake2Hasher>::trie_root(self.top.clone()).as_ref().into()
}
fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec<u8> {
@@ -225,10 +230,10 @@ impl Externalities for BasicExternalities {
InMemory::<Blake2Hasher>::default().child_storage_root(storage_key.as_ref(), delta).0
} else {
default_child_trie_root::<Layout<Blake2Hasher>>(storage_key.as_ref())
}
}.encode()
}
fn storage_changes_root(&mut self, _parent: H256) -> Result<Option<H256>, ()> {
fn storage_changes_root(&mut self, _parent: &[u8]) -> Result<Option<Vec<u8>>, ()> {
Ok(None)
}
}
@@ -243,7 +248,7 @@ impl externalities::ExtensionStore for BasicExternalities {
#[cfg(test)]
mod tests {
use super::*;
use primitives::{H256, map};
use primitives::map;
use primitives::storage::well_known_keys::CODE;
use hex_literal::hex;
@@ -255,7 +260,7 @@ mod tests {
ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa");
assert_eq!(ext.storage_root(), H256::from(ROOT));
assert_eq!(&ext.storage_root()[..], &ROOT);
}
#[test]
@@ -18,7 +18,7 @@
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Entry;
use codec::Decode;
use codec::{Decode, Encode};
use hash_db::Hasher;
use num_traits::One;
use crate::backend::Backend;
@@ -47,6 +47,7 @@ pub(crate) fn prepare_input<'a, B, H, Number>(
where
B: Backend<H>,
H: Hasher + 'a,
H::Out: Encode,
Number: BlockNumber,
{
let number = parent.number.clone() + One::one();
@@ -200,7 +201,7 @@ fn prepare_digest_input<'a, H, Number>(
), String>
where
H: Hasher,
H::Out: 'a,
H::Out: 'a + Encode,
Number: BlockNumber,
{
let build_skewed_digest = config.end.as_ref() == Some(&block);
@@ -19,7 +19,7 @@
use std::cell::RefCell;
use std::collections::VecDeque;
use codec::{Decode, Encode};
use codec::{Decode, Encode, Codec};
use hash_db::Hasher;
use num_traits::Zero;
use trie::Recorder;
@@ -81,7 +81,7 @@ pub fn key_changes_proof<'a, H: Hasher, Number: BlockNumber>(
max: Number,
storage_key: Option<&[u8]>,
key: &[u8],
) -> Result<Vec<Vec<u8>>, String> {
) -> Result<Vec<Vec<u8>>, String> where H::Out: Codec {
// we can't query any roots before root
let max = ::std::cmp::min(max.clone(), end.number.clone());
@@ -129,7 +129,7 @@ pub fn key_changes_proof_check<'a, H: Hasher, Number: BlockNumber>(
max: Number,
storage_key: Option<&[u8]>,
key: &[u8]
) -> Result<Vec<(Number, u32)>, String> {
) -> Result<Vec<(Number, u32)>, String> where H::Out: Encode {
key_changes_proof_check_with_db(
config,
roots_storage,
@@ -152,7 +152,7 @@ pub fn key_changes_proof_check_with_db<'a, H: Hasher, Number: BlockNumber>(
max: Number,
storage_key: Option<&[u8]>,
key: &[u8]
) -> Result<Vec<(Number, u32)>, String> {
) -> Result<Vec<(Number, u32)>, String> where H::Out: Encode {
// we can't query any roots before root
let max = ::std::cmp::min(max.clone(), end.number.clone());
@@ -316,8 +316,8 @@ pub struct DrilldownIterator<'a, H, Number>
essence: DrilldownIteratorEssence<'a, H, Number>,
}
impl<'a, H: Hasher, Number: BlockNumber> Iterator
for DrilldownIterator<'a, H, Number>
impl<'a, H: Hasher, Number: BlockNumber> Iterator for DrilldownIterator<'a, H, Number>
where H::Out: Encode
{
type Item = Result<(Number, u32), String>;
@@ -358,7 +358,7 @@ impl<'a, H, Number> Iterator for ProvingDrilldownIterator<'a, H, Number>
where
Number: BlockNumber,
H: Hasher,
H::Out: 'a,
H::Out: 'a + Codec,
{
type Item = Result<(Number, u32), String>;
@@ -181,7 +181,7 @@ pub fn build_changes_trie<'a, B: Backend<H>, S: Storage<H, Number>, H: Hasher, N
parent_hash: H::Out,
) -> Result<Option<(MemoryDB<H>, H::Out, CacheAction<H::Out, Number>)>, ()>
where
H::Out: Ord + 'static,
H::Out: Ord + 'static + Encode,
{
let (storage, config) = match (storage, changes.changes_trie_config.as_ref()) {
(Some(storage), Some(config)) => (storage, config),
@@ -25,7 +25,7 @@ use crate::trie_backend_essence::TrieBackendEssence;
use crate::changes_trie::{AnchorBlockId, Configuration, Storage, BlockNumber};
use crate::changes_trie::storage::TrieBackendAdapter;
use crate::changes_trie::input::{ChildIndex, InputKey};
use codec::Decode;
use codec::{Decode, Codec};
/// Get number of oldest block for which changes trie is not pruned
/// given changes trie configuration, pruning parameter and number of
@@ -55,7 +55,7 @@ pub fn prune<S: Storage<H, Number>, H: Hasher, Number: BlockNumber, F: FnMut(H::
min_blocks_to_keep: Number,
current_block: &AnchorBlockId<H::Out, Number>,
mut remove_trie_node: F,
) {
) where H::Out: Codec {
// select range for pruning
let (first, last) = match pruning_range(config, min_blocks_to_keep, current_block.number.clone()) {
@@ -116,7 +116,7 @@ fn prune_trie<S: Storage<H, Number>, H: Hasher, Number: BlockNumber, F: FnMut(H:
storage: &S,
root: H::Out,
remove_trie_node: &mut F,
) {
) where H::Out: Codec {
// enumerate all changes trie' keys, recording all nodes that have been 'touched'
// (effectively - all changes trie nodes)
@@ -221,13 +221,15 @@ mod tests {
storage: &S,
min_blocks_to_keep: u64,
current_block: u64,
) -> HashSet<H::Out> {
) -> HashSet<H::Out> where H::Out: Codec {
let mut pruned_trie_nodes = HashSet::new();
prune(config,
prune(
config,
storage,
min_blocks_to_keep,
&AnchorBlockId { hash: Default::default(), number: current_block },
|node| { pruned_trie_nodes.insert(node); });
|node| { pruned_trie_nodes.insert(node); },
);
pruned_trie_nodes
}
+43 -27
View File
@@ -30,6 +30,7 @@ use primitives::{
};
use trie::{trie_types::Layout, MemoryDB, default_child_trie_root};
use externalities::Extensions;
use codec::{Decode, Encode};
use std::{error, fmt, any::{Any, TypeId}};
use log::{warn, trace};
@@ -189,25 +190,25 @@ where
result
}
fn storage_hash(&self, key: &[u8]) -> Option<H256> {
fn storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
let _guard = panic_handler::AbortGuard::force_abort();
let result = self.overlay
.storage(key)
.map(|x| x.map(|x| H::hash(x)))
.unwrap_or_else(||
self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)
);
.unwrap_or_else(|| self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL));
trace!(target: "state-trace", "{:04x}: Hash {}={:?}",
self.id,
HexDisplay::from(&key),
result,
);
result
result.map(|r| r.encode())
}
fn original_storage(&self, key: &[u8]) -> Option<Vec<u8>> {
let _guard = panic_handler::AbortGuard::force_abort();
let result = self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL);
trace!(target: "state-trace", "{:04x}: GetOriginal {}={:?}",
self.id,
HexDisplay::from(&key),
@@ -216,15 +217,16 @@ where
result
}
fn original_storage_hash(&self, key: &[u8]) -> Option<H256> {
fn original_storage_hash(&self, key: &[u8]) -> Option<Vec<u8>> {
let _guard = panic_handler::AbortGuard::force_abort();
let result = self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL);
trace!(target: "state-trace", "{:04x}: GetOriginalHash {}={:?}",
self.id,
HexDisplay::from(&key),
result,
);
result
result.map(|r| r.encode())
}
fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
@@ -246,7 +248,7 @@ where
result
}
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
let _guard = panic_handler::AbortGuard::force_abort();
let result = self.overlay
.child_storage(storage_key.as_ref(), key)
@@ -262,7 +264,7 @@ where
result,
);
result
result.map(|r| r.encode())
}
fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<Vec<u8>> {
@@ -280,7 +282,11 @@ where
result
}
fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option<H256> {
fn original_child_storage_hash(
&self,
storage_key: ChildStorageKey,
key: &[u8],
) -> Option<Vec<u8>> {
let _guard = panic_handler::AbortGuard::force_abort();
let result = self.backend
.child_storage_hash(storage_key.as_ref(), key)
@@ -292,7 +298,7 @@ where
HexDisplay::from(&key),
result,
);
result
result.map(|r| r.encode())
}
fn exists_storage(&self, key: &[u8]) -> bool {
@@ -415,14 +421,14 @@ where
42
}
fn storage_root(&mut self) -> H256 {
fn storage_root(&mut self) -> Vec<u8> {
let _guard = panic_handler::AbortGuard::force_abort();
if let Some((_, ref root)) = self.storage_transaction {
trace!(target: "state-trace", "{:04x}: Root (cached) {}",
self.id,
HexDisplay::from(&root.as_ref()),
);
return root.clone();
return root.encode();
}
let child_storage_keys =
@@ -447,7 +453,7 @@ where
self.id,
HexDisplay::from(&root.as_ref()),
);
root
root.encode()
}
fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec<u8> {
@@ -455,6 +461,7 @@ where
if self.storage_transaction.is_some() {
let root = self
.storage(storage_key.as_ref())
.and_then(|k| Decode::decode(&mut &k[..]).ok())
.unwrap_or(
default_child_trie_root::<Layout<H>>(storage_key.as_ref())
);
@@ -463,7 +470,7 @@ where
HexDisplay::from(&storage_key.as_ref()),
HexDisplay::from(&root.as_ref()),
);
root
root.encode()
} else {
let storage_key = storage_key.as_ref();
@@ -481,7 +488,7 @@ where
if is_empty {
self.overlay.set_storage(storage_key.into(), None);
} else {
self.overlay.set_storage(storage_key.into(), Some(root.clone()));
self.overlay.set_storage(storage_key.into(), Some(root.encode()));
}
trace!(target: "state-trace", "{:04x}: ChildRoot({}) {}",
@@ -489,20 +496,29 @@ where
HexDisplay::from(&storage_key.as_ref()),
HexDisplay::from(&root.as_ref()),
);
root
root.encode()
}
}
fn storage_changes_root(&mut self, parent_hash: H256) -> Result<Option<H256>, ()> {
fn storage_changes_root(&mut self, parent_hash: &[u8]) -> Result<Option<Vec<u8>>, ()> {
let _guard = panic_handler::AbortGuard::force_abort();
self.changes_trie_transaction = build_changes_trie::<_, T, H, N>(
self.backend,
self.changes_trie_storage.clone(),
self.overlay,
parent_hash,
H256::decode(&mut &parent_hash[..]).map_err(|e|
trace!(
target: "state-trace",
"Failed to decode changes root parent hash: {}",
e,
)
)?,
)?;
let result = Ok(self.changes_trie_transaction.as_ref().map(|(_, root, _)| root.clone()));
let result = Ok(
self.changes_trie_transaction.as_ref().map(|(_, root, _)| root.encode())
);
trace!(target: "state-trace", "{:04x}: ChangesRoot({}) {:?}",
self.id,
HexDisplay::from(&parent_hash.as_ref()),
@@ -566,7 +582,7 @@ mod tests {
let mut overlay = prepare_overlay_with_changes();
let backend = TestBackend::default();
let mut ext = TestExt::new(&mut overlay, &backend, None, None);
assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None);
assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None);
}
#[test]
@@ -576,7 +592,7 @@ mod tests {
let storage = TestChangesTrieStorage::with_blocks(vec![(100, Default::default())]);
let backend = TestBackend::default();
let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None);
assert_eq!(ext.storage_changes_root(Default::default()).unwrap(), None);
assert_eq!(ext.storage_changes_root(&H256::default().encode()).unwrap(), None);
}
#[test]
@@ -586,8 +602,8 @@ mod tests {
let backend = TestBackend::default();
let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None);
assert_eq!(
ext.storage_changes_root(Default::default()).unwrap(),
Some(hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").into()),
ext.storage_changes_root(&H256::default().encode()).unwrap(),
Some(hex!("bb0c2ef6e1d36d5490f9766cfcc7dfe2a6ca804504c3bb206053890d6dd02376").to_vec()),
);
}
@@ -599,8 +615,8 @@ mod tests {
let backend = TestBackend::default();
let mut ext = TestExt::new(&mut overlay, &backend, Some(&storage), None);
assert_eq!(
ext.storage_changes_root(Default::default()).unwrap(),
Some(hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").into()),
ext.storage_changes_root(&H256::default().encode()).unwrap(),
Some(hex!("96f5aae4690e7302737b6f9b7f8567d5bbb9eac1c315f80101235a92d9ec27f4").to_vec()),
);
}
}
@@ -21,7 +21,7 @@
use std::{fmt, result, collections::HashMap, panic::UnwindSafe, marker::PhantomData};
use log::{warn, trace};
use hash_db::Hasher;
use codec::{Decode, Encode};
use codec::{Decode, Encode, Codec};
use primitives::{
storage::well_known_keys, NativeOrEncoded, NeverNativeValue,
traits::CodeExecutor, hexdisplay::HexDisplay, hash::H256,
@@ -567,7 +567,7 @@ pub fn prove_child_read<B, H, I>(
where
B: Backend<H>,
H: Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
@@ -584,7 +584,7 @@ pub fn prove_read_on_trie_backend<S, H, I>(
where
S: trie_backend_essence::TrieBackendStorage<H>,
H: Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
@@ -606,7 +606,7 @@ pub fn prove_child_read_on_trie_backend<S, H, I>(
where
S: trie_backend_essence::TrieBackendStorage<H>,
H: Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
@@ -627,7 +627,7 @@ pub fn read_proof_check<H, I>(
) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, Box<dyn Error>>
where
H: Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
@@ -649,7 +649,7 @@ pub fn read_child_proof_check<H, I>(
) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>, Box<dyn Error>>
where
H: Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
I: IntoIterator,
I::Item: AsRef<[u8]>,
{
@@ -673,7 +673,7 @@ pub fn read_proof_check_on_proving_backend<H>(
) -> Result<Option<Vec<u8>>, Box<dyn Error>>
where
H: Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
{
proving_backend.storage(key).map_err(|e| Box::new(e) as Box<dyn Error>)
}
@@ -686,7 +686,7 @@ pub fn read_child_proof_check_on_proving_backend<H>(
) -> Result<Option<Vec<u8>>, Box<dyn Error>>
where
H: Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
{
proving_backend.child_storage(storage_key, key).map_err(|e| Box::new(e) as Box<dyn Error>)
}
@@ -352,7 +352,7 @@ impl From<Option<Vec<u8>>> for OverlayedValue {
mod tests {
use hex_literal::hex;
use primitives::{
Blake2Hasher, H256, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX,
Blake2Hasher, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX,
};
use crate::backend::InMemory;
use crate::changes_trie::InMemoryStorage as InMemoryChangesTrieStorage;
@@ -426,7 +426,7 @@ mod tests {
);
const ROOT: [u8; 32] = hex!("39245109cef3758c2eed2ccba8d9b370a917850af3824bc8348d505df2c298fa");
assert_eq!(ext.storage_root(), H256::from(ROOT));
assert_eq!(&ext.storage_root()[..], &ROOT);
}
#[test]
@@ -18,7 +18,7 @@
use std::sync::Arc;
use parking_lot::RwLock;
use codec::{Decode, Encode};
use codec::{Decode, Encode, Codec};
use log::debug;
use hash_db::{Hasher, HashDB, EMPTY_PREFIX, Prefix};
use trie::{
@@ -119,6 +119,7 @@ impl<'a, S, H> ProvingBackendRecorder<'a, S, H>
where
S: TrieBackendStorage<H>,
H: Hasher,
H::Out: Codec,
{
/// Produce proof for a key query.
pub fn storage(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>, String> {
@@ -145,6 +146,7 @@ impl<'a, S, H> ProvingBackendRecorder<'a, S, H>
key: &[u8]
) -> Result<Option<Vec<u8>>, String> {
let root = self.storage(storage_key)?
.and_then(|r| Decode::decode(&mut &r[..]).ok())
.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key));
let mut read_overlay = S::Overlay::default();
@@ -158,7 +160,7 @@ impl<'a, S, H> ProvingBackendRecorder<'a, S, H>
read_child_trie_value_with::<Layout<H>, _, _>(
storage_key,
&eph,
&root,
&root.as_ref(),
key,
&mut *self.proof_recorder
).map_err(map_e)
@@ -199,7 +201,9 @@ pub struct ProofRecorderBackend<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hashe
proof_recorder: ProofRecorder<H>,
}
impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> ProvingBackend<'a, S, H> {
impl<'a, S: 'a + TrieBackendStorage<H>, H: 'a + Hasher> ProvingBackend<'a, S, H>
where H::Out: Codec
{
/// Create new proving backend.
pub fn new(backend: &'a TrieBackend<S, H>) -> Self {
let proof_recorder = Default::default();
@@ -254,7 +258,7 @@ impl<'a, S, H> Backend<H> for ProvingBackend<'a, S, H>
where
S: 'a + TrieBackendStorage<H>,
H: 'a + Hasher,
H::Out: Ord,
H::Out: Ord + Codec,
{
type Error = String;
type Transaction = S::Overlay;
@@ -302,7 +306,7 @@ impl<'a, S, H> Backend<H> for ProvingBackend<'a, S, H>
self.0.storage_root(delta)
}
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord
@@ -318,6 +322,7 @@ pub fn create_proof_check_backend<H>(
) -> Result<TrieBackend<MemoryDB<H>, H>, Box<dyn Error>>
where
H: Hasher,
H::Out: Codec,
{
let db = create_proof_check_backend_storage(proof);
@@ -178,7 +178,7 @@ mod tests {
ext.set_storage(b"dog".to_vec(), b"puppy".to_vec());
ext.set_storage(b"dogglesworth".to_vec(), b"cat".to_vec());
const ROOT: [u8; 32] = hex!("2a340d3dfd52f5992c6b117e9e45f479e6da5afffafeb26ab619cf137a95aeb8");
assert_eq!(ext.storage_root(), H256::from(ROOT));
assert_eq!(&ext.storage_root()[..], &ROOT);
}
#[test]
@@ -22,13 +22,14 @@ use trie::{Trie, delta_trie_root, default_child_trie_root, child_delta_trie_root
use trie::trie_types::{TrieDB, TrieError, Layout};
use crate::trie_backend_essence::{TrieBackendEssence, TrieBackendStorage, Ephemeral};
use crate::Backend;
use codec::{Codec, Decode};
/// Patricia trie-based backend. Transaction type is an overlay of changes to commit.
pub struct TrieBackend<S: TrieBackendStorage<H>, H: Hasher> {
essence: TrieBackendEssence<S, H>,
}
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackend<S, H> {
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackend<S, H> where H::Out: Codec {
/// Create new trie-based backend.
pub fn new(storage: S, root: H::Out) -> Self {
TrieBackend {
@@ -64,7 +65,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher> std::fmt::Debug for TrieBackend<S, H>
}
impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
H::Out: Ord,
H::Out: Ord + Codec,
{
type Error = String;
type Transaction = S::Overlay;
@@ -159,16 +160,17 @@ impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
(root, write_overlay)
}
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (Vec<u8>, bool, Self::Transaction)
fn child_storage_root<I>(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction)
where
I: IntoIterator<Item=(Vec<u8>, Option<Vec<u8>>)>,
H::Out: Ord
H::Out: Ord,
{
let default_root = default_child_trie_root::<Layout<H>>(storage_key);
let mut write_overlay = S::Overlay::default();
let mut root = match self.storage(storage_key) {
Ok(value) => value.unwrap_or(default_root.clone()),
Ok(value) =>
value.and_then(|r| Decode::decode(&mut &r[..]).ok()).unwrap_or(default_root.clone()),
Err(e) => {
warn!(target: "trie", "Failed to read child storage root: {}", e);
default_root.clone()
@@ -181,10 +183,10 @@ impl<S: TrieBackendStorage<H>, H: Hasher> Backend<H> for TrieBackend<S, H> where
&mut write_overlay,
);
match child_delta_trie_root::<Layout<H>, _, _, _, _>(
match child_delta_trie_root::<Layout<H>, _, _, _, _, _>(
storage_key,
&mut eph,
root.clone(),
root,
delta
) {
Ok(ret) => root = ret,
@@ -26,6 +26,7 @@ use trie::{Trie, MemoryDB, PrefixedMemoryDB, DBValue,
for_keys_in_child_trie};
use trie::trie_types::{TrieDB, TrieError, Layout};
use crate::backend::Consolidate;
use codec::Encode;
/// Patricia trie-based storage trait.
pub trait Storage<H: Hasher>: Send + Sync {
@@ -39,7 +40,7 @@ pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher> {
root: H::Out,
}
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> where H::Out: Encode {
/// Create new trie-based backend.
pub fn new(storage: S, root: H::Out) -> Self {
TrieBackendEssence {
@@ -79,7 +80,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
/// Get the value of child storage at given key.
pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result<Option<Vec<u8>>, String> {
let root = self.storage(storage_key)?
.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key));
.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key).encode());
let mut read_overlay = S::Overlay::default();
let eph = Ephemeral {
@@ -95,7 +96,7 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
/// Retrieve all entries keys of child storage and call `f` for each of those keys.
pub fn for_keys_in_child_storage<F: FnMut(&[u8])>(&self, storage_key: &[u8], f: F) {
let root = match self.storage(storage_key) {
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key)),
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key).encode()),
Err(e) => {
debug!(target: "trie", "Error while iterating child storage: {}", e);
return;
@@ -119,9 +120,14 @@ impl<S: TrieBackendStorage<H>, H: Hasher> TrieBackendEssence<S, H> {
}
/// Execute given closure for all keys starting with prefix.
pub fn for_child_keys_with_prefix<F: FnMut(&[u8])>(&self, storage_key: &[u8], prefix: &[u8], mut f: F) {
pub fn for_child_keys_with_prefix<F: FnMut(&[u8])>(
&self,
storage_key: &[u8],
prefix: &[u8],
mut f: F,
) {
let root_vec = match self.storage(storage_key) {
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key)),
Ok(v) => v.unwrap_or(default_child_trie_root::<Layout<H>>(storage_key).encode()),
Err(e) => {
debug!(target: "trie", "Error while iterating child storage: {}", e);
return;
+16 -10
View File
@@ -167,39 +167,45 @@ pub fn read_trie_value_with<
}
/// Determine the default child trie root.
pub fn default_child_trie_root<L: TrieConfiguration>(_storage_key: &[u8]) -> Vec<u8> {
L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty()).as_ref().iter().cloned().collect()
pub fn default_child_trie_root<L: TrieConfiguration>(
_storage_key: &[u8],
) -> <L::Hash as Hasher>::Out {
L::trie_root::<_, Vec<u8>, Vec<u8>>(core::iter::empty())
}
/// Determine a child trie root given its ordered contents, closed form. H is the default hasher,
/// but a generic implementation may ignore this type parameter and use other hashers.
pub fn child_trie_root<L: TrieConfiguration, I, A, B>(_storage_key: &[u8], input: I) -> Vec<u8>
pub fn child_trie_root<L: TrieConfiguration, I, A, B>(
_storage_key: &[u8],
input: I,
) -> <L::Hash as Hasher>::Out
where
I: IntoIterator<Item = (A, B)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
{
L::trie_root(input).as_ref().iter().cloned().collect()
L::trie_root(input)
}
/// Determine a child trie root given a hash DB and delta values. H is the default hasher,
/// but a generic implementation may ignore this type parameter and use other hashers.
pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB>(
pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB, RD>(
_storage_key: &[u8],
db: &mut DB,
root_vec: Vec<u8>,
delta: I
) -> Result<Vec<u8>, Box<TrieError<L>>>
root_data: RD,
delta: I,
) -> Result<<L::Hash as Hasher>::Out, Box<TrieError<L>>>
where
I: IntoIterator<Item = (A, Option<B>)>,
A: AsRef<[u8]> + Ord,
B: AsRef<[u8]>,
RD: AsRef<[u8]>,
DB: hash_db::HashDB<L::Hash, trie_db::DBValue>
+ hash_db::PlainDB<TrieHash<L>, trie_db::DBValue>,
{
let mut root = TrieHash::<L>::default();
// root is fetched from DB, not writable by runtime, so it's always valid.
root.as_mut().copy_from_slice(&root_vec);
root.as_mut().copy_from_slice(root_data.as_ref());
{
let mut trie = TrieDBMut::<L>::from_existing(&mut *db, &mut root)?;
@@ -212,7 +218,7 @@ pub fn child_delta_trie_root<L: TrieConfiguration, I, A, B, DB>(
}
}
Ok(root.as_ref().to_vec())
Ok(root)
}
/// Call `f` for all keys in a child trie.
+15 -7
View File
@@ -30,7 +30,7 @@ use sr_primitives::{
TransactionValidity, ValidTransaction, InvalidTransaction, TransactionValidityError,
},
};
use codec::{KeyedVec, Encode};
use codec::{KeyedVec, Encode, Decode};
use frame_system::Trait;
use crate::{
AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest, AuthorityId
@@ -139,20 +139,26 @@ fn execute_block_with_state_root_handler(
});
let o_new_authorities = <NewAuthorities>::take();
let storage_root = Hash::decode(&mut &storage_root()[..])
.expect("`storage_root` is a valid hash");
if let Mode::Overwrite = mode {
header.state_root = storage_root().into();
header.state_root = storage_root;
} else {
// check storage root.
let storage_root = storage_root().into();
info_expect_equal_hash(&storage_root, &header.state_root);
assert!(storage_root == header.state_root, "Storage root must match that calculated.");
}
// check digest
let digest = &mut header.digest;
if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into()) {
digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into()));
if let Some(storage_changes_root) = storage_changes_root(&header.parent_hash.encode()) {
digest.push(
generic::DigestItem::ChangesTrieRoot(
Hash::decode(&mut &storage_changes_root[..])
.expect("`storage_changes_root` is a valid hash")
)
);
}
if let Some(new_authorities) = o_new_authorities {
digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode()));
@@ -226,8 +232,10 @@ pub fn finalize_block() -> Header {
let o_new_authorities = <NewAuthorities>::take();
// This MUST come after all changes to storage are done. Otherwise we will fail the
// “Storage root does not match that calculated” assertion.
let storage_root = BlakeTwo256::storage_root();
let storage_changes_root = BlakeTwo256::storage_changes_root(parent_hash);
let storage_root = Hash::decode(&mut &storage_root()[..])
.expect("`storage_root` is a valid hash");
let storage_changes_root = storage_changes_root(&parent_hash.encode())
.map(|r| Hash::decode(&mut &r[..]).expect("`storage_changes_root` is a valid hash"));
if let Some(storage_changes_root) = storage_changes_root {
digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root));