From 3e26fceda412f6c0f280ef1ed847c392384cd523 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 --- substrate/Cargo.lock | 1 - substrate/bin/node/executor/src/lib.rs | 4 +- substrate/client/db/src/lib.rs | 6 +- substrate/client/db/src/storage_cache.rs | 2 +- .../executor/src/deprecated_host_interface.rs | 2 +- substrate/client/executor/src/wasm_runtime.rs | 12 ++-- substrate/client/src/cht.rs | 6 +- substrate/client/src/light/backend.rs | 10 +-- substrate/client/src/light/fetcher.rs | 4 +- substrate/frame/system/src/lib.rs | 10 ++- substrate/primitives/externalities/Cargo.toml | 1 - substrate/primitives/externalities/src/lib.rs | 44 +++++++++--- substrate/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 ++-- substrate/primitives/state-machine/src/ext.rs | 70 ++++++++++++------- substrate/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 +- .../state-machine/src/trie_backend.rs | 16 +++-- .../state-machine/src/trie_backend_essence.rs | 16 +++-- substrate/primitives/trie/src/lib.rs | 26 ++++--- substrate/test/utils/runtime/src/system.rs | 22 ++++-- 29 files changed, 253 insertions(+), 165 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 226cce363e..6ae7d4deab 100644 --- a/substrate/Cargo.lock +++ b/substrate/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/substrate/bin/node/executor/src/lib.rs b/substrate/bin/node/executor/src/lib.rs index b1e5e24ffd..d85ec452c7 100644 --- a/substrate/bin/node/executor/src/lib.rs +++ b/substrate/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/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index dceffc852a..253b48e6fa 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/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/substrate/client/db/src/storage_cache.rs b/substrate/client/db/src/storage_cache.rs index 3febc6b4d4..3884857786 100644 --- a/substrate/client/db/src/storage_cache.rs +++ b/substrate/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/substrate/client/executor/src/deprecated_host_interface.rs b/substrate/client/executor/src/deprecated_host_interface.rs index 223b13367a..f74a9597e5 100644 --- a/substrate/client/executor/src/deprecated_host_interface.rs +++ b/substrate/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/substrate/client/executor/src/wasm_runtime.rs b/substrate/client/executor/src/wasm_runtime.rs index c58f63a1e0..5014c05816 100644 --- a/substrate/client/executor/src/wasm_runtime.rs +++ b/substrate/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/substrate/client/src/cht.rs b/substrate/client/src/cht.rs index dc49069f0a..7e0552f2f2 100644 --- a/substrate/client/src/cht.rs +++ b/substrate/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/substrate/client/src/light/backend.rs b/substrate/client/src/light/backend.rs index da21ebf9e8..2077713ba5 100644 --- a/substrate/client/src/light/backend.rs +++ b/substrate/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/substrate/client/src/light/fetcher.rs b/substrate/client/src/light/fetcher.rs index d3f9436262..9db6dda172 100644 --- a/substrate/client/src/light/fetcher.rs +++ b/substrate/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/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index 611ec2ff16..17fb3fbf0e 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/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/substrate/primitives/externalities/Cargo.toml b/substrate/primitives/externalities/Cargo.toml index 0b806ecee0..ec4fa9a9a5 100644 --- a/substrate/primitives/externalities/Cargo.toml +++ b/substrate/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/substrate/primitives/externalities/src/lib.rs b/substrate/primitives/externalities/src/lib.rs index 4efbc54a4e..da3fe16d77 100644 --- a/substrate/primitives/externalities/src/lib.rs +++ b/substrate/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/substrate/primitives/sr-io/src/lib.rs b/substrate/primitives/sr-io/src/lib.rs index 589b6a1dd1..40d52db98b 100644 --- a/substrate/primitives/sr-io/src/lib.rs +++ b/substrate/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/substrate/primitives/sr-primitives/src/traits.rs b/substrate/primitives/sr-primitives/src/traits.rs index 84ac039a1d..7c6a88acc2 100644 --- a/substrate/primitives/sr-primitives/src/traits.rs +++ b/substrate/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/substrate/primitives/state-machine/src/backend.rs b/substrate/primitives/state-machine/src/backend.rs index 5fbda1aa32..366634ae1a 100644 --- a/substrate/primitives/state-machine/src/backend.rs +++ b/substrate/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/substrate/primitives/state-machine/src/basic.rs b/substrate/primitives/state-machine/src/basic.rs index e758b3dd3b..82a0c21f20 100644 --- a/substrate/primitives/state-machine/src/basic.rs +++ b/substrate/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/substrate/primitives/state-machine/src/changes_trie/build.rs b/substrate/primitives/state-machine/src/changes_trie/build.rs index 10c38a41e2..6c50c028ca 100644 --- a/substrate/primitives/state-machine/src/changes_trie/build.rs +++ b/substrate/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/substrate/primitives/state-machine/src/changes_trie/changes_iterator.rs b/substrate/primitives/state-machine/src/changes_trie/changes_iterator.rs index 2f61b87fe2..017eb33d52 100644 --- a/substrate/primitives/state-machine/src/changes_trie/changes_iterator.rs +++ b/substrate/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/substrate/primitives/state-machine/src/changes_trie/mod.rs b/substrate/primitives/state-machine/src/changes_trie/mod.rs index f771fddf61..0542ec6268 100644 --- a/substrate/primitives/state-machine/src/changes_trie/mod.rs +++ b/substrate/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/substrate/primitives/state-machine/src/changes_trie/prune.rs b/substrate/primitives/state-machine/src/changes_trie/prune.rs index fccd177e60..2f39f9162c 100644 --- a/substrate/primitives/state-machine/src/changes_trie/prune.rs +++ b/substrate/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/substrate/primitives/state-machine/src/ext.rs b/substrate/primitives/state-machine/src/ext.rs index 0e93302a95..57197a4ae3 100644 --- a/substrate/primitives/state-machine/src/ext.rs +++ b/substrate/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/substrate/primitives/state-machine/src/lib.rs b/substrate/primitives/state-machine/src/lib.rs index 151b1a776f..d4798ad4fb 100644 --- a/substrate/primitives/state-machine/src/lib.rs +++ b/substrate/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/substrate/primitives/state-machine/src/overlayed_changes.rs b/substrate/primitives/state-machine/src/overlayed_changes.rs index 73cb8b604a..9bbfd68f67 100644 --- a/substrate/primitives/state-machine/src/overlayed_changes.rs +++ b/substrate/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/substrate/primitives/state-machine/src/proving_backend.rs b/substrate/primitives/state-machine/src/proving_backend.rs index 2ebd82f0c4..446dc635e1 100644 --- a/substrate/primitives/state-machine/src/proving_backend.rs +++ b/substrate/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/substrate/primitives/state-machine/src/testing.rs b/substrate/primitives/state-machine/src/testing.rs index 61b338bc81..dd4f7c557e 100644 --- a/substrate/primitives/state-machine/src/testing.rs +++ b/substrate/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/substrate/primitives/state-machine/src/trie_backend.rs b/substrate/primitives/state-machine/src/trie_backend.rs index 432ccf3e75..a2ca5c5d4a 100644 --- a/substrate/primitives/state-machine/src/trie_backend.rs +++ b/substrate/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/substrate/primitives/state-machine/src/trie_backend_essence.rs b/substrate/primitives/state-machine/src/trie_backend_essence.rs index 5a54319634..a8572aff60 100644 --- a/substrate/primitives/state-machine/src/trie_backend_essence.rs +++ b/substrate/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/substrate/primitives/trie/src/lib.rs b/substrate/primitives/trie/src/lib.rs index de056cace1..e1315f011f 100644 --- a/substrate/primitives/trie/src/lib.rs +++ b/substrate/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/substrate/test/utils/runtime/src/system.rs b/substrate/test/utils/runtime/src/system.rs index 1ac318c417..1a04da1764 100644 --- a/substrate/test/utils/runtime/src/system.rs +++ b/substrate/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));