From b9e7f09a675b5625cc8b156848d976592e07a409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 28 Nov 2019 01:00:29 +0100 Subject: [PATCH] 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 --- Cargo.lock | 1 - bin/node/executor/src/lib.rs | 4 +- client/db/src/lib.rs | 6 +- client/db/src/storage_cache.rs | 2 +- .../executor/src/deprecated_host_interface.rs | 2 +- client/executor/src/wasm_runtime.rs | 12 ++-- client/src/cht.rs | 6 +- client/src/light/backend.rs | 10 +-- client/src/light/fetcher.rs | 4 +- frame/system/src/lib.rs | 10 ++- primitives/externalities/Cargo.toml | 1 - primitives/externalities/src/lib.rs | 44 +++++++++--- primitives/sr-io/src/lib.rs | 30 ++++++-- primitives/sr-primitives/src/traits.rs | 18 +---- primitives/state-machine/src/backend.rs | 15 ++-- primitives/state-machine/src/basic.rs | 31 ++++---- .../state-machine/src/changes_trie/build.rs | 5 +- .../src/changes_trie/changes_iterator.rs | 14 ++-- .../state-machine/src/changes_trie/mod.rs | 2 +- .../state-machine/src/changes_trie/prune.rs | 14 ++-- primitives/state-machine/src/ext.rs | 70 ++++++++++++------- primitives/state-machine/src/lib.rs | 16 ++--- .../state-machine/src/overlayed_changes.rs | 4 +- .../state-machine/src/proving_backend.rs | 15 ++-- primitives/state-machine/src/testing.rs | 2 +- primitives/state-machine/src/trie_backend.rs | 16 +++-- .../state-machine/src/trie_backend_essence.rs | 16 +++-- primitives/trie/src/lib.rs | 26 ++++--- test/utils/runtime/src/system.rs | 22 ++++-- 29 files changed, 253 insertions(+), 165 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 226cce363e7d5..6ae7d4deabf19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", ] diff --git a/bin/node/executor/src/lib.rs b/bin/node/executor/src/lib.rs index b1e5e24ffd328..d85ec452c72c5 100644 --- a/bin/node/executor/src/lib.rs +++ b/bin/node/executor/src/lib.rs @@ -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] diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index dceffc852a646..253b48e6fa15f 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -174,7 +174,7 @@ impl StateBackend for RefTrackingState { self.state.storage_root(delta) } - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (H256, bool, Self::Transaction) where I: IntoIterator, Option>)>, { @@ -193,7 +193,9 @@ impl StateBackend for RefTrackingState { self.state.child_keys(child_key, prefix) } - fn as_trie_backend(&mut self) -> Option<&state_machine::TrieBackend> { + fn as_trie_backend( + &mut self, + ) -> Option<&state_machine::TrieBackend> { self.state.as_trie_backend() } } diff --git a/client/db/src/storage_cache.rs b/client/db/src/storage_cache.rs index 3febc6b4d4807..38848577868aa 100644 --- a/client/db/src/storage_cache.rs +++ b/client/db/src/storage_cache.rs @@ -568,7 +568,7 @@ impl, B: BlockT> StateBackend for CachingState< self.state.storage_root(delta) } - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord diff --git a/client/executor/src/deprecated_host_interface.rs b/client/executor/src/deprecated_host_interface.rs index 223b13367aa87..f74a9597e57fb 100644 --- a/client/executor/src/deprecated_host_interface.rs +++ b/client/executor/src/deprecated_host_interface.rs @@ -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) diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index c58f63a1e03de..5014c0581609e 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -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>, + instances: HashMap<(WasmExecutionMethod, Vec), Result>, } 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), 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, ) { // 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)); } } diff --git a/client/src/cht.rs b/client/src/cht.rs index dc49069f0afa0..7e0552f2f267a 100644 --- a/client/src/cht.rs +++ b/client/src/cht.rs @@ -92,7 +92,7 @@ pub fn build_proof( where Header: HeaderT, Hasher: hash_db::Hasher, - Hasher::Out: Ord, + Hasher::Out: Ord + codec::Codec, BlocksI: IntoIterator, HashesI: IntoIterator>>, { @@ -119,7 +119,7 @@ pub fn check_proof( where Header: HeaderT, Hasher: hash_db::Hasher, - Hasher::Out: Ord, + Hasher::Out: Ord + codec::Codec, { do_check_proof::( local_root, @@ -148,7 +148,7 @@ pub fn check_proof_on_proving_backend( where Header: HeaderT, Hasher: hash_db::Hasher, - Hasher::Out: Ord, + Hasher::Out: Ord + codec::Codec, { do_check_proof::( local_root, diff --git a/client/src/light/backend.rs b/client/src/light/backend.rs index da21ebf9e8640..2077713ba5481 100644 --- a/client/src/light/backend.rs +++ b/client/src/light/backend.rs @@ -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 std::fmt::Debug for GenesisOrUnavailableState { impl StateBackend for GenesisOrUnavailableState where - H::Out: Ord, + H::Out: Ord + codec::Codec, { type Error = ClientError; type Transaction = (); @@ -409,7 +411,7 @@ impl StateBackend for GenesisOrUnavailableState } } - fn child_storage_root(&self, key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)> { @@ -418,7 +420,7 @@ impl StateBackend for GenesisOrUnavailableState 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, ()), } } diff --git a/client/src/light/fetcher.rs b/client/src/light/fetcher.rs index d3f9436262d91..9db6dda172d1b 100644 --- a/client/src/light/fetcher.rs +++ b/client/src/light/fetcher.rs @@ -70,7 +70,7 @@ impl> LightDataChecker { ) -> ClientResult, 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> LightDataChecker { ) -> 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); diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 611ec2ff16093..17fb3fbf0ef22 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -668,13 +668,17 @@ impl Module { } } - 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); } diff --git a/primitives/externalities/Cargo.toml b/primitives/externalities/Cargo.toml index 0b806ecee0494..ec4fa9a9a5d29 100644 --- a/primitives/externalities/Cargo.toml +++ b/primitives/externalities/Cargo.toml @@ -6,7 +6,6 @@ authors = ["Parity Technologies "] 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" } diff --git a/primitives/externalities/src/lib.rs b/primitives/externalities/src/lib.rs index 4efbc54a4edc9..da3fe16d77945 100644 --- a/primitives/externalities/src/lib.rs +++ b/primitives/externalities/src/lib.rs @@ -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>; /// Get storage value hash. This may be optimized for large values. - fn storage_hash(&self, key: &[u8]) -> Option; + fn storage_hash(&self, key: &[u8]) -> Option>; /// Get child storage value hash. This may be optimized for large values. - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option; + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; /// Read original runtime storage, ignoring any overlayed changes. fn original_storage(&self, key: &[u8]) -> Option>; /// 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>; /// Get original storage value hash, ignoring any overlayed changes. /// This may be optimized for large values. - fn original_storage_hash(&self, key: &[u8]) -> Option; + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn original_storage_hash(&self, key: &[u8]) -> Option>; /// 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; + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn original_child_storage_hash( + &self, + storage_key: ChildStorageKey, + key: &[u8], + ) -> Option>; /// Read child runtime storage. + /// + /// Returns an `Option` that holds the SCALE encoded hash. fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; /// 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, value: Option>); /// Set or clear a child storage entry. Return whether the operation succeeds. - fn place_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Option>); + fn place_child_storage( + &mut self, + storage_key: ChildStorageKey, + key: Vec, + value: Option>, + ); /// 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; /// 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; /// 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, ()>; + /// `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>, ()>; } /// Extension for the [`Externalities`] trait. diff --git a/primitives/sr-io/src/lib.rs b/primitives/sr-io/src/lib.rs index 589b6a1dd1aad..40d52db98b0a8 100644 --- a/primitives/sr-io/src/lib.rs +++ b/primitives/sr-io/src/lib.rs @@ -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 { 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 { 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 { - 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> { + 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, Vec)>) -> H256 { + fn blake2_256_root(input: Vec<(Vec, Vec)>) -> H256 { Layout::::trie_root(input) } /// A trie root formed from the enumerated items. - fn blake2_256_ordered_trie_root(input: Vec>) -> H256 { + fn blake2_256_ordered_root(input: Vec>) -> H256 { Layout::::ordered_trie_root(input) } } @@ -779,6 +796,7 @@ pub type SubstrateHostFunctions = ( allocator::HostFunctions, logging::HostFunctions, sandbox::HostFunctions, + crate::trie::HostFunctions, ); #[cfg(test)] diff --git a/primitives/sr-primitives/src/traits.rs b/primitives/sr-primitives/src/traits.rs index 84ac039a1d945..7c6a88acc2368 100644 --- a/primitives/sr-primitives/src/traits.rs +++ b/primitives/sr-primitives/src/traits.rs @@ -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, Vec)>) -> 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; } /// Blake2-256 Hash implementation. @@ -405,19 +399,11 @@ impl Hash for BlakeTwo256 { } fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { - runtime_io::storage::blake2_256_trie_root(input) + runtime_io::trie::blake2_256_root(input) } fn ordered_trie_root(input: Vec>) -> 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 { - runtime_io::storage::changes_root(parent_hash.into()).map(Into::into) + runtime_io::trie::blake2_256_ordered_root(input) } } diff --git a/primitives/state-machine/src/backend.rs b/primitives/state-machine/src/backend.rs index 5fbda1aa32f45..366634ae1a9d7 100644 --- a/primitives/state-machine/src/backend.rs +++ b/primitives/state-machine/src/backend.rs @@ -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: 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(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord; @@ -134,7 +135,7 @@ pub trait Backend: std::fmt::Debug { I1: IntoIterator, Option>)>, I2i: IntoIterator, Option>)>, I2: IntoIterator, I2i)>, - ::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: 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: Hasher> Backend for &'a T { (*self).storage_root(delta) } - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord, @@ -287,7 +288,7 @@ impl PartialEq for InMemory { } } -impl InMemory { +impl InMemory where H::Out: Codec { /// Copy the state, with applied updates pub fn update(&self, changes: >::Transaction) -> Self { let mut inner: HashMap<_, _> = self.inner.clone(); @@ -362,7 +363,7 @@ impl InMemory { } } -impl Backend for InMemory { +impl Backend for InMemory where H::Out: Codec { type Error = Void; type Transaction = Vec<(Option>, Vec, Option>)>; type TrieBackendStorage = MemoryDB; @@ -418,7 +419,7 @@ impl Backend for InMemory { (root, full_transaction) } - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord diff --git a/primitives/state-machine/src/basic.rs b/primitives/state-machine/src/basic.rs index e758b3dd3b814..82a0c21f20969 100644 --- a/primitives/state-machine/src/basic.rs +++ b/primitives/state-machine/src/basic.rs @@ -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 { - self.storage(key).map(|v| Blake2Hasher::hash(&v)) + fn storage_hash(&self, key: &[u8]) -> Option> { + self.storage(key).map(|v| Blake2Hasher::hash(&v).encode()) } fn original_storage(&self, key: &[u8]) -> Option> { self.storage(key) } - fn original_storage_hash(&self, key: &[u8]) -> Option { + fn original_storage_hash(&self, key: &[u8]) -> Option> { 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 { - self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v)) + fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + self.child_storage(storage_key, key).map(|v| Blake2Hasher::hash(&v).encode()) } - fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + fn original_child_storage_hash( + &self, + storage_key: ChildStorageKey, + key: &[u8], + ) -> Option> { 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 { 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::::trie_root(self.top.clone()) + Layout::::trie_root(self.top.clone()).as_ref().into() } fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { @@ -225,10 +230,10 @@ impl Externalities for BasicExternalities { InMemory::::default().child_storage_root(storage_key.as_ref(), delta).0 } else { default_child_trie_root::>(storage_key.as_ref()) - } + }.encode() } - fn storage_changes_root(&mut self, _parent: H256) -> Result, ()> { + fn storage_changes_root(&mut self, _parent: &[u8]) -> Result>, ()> { 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] diff --git a/primitives/state-machine/src/changes_trie/build.rs b/primitives/state-machine/src/changes_trie/build.rs index 10c38a41e2650..6c50c028ca66e 100644 --- a/primitives/state-machine/src/changes_trie/build.rs +++ b/primitives/state-machine/src/changes_trie/build.rs @@ -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: 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); diff --git a/primitives/state-machine/src/changes_trie/changes_iterator.rs b/primitives/state-machine/src/changes_trie/changes_iterator.rs index 2f61b87fe2199..017eb33d5270f 100644 --- a/primitives/state-machine/src/changes_trie/changes_iterator.rs +++ b/primitives/state-machine/src/changes_trie/changes_iterator.rs @@ -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>, String> { +) -> Result>, 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, String> { +) -> Result, 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, String> { +) -> Result, 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>; diff --git a/primitives/state-machine/src/changes_trie/mod.rs b/primitives/state-machine/src/changes_trie/mod.rs index f771fddf61964..0542ec6268156 100644 --- a/primitives/state-machine/src/changes_trie/mod.rs +++ b/primitives/state-machine/src/changes_trie/mod.rs @@ -181,7 +181,7 @@ pub fn build_changes_trie<'a, B: Backend, S: Storage, H: Hasher, N parent_hash: H::Out, ) -> Result, H::Out, CacheAction)>, ()> 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), diff --git a/primitives/state-machine/src/changes_trie/prune.rs b/primitives/state-machine/src/changes_trie/prune.rs index fccd177e60a2f..2f39f9162cc81 100644 --- a/primitives/state-machine/src/changes_trie/prune.rs +++ b/primitives/state-machine/src/changes_trie/prune.rs @@ -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, H: Hasher, Number: BlockNumber, F: FnMut(H:: min_blocks_to_keep: Number, current_block: &AnchorBlockId, 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, 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 { + ) -> HashSet 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 } diff --git a/primitives/state-machine/src/ext.rs b/primitives/state-machine/src/ext.rs index 0e93302a95a54..57197a4ae3c45 100644 --- a/primitives/state-machine/src/ext.rs +++ b/primitives/state-machine/src/ext.rs @@ -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 { + fn storage_hash(&self, key: &[u8]) -> Option> { 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> { 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 { + fn original_storage_hash(&self, key: &[u8]) -> Option> { 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> { @@ -246,7 +248,7 @@ where result } - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { 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> { @@ -280,7 +282,11 @@ where result } - fn original_child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + fn original_child_storage_hash( + &self, + storage_key: ChildStorageKey, + key: &[u8], + ) -> Option> { 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 { 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 { @@ -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::>(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, ()> { + fn storage_changes_root(&mut self, parent_hash: &[u8]) -> Result>, ()> { 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()), ); } } diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index 151b1a776fd84..d4798ad4fb185 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -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( where B: Backend, 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( where S: trie_backend_essence::TrieBackendStorage, 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( where S: trie_backend_essence::TrieBackendStorage, H: Hasher, - H::Out: Ord, + H::Out: Ord + Codec, I: IntoIterator, I::Item: AsRef<[u8]>, { @@ -627,7 +627,7 @@ pub fn read_proof_check( ) -> Result, Option>>, Box> 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( ) -> Result, Option>>, Box> 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( ) -> Result>, Box> where H: Hasher, - H::Out: Ord, + H::Out: Ord + Codec, { proving_backend.storage(key).map_err(|e| Box::new(e) as Box) } @@ -686,7 +686,7 @@ pub fn read_child_proof_check_on_proving_backend( ) -> Result>, Box> 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) } diff --git a/primitives/state-machine/src/overlayed_changes.rs b/primitives/state-machine/src/overlayed_changes.rs index 73cb8b604a1c2..9bbfd68f67893 100644 --- a/primitives/state-machine/src/overlayed_changes.rs +++ b/primitives/state-machine/src/overlayed_changes.rs @@ -352,7 +352,7 @@ impl From>> 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] diff --git a/primitives/state-machine/src/proving_backend.rs b/primitives/state-machine/src/proving_backend.rs index 2ebd82f0c43c0..446dc635e1c6c 100644 --- a/primitives/state-machine/src/proving_backend.rs +++ b/primitives/state-machine/src/proving_backend.rs @@ -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: Hasher, + H::Out: Codec, { /// Produce proof for a key query. pub fn storage(&mut self, key: &[u8]) -> Result>, String> { @@ -145,6 +146,7 @@ impl<'a, S, H> ProvingBackendRecorder<'a, S, H> key: &[u8] ) -> Result>, String> { let root = self.storage(storage_key)? + .and_then(|r| Decode::decode(&mut &r[..]).ok()) .unwrap_or(default_child_trie_root::>(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::, _, _>( 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: 'a + Hashe proof_recorder: ProofRecorder, } -impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> ProvingBackend<'a, S, H> { +impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> ProvingBackend<'a, S, H> + where H::Out: Codec +{ /// Create new proving backend. pub fn new(backend: &'a TrieBackend) -> Self { let proof_recorder = Default::default(); @@ -254,7 +258,7 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> where S: 'a + TrieBackendStorage, 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 for ProvingBackend<'a, S, H> self.0.storage_root(delta) } - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, H::Out: Ord @@ -318,6 +322,7 @@ pub fn create_proof_check_backend( ) -> Result, H>, Box> where H: Hasher, + H::Out: Codec, { let db = create_proof_check_backend_storage(proof); diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index 61b338bc81acd..dd4f7c557e987 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -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] diff --git a/primitives/state-machine/src/trie_backend.rs b/primitives/state-machine/src/trie_backend.rs index 432ccf3e75f0e..a2ca5c5d4af93 100644 --- a/primitives/state-machine/src/trie_backend.rs +++ b/primitives/state-machine/src/trie_backend.rs @@ -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, H: Hasher> { essence: TrieBackendEssence, } -impl, H: Hasher> TrieBackend { +impl, H: Hasher> TrieBackend where H::Out: Codec { /// Create new trie-based backend. pub fn new(storage: S, root: H::Out) -> Self { TrieBackend { @@ -64,7 +65,7 @@ impl, H: Hasher> std::fmt::Debug for TrieBackend } impl, H: Hasher> Backend for TrieBackend where - H::Out: Ord, + H::Out: Ord + Codec, { type Error = String; type Transaction = S::Overlay; @@ -159,16 +160,17 @@ impl, H: Hasher> Backend for TrieBackend where (root, write_overlay) } - fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (H::Out, bool, Self::Transaction) where I: IntoIterator, Option>)>, - H::Out: Ord + H::Out: Ord, { let default_root = default_child_trie_root::>(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, H: Hasher> Backend for TrieBackend where &mut write_overlay, ); - match child_delta_trie_root::, _, _, _, _>( + match child_delta_trie_root::, _, _, _, _, _>( storage_key, &mut eph, - root.clone(), + root, delta ) { Ok(ret) => root = ret, diff --git a/primitives/state-machine/src/trie_backend_essence.rs b/primitives/state-machine/src/trie_backend_essence.rs index 5a5431963448c..a8572aff6019a 100644 --- a/primitives/state-machine/src/trie_backend_essence.rs +++ b/primitives/state-machine/src/trie_backend_essence.rs @@ -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: Send + Sync { @@ -39,7 +40,7 @@ pub struct TrieBackendEssence, H: Hasher> { root: H::Out, } -impl, H: Hasher> TrieBackendEssence { +impl, H: Hasher> TrieBackendEssence where H::Out: Encode { /// Create new trie-based backend. pub fn new(storage: S, root: H::Out) -> Self { TrieBackendEssence { @@ -79,7 +80,7 @@ impl, H: Hasher> TrieBackendEssence { /// Get the value of child storage at given key. pub fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, String> { let root = self.storage(storage_key)? - .unwrap_or(default_child_trie_root::>(storage_key)); + .unwrap_or(default_child_trie_root::>(storage_key).encode()); let mut read_overlay = S::Overlay::default(); let eph = Ephemeral { @@ -95,7 +96,7 @@ impl, H: Hasher> TrieBackendEssence { /// Retrieve all entries keys of child storage and call `f` for each of those keys. pub fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { let root = match self.storage(storage_key) { - Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key)), + Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key).encode()), Err(e) => { debug!(target: "trie", "Error while iterating child storage: {}", e); return; @@ -119,9 +120,14 @@ impl, H: Hasher> TrieBackendEssence { } /// Execute given closure for all keys starting with prefix. - pub fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], mut f: F) { + pub fn for_child_keys_with_prefix( + &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::>(storage_key)), + Ok(v) => v.unwrap_or(default_child_trie_root::>(storage_key).encode()), Err(e) => { debug!(target: "trie", "Error while iterating child storage: {}", e); return; diff --git a/primitives/trie/src/lib.rs b/primitives/trie/src/lib.rs index de056cace1b7e..e1315f011f2a8 100644 --- a/primitives/trie/src/lib.rs +++ b/primitives/trie/src/lib.rs @@ -167,39 +167,45 @@ pub fn read_trie_value_with< } /// Determine the default child trie root. -pub fn default_child_trie_root(_storage_key: &[u8]) -> Vec { - L::trie_root::<_, Vec, Vec>(core::iter::empty()).as_ref().iter().cloned().collect() +pub fn default_child_trie_root( + _storage_key: &[u8], +) -> ::Out { + L::trie_root::<_, Vec, Vec>(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(_storage_key: &[u8], input: I) -> Vec +pub fn child_trie_root( + _storage_key: &[u8], + input: I, +) -> ::Out where I: IntoIterator, 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( +pub fn child_delta_trie_root( _storage_key: &[u8], db: &mut DB, - root_vec: Vec, - delta: I -) -> Result, Box>> + root_data: RD, + delta: I, +) -> Result<::Out, Box>> where I: IntoIterator)>, A: AsRef<[u8]> + Ord, B: AsRef<[u8]>, + RD: AsRef<[u8]>, DB: hash_db::HashDB + hash_db::PlainDB, trie_db::DBValue>, { let mut root = TrieHash::::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::::from_existing(&mut *db, &mut root)?; @@ -212,7 +218,7 @@ pub fn child_delta_trie_root( } } - Ok(root.as_ref().to_vec()) + Ok(root) } /// Call `f` for all keys in a child trie. diff --git a/test/utils/runtime/src/system.rs b/test/utils/runtime/src/system.rs index 1ac318c417c27..1a04da1764323 100644 --- a/test/utils/runtime/src/system.rs +++ b/test/utils/runtime/src/system.rs @@ -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 = ::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 = ::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));