diff --git a/substrate/core/client/db/src/lib.rs b/substrate/core/client/db/src/lib.rs index f5ece21fbb..722309b415 100644 --- a/substrate/core/client/db/src/lib.rs +++ b/substrate/core/client/db/src/lib.rs @@ -47,18 +47,20 @@ use hash_db::{Hasher, Prefix}; use kvdb::{KeyValueDB, DBTransaction}; use trie::{MemoryDB, PrefixedMemoryDB, prefixed_key}; use parking_lot::{Mutex, RwLock}; -use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash}; +use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash, traits::CodeExecutor}; use primitives::storage::well_known_keys; use sr_primitives::{ generic::{BlockId, DigestItem}, Justification, StorageOverlay, ChildrenStorageOverlay, - BuildStorage + BuildStorage, }; use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion }; -use state_machine::backend::Backend as StateBackend; use executor::RuntimeInfo; -use state_machine::{CodeExecutor, DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, ChangesTrieBuildCache}; +use state_machine::{ + DBValue, ChangesTrieTransaction, ChangesTrieCacheAction, ChangesTrieBuildCache, + backend::Backend as StateBackend, +}; use crate::utils::{Meta, db_err, meta_keys, read_db, block_id_to_lookup_key, read_meta}; use client::leaves::{LeafSet, FinalizationDisplaced}; use client::children; diff --git a/substrate/core/client/src/backend.rs b/substrate/core/client/src/backend.rs index ad683ebac1..e7b5045336 100644 --- a/substrate/core/client/src/backend.rs +++ b/substrate/core/client/src/backend.rs @@ -144,7 +144,7 @@ pub trait Finalizer, B: Backend error::Result<()>; - + /// Finalize a block. This will implicitly finalize all blocks up to it and /// fire finality notifications. /// diff --git a/substrate/core/client/src/call_executor.rs b/substrate/core/client/src/call_executor.rs index 0556bc7bff..b49a58a0e5 100644 --- a/substrate/core/client/src/call_executor.rs +++ b/substrate/core/client/src/call_executor.rs @@ -20,13 +20,15 @@ use sr_primitives::{ generic::BlockId, traits::Block as BlockT, traits::NumberFor, }; use state_machine::{ - self, OverlayedChanges, Ext, CodeExecutor, ExecutionManager, - ExecutionStrategy, NeverOffchainExt, backend::Backend as _, - ChangesTrieTransaction, + self, OverlayedChanges, Ext, ExecutionManager, StateMachine, ExecutionStrategy, + backend::Backend as _, ChangesTrieTransaction, }; use executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; use hash_db::Hasher; -use primitives::{offchain, H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue}; +use primitives::{ + offchain::{self, NeverOffchainExt}, H256, Blake2Hasher, NativeOrEncoded, NeverNativeValue, + traits::CodeExecutor, +}; use crate::runtime_api::{ProofRecorder, InitializeBlock}; use crate::backend; @@ -204,7 +206,7 @@ where ) -> error::Result> { let mut changes = OverlayedChanges::default(); let state = self.backend.state_at(*id)?; - let return_data = state_machine::new( + let return_data = StateMachine::new( &state, self.backend.changes_trie_storage(), side_effects_handler, @@ -277,7 +279,7 @@ where recorder.clone() ); - state_machine::new( + StateMachine::new( &backend, self.backend.changes_trie_storage(), side_effects_handler, @@ -295,7 +297,7 @@ where .map(|(result, _, _)| result) .map_err(Into::into) } - None => state_machine::new( + None => StateMachine::new( &state, self.backend.changes_trie_storage(), side_effects_handler, @@ -354,7 +356,7 @@ where (S::Transaction, ::Out), Option>>, )> { - state_machine::new( + StateMachine::new( state, self.backend.changes_trie_storage(), side_effects_handler, diff --git a/substrate/core/client/src/client.rs b/substrate/core/client/src/client.rs index 90cdff9fa8..c7df30d8ae 100644 --- a/substrate/core/client/src/client.rs +++ b/substrate/core/client/src/client.rs @@ -26,10 +26,9 @@ use parking_lot::{Mutex, RwLock}; use codec::{Encode, Decode}; use hash_db::{Hasher, Prefix}; use primitives::{ - Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, - NeverNativeValue, ExecutionContext, NativeOrEncoded, - storage::{StorageKey, StorageData, well_known_keys}, - offchain, + Blake2Hasher, H256, ChangesTrieConfiguration, convert_hash, NeverNativeValue, ExecutionContext, + NativeOrEncoded, storage::{StorageKey, StorageData, well_known_keys}, + offchain::{NeverOffchainExt, self}, traits::CodeExecutor, }; use substrate_telemetry::{telemetry, SUBSTRATE_INFO}; use sr_primitives::{ @@ -41,11 +40,10 @@ use sr_primitives::{ }, }; use state_machine::{ - DBValue, Backend as StateBackend, CodeExecutor, ChangesTrieAnchorBlockId, - ExecutionStrategy, ExecutionManager, prove_read, prove_child_read, - ChangesTrieRootsStorage, ChangesTrieStorage, - ChangesTrieTransaction, ChangesTrieConfigurationRange, - key_changes, key_changes_proof, OverlayedChanges, NeverOffchainExt, + DBValue, Backend as StateBackend, ChangesTrieAnchorBlockId, ExecutionStrategy, ExecutionManager, + prove_read, prove_child_read, ChangesTrieRootsStorage, ChangesTrieStorage, + ChangesTrieTransaction, ChangesTrieConfigurationRange, key_changes, key_changes_proof, + OverlayedChanges, }; use executor::{RuntimeVersion, RuntimeInfo}; use consensus::{ diff --git a/substrate/core/client/src/error.rs b/substrate/core/client/src/error.rs index 6f087df9de..922d122b42 100644 --- a/substrate/core/client/src/error.rs +++ b/substrate/core/client/src/error.rs @@ -131,9 +131,7 @@ impl Error { } /// Chain a state error. - pub fn from_state(e: Box) -> Self { + pub fn from_state(e: Box) -> Self { Error::Execution(e) } } - -impl state_machine::Error for Error {} diff --git a/substrate/core/client/src/genesis.rs b/substrate/core/client/src/genesis.rs index 88529114e2..2f31462955 100644 --- a/substrate/core/client/src/genesis.rs +++ b/substrate/core/client/src/genesis.rs @@ -24,7 +24,10 @@ pub fn construct_genesis_block< > ( state_root: Block::Hash ) -> Block { - let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root(::std::iter::empty::<(&[u8], &[u8])>()); + let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( + std::iter::empty::<(&[u8], &[u8])>(), + ); + Block::new( <::Header as HeaderT>::new( Zero::zero(), @@ -41,14 +44,16 @@ pub fn construct_genesis_block< mod tests { use codec::{Encode, Decode, Joiner}; use executor::native_executor_instance; - use state_machine::{self, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage}; + use state_machine::{ + StateMachine, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage, + }; use state_machine::backend::InMemory; use test_client::{ runtime::genesismap::{GenesisConfig, insert_genesis_block}, runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest}, AccountKeyring, Sr25519Keyring, }; - use primitives::{Blake2Hasher, map}; + use primitives::{Blake2Hasher, map, offchain::NeverOffchainExt}; use hex::*; native_executor_instance!( @@ -85,10 +90,10 @@ mod tests { let hash = header.hash(); let mut overlay = OverlayedChanges::default(); - state_machine::new( + StateMachine::new( backend, Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - state_machine::NeverOffchainExt::new(), + NeverOffchainExt::new(), &mut overlay, &executor(), "Core_initialize_block", @@ -99,10 +104,10 @@ mod tests { ).unwrap(); for tx in transactions.iter() { - state_machine::new( + StateMachine::new( backend, Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - state_machine::NeverOffchainExt::new(), + NeverOffchainExt::new(), &mut overlay, &executor(), "BlockBuilder_apply_extrinsic", @@ -113,10 +118,10 @@ mod tests { ).unwrap(); } - let (ret_data, _, _) = state_machine::new( + let (ret_data, _, _) = StateMachine::new( backend, Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - state_machine::NeverOffchainExt::new(), + NeverOffchainExt::new(), &mut overlay, &executor(), "BlockBuilder_finalize_block", @@ -161,10 +166,10 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = state_machine::new( + let _ = StateMachine::new( &backend, Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - state_machine::NeverOffchainExt::new(), + NeverOffchainExt::new(), &mut overlay, &executor(), "Core_execute_block", @@ -191,10 +196,10 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = state_machine::new( + let _ = StateMachine::new( &backend, Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - state_machine::NeverOffchainExt::new(), + NeverOffchainExt::new(), &mut overlay, &executor(), "Core_execute_block", @@ -221,10 +226,10 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let r = state_machine::new( + let r = StateMachine::new( &backend, Some(&InMemoryChangesTrieStorage::<_, u64>::new()), - state_machine::NeverOffchainExt::new(), + NeverOffchainExt::new(), &mut overlay, &executor(), "Core_execute_block", diff --git a/substrate/core/client/src/lib.rs b/substrate/core/client/src/lib.rs index 1313b8b80e..3919b3970f 100644 --- a/substrate/core/client/src/lib.rs +++ b/substrate/core/client/src/lib.rs @@ -121,7 +121,7 @@ pub use crate::client::{ #[cfg(feature = "std")] pub use crate::notifications::{StorageEventStream, StorageChangeSet}; #[cfg(feature = "std")] -pub use state_machine::{ExecutionStrategy, NeverOffchainExt}; +pub use state_machine::ExecutionStrategy; #[cfg(feature = "std")] pub use crate::leaves::LeafSet; diff --git a/substrate/core/client/src/light/call_executor.rs b/substrate/core/client/src/light/call_executor.rs index fd6ae68e8e..370b6054e6 100644 --- a/substrate/core/client/src/light/call_executor.rs +++ b/substrate/core/client/src/light/call_executor.rs @@ -23,13 +23,15 @@ use std::{ }; use codec::{Encode, Decode}; -use primitives::{offchain, H256, Blake2Hasher, convert_hash, NativeOrEncoded}; +use primitives::{ + offchain::{self, NeverOffchainExt}, H256, Blake2Hasher, convert_hash, NativeOrEncoded, + traits::CodeExecutor, +}; use sr_primitives::generic::BlockId; use sr_primitives::traits::{One, Block as BlockT, Header as HeaderT, NumberFor}; use state_machine::{ - self, Backend as StateBackend, CodeExecutor, OverlayedChanges, - ExecutionStrategy, ChangesTrieTransaction, create_proof_check_backend, - execution_proof_check_on_trie_backend, ExecutionManager, NeverOffchainExt + self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend, + execution_proof_check_on_trie_backend, ExecutionManager, ChangesTrieTransaction, }; use hash_db::Hasher; @@ -451,7 +453,7 @@ pub fn prove_execution( pub fn check_execution_proof( executor: &E, request: &RemoteCallRequest
, - remote_proof: Vec> + remote_proof: Vec>, ) -> ClientResult> where Header: HeaderT, @@ -482,16 +484,14 @@ pub fn check_execution_proof( )?; // execute method - let local_result = execution_proof_check_on_trie_backend::( + execution_proof_check_on_trie_backend::( &trie_backend, &mut changes, executor, &request.method, &request.call_data, None, - )?; - - Ok(local_result) + ).map_err(Into::into) } #[cfg(test)] @@ -568,8 +568,14 @@ mod tests { backend.blockchain().insert(hash0, header0, None, None, NewBlockState::Final).unwrap(); backend.blockchain().insert(hash1, header1, None, None, NewBlockState::Final).unwrap(); - let local_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![1]))); - let remote_executor = RemoteCallExecutor::new(Arc::new(backend.blockchain().clone()), Arc::new(OkCallFetcher::new(vec![2]))); + let local_executor = RemoteCallExecutor::new( + Arc::new(backend.blockchain().clone()), + Arc::new(OkCallFetcher::new(vec![1])), + ); + let remote_executor = RemoteCallExecutor::new( + Arc::new(backend.blockchain().clone()), + Arc::new(OkCallFetcher::new(vec![2])), + ); let remote_or_local = RemoteOrLocalCallExecutor::new(backend, remote_executor, local_executor); assert_eq!( remote_or_local.call( diff --git a/substrate/core/client/src/light/fetcher.rs b/substrate/core/client/src/light/fetcher.rs index 14a3c72b05..6ac637f3fa 100644 --- a/substrate/core/client/src/light/fetcher.rs +++ b/substrate/core/client/src/light/fetcher.rs @@ -23,16 +23,15 @@ use std::future::Future; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use codec::{Decode, Encode}; -use primitives::{ChangesTrieConfiguration, convert_hash}; +use primitives::{ChangesTrieConfiguration, convert_hash, traits::CodeExecutor}; use sr_primitives::traits::{ Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor, SimpleArithmetic, CheckedConversion, Zero, }; use state_machine::{ - CodeExecutor, ChangesTrieRootsStorage, - ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, - TrieBackend, read_proof_check, key_changes_proof_check, - create_proof_check_backend_storage, read_child_proof_check, + ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, + TrieBackend, read_proof_check, key_changes_proof_check, create_proof_check_backend_storage, + read_child_proof_check, }; use crate::cht; diff --git a/substrate/core/client/src/light/mod.rs b/substrate/core/client/src/light/mod.rs index c53a2eef2b..08e14ad8f3 100644 --- a/substrate/core/client/src/light/mod.rs +++ b/substrate/core/client/src/light/mod.rs @@ -24,10 +24,9 @@ pub mod fetcher; use std::sync::Arc; use executor::RuntimeInfo; -use primitives::{H256, Blake2Hasher}; +use primitives::{H256, Blake2Hasher, traits::CodeExecutor}; use sr_primitives::BuildStorage; use sr_primitives::traits::Block as BlockT; -use state_machine::CodeExecutor; use crate::call_executor::LocalCallExecutor; use crate::client::Client; diff --git a/substrate/core/executor/Cargo.toml b/substrate/core/executor/Cargo.toml index a62a969d21..3d8f047322 100644 --- a/substrate/core/executor/Cargo.toml +++ b/substrate/core/executor/Cargo.toml @@ -11,7 +11,6 @@ runtime_io = { package = "sr-io", path = "../sr-io" } primitives = { package = "substrate-primitives", path = "../primitives" } trie = { package = "substrate-trie", path = "../trie" } serializer = { package = "substrate-serializer", path = "../serializer" } -state_machine = { package = "substrate-state-machine", path = "../state-machine" } runtime_version = { package = "sr-version", path = "../sr-version" } panic-handler = { package = "substrate-panic-handler", path = "../panic-handler" } wasm-interface = { package = "substrate-wasm-interface", path = "../wasm-interface" } @@ -30,6 +29,7 @@ hex-literal = "0.2.0" runtime-test = { package = "substrate-runtime-test", path = "runtime-test" } substrate-client = { path = "../client" } substrate-offchain = { path = "../offchain/" } +state_machine = { package = "substrate-state-machine", path = "../state-machine" } [features] default = [] diff --git a/substrate/core/executor/src/error.rs b/substrate/core/executor/src/error.rs index 967d074ec9..d6bf6b8b84 100644 --- a/substrate/core/executor/src/error.rs +++ b/substrate/core/executor/src/error.rs @@ -16,7 +16,6 @@ //! Rust executor possible errors. -use state_machine; use serializer; use wasmi; @@ -92,8 +91,6 @@ impl std::error::Error for Error { } } -impl state_machine::Error for Error {} - impl wasmi::HostError for Error {} impl From for Error { diff --git a/substrate/core/executor/src/lib.rs b/substrate/core/executor/src/lib.rs index d4bed6964e..b5c5027951 100644 --- a/substrate/core/executor/src/lib.rs +++ b/substrate/core/executor/src/lib.rs @@ -43,11 +43,10 @@ pub use wasmi; pub use wasm_executor::WasmExecutor; pub use native_executor::{with_native_environment, NativeExecutor, NativeExecutionDispatch}; pub use wasm_runtimes_cache::RuntimesCache; -pub use state_machine::Externalities; pub use runtime_version::{RuntimeVersion, NativeVersion}; pub use codec::Codec; #[doc(hidden)] -pub use primitives::Blake2Hasher; +pub use primitives::{Blake2Hasher, traits::Externalities}; #[doc(hidden)] pub use wasm_interface; diff --git a/substrate/core/executor/src/native_executor.rs b/substrate/core/executor/src/native_executor.rs index 616b9f8c6d..3de795fc27 100644 --- a/substrate/core/executor/src/native_executor.rs +++ b/substrate/core/executor/src/native_executor.rs @@ -16,12 +16,11 @@ use std::{result, cell::RefCell, panic::UnwindSafe}; use crate::error::{Error, Result}; -use state_machine::{CodeExecutor, Externalities}; use crate::wasm_executor::WasmExecutor; use runtime_version::{NativeVersion, RuntimeVersion}; use codec::{Decode, Encode}; use crate::RuntimeInfo; -use primitives::{Blake2Hasher, NativeOrEncoded}; +use primitives::{Blake2Hasher, NativeOrEncoded, traits::{CodeExecutor, Externalities}}; use log::{trace, warn}; use crate::RuntimesCache; @@ -35,7 +34,7 @@ fn safe_call(f: F) -> Result { // Substrate uses custom panic hook that terminates process on panic. Disable termination for the native call. let _guard = panic_handler::AbortGuard::force_unwind(); - ::std::panic::catch_unwind(f).map_err(|_| Error::Runtime) + std::panic::catch_unwind(f).map_err(|_| Error::Runtime) } /// Set up the externalities and safe calling environment to execute calls to a native runtime. @@ -44,7 +43,7 @@ fn safe_call(f: F) -> Result pub fn with_native_environment(ext: &mut dyn Externalities, f: F) -> Result where F: UnwindSafe + FnOnce() -> U { - ::runtime_io::with_externalities(ext, move || safe_call(f)) + runtime_io::with_externalities(ext, move || safe_call(f)) } /// Delegate for dispatching a CodeExecutor call. diff --git a/substrate/core/executor/src/wasm_executor.rs b/substrate/core/executor/src/wasm_executor.rs index 25f1f969b8..4baa547ab8 100644 --- a/substrate/core/executor/src/wasm_executor.rs +++ b/substrate/core/executor/src/wasm_executor.rs @@ -27,12 +27,12 @@ use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, memory_units::Pages, RuntimeValue::{I32, I64, self}, }; -use state_machine::Externalities; use crate::error::{Error, Result}; use codec::{Encode, Decode}; use primitives::{ blake2_128, blake2_256, twox_64, twox_128, twox_256, ed25519, sr25519, Pair, crypto::KeyTypeId, - offchain, hexdisplay::HexDisplay, sandbox as sandbox_primitives, Blake2Hasher, + offchain, hexdisplay::HexDisplay, sandbox as sandbox_primitives, H256, Blake2Hasher, + traits::Externalities, child_storage_key::ChildStorageKey, }; use trie::{TrieConfiguration, trie_types::Layout}; use crate::sandbox; diff --git a/substrate/core/executor/src/wasm_runtimes_cache.rs b/substrate/core/executor/src/wasm_runtimes_cache.rs index fd0ab91503..fb207dc18b 100644 --- a/substrate/core/executor/src/wasm_runtimes_cache.rs +++ b/substrate/core/executor/src/wasm_runtimes_cache.rs @@ -21,13 +21,9 @@ use crate::wasm_executor::WasmExecutor; use log::{trace, warn}; use codec::Decode; use parity_wasm::elements::{deserialize_buffer, DataSegment, Instruction, Module as RawModule}; -use primitives::storage::well_known_keys; -use primitives::Blake2Hasher; +use primitives::{storage::well_known_keys, Blake2Hasher, traits::Externalities}; use runtime_version::RuntimeVersion; -use state_machine::Externalities; -use std::collections::hash_map::{Entry, HashMap}; -use std::mem; -use std::rc::Rc; +use std::{collections::hash_map::{Entry, HashMap}, mem, rc::Rc}; use wasmi::{Module as WasmModule, ModuleRef as WasmModuleInstanceRef, RuntimeValue}; #[derive(Debug)] diff --git a/substrate/core/finality-grandpa/src/finality_proof.rs b/substrate/core/finality-grandpa/src/finality_proof.rs index 4b84ede933..bae6c8ebc0 100644 --- a/substrate/core/finality-grandpa/src/finality_proof.rs +++ b/substrate/core/finality-grandpa/src/finality_proof.rs @@ -40,16 +40,15 @@ use log::{trace, warn}; use client::{ backend::Backend, blockchain::Backend as BlockchainBackend, CallExecutor, Client, error::{Error as ClientError, Result as ClientResult}, - light::fetcher::{FetchChecker, RemoteCallRequest}, - ExecutionStrategy, NeverOffchainExt, + light::fetcher::{FetchChecker, RemoteCallRequest}, ExecutionStrategy, }; use codec::{Encode, Decode}; use grandpa::BlockNumberOps; -use sr_primitives::{Justification, generic::BlockId}; -use sr_primitives::traits::{ - NumberFor, Block as BlockT, Header as HeaderT, One, +use sr_primitives::{ + Justification, generic::BlockId, + traits::{NumberFor, Block as BlockT, Header as HeaderT, One}, }; -use primitives::{H256, Blake2Hasher}; +use primitives::{H256, Blake2Hasher, offchain::NeverOffchainExt}; use substrate_telemetry::{telemetry, CONSENSUS_INFO}; use fg_primitives::AuthorityId; diff --git a/substrate/core/primitives/src/child_storage_key.rs b/substrate/core/primitives/src/child_storage_key.rs new file mode 100644 index 0000000000..eba34c1ef9 --- /dev/null +++ b/substrate/core/primitives/src/child_storage_key.rs @@ -0,0 +1,68 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Provides a wrapper around a child storage key. + +use crate::storage::well_known_keys::is_child_trie_key_valid; +use rstd::{borrow::Cow, vec::Vec}; + +/// A wrapper around a child storage key. +/// +/// This wrapper ensures that the child storage key is correct and properly used. It is +/// impossible to create an instance of this struct without providing a correct `storage_key`. +pub struct ChildStorageKey<'a> { + storage_key: Cow<'a, [u8]>, +} + +impl<'a> ChildStorageKey<'a> { + fn new(storage_key: Cow<'a, [u8]>) -> Option { + if is_child_trie_key_valid(&storage_key) { + Some(ChildStorageKey { storage_key }) + } else { + None + } + } + + /// Create a new `ChildStorageKey` from a vector. + /// + /// `storage_key` need to start with `:child_storage:default:` + /// See `is_child_trie_key_valid` for more details. + pub fn from_vec(key: Vec) -> Option { + Self::new(Cow::Owned(key)) + } + + /// Create a new `ChildStorageKey` from a slice. + /// + /// `storage_key` need to start with `:child_storage:default:` + /// See `is_child_trie_key_valid` for more details. + pub fn from_slice(key: &'a [u8]) -> Option { + Self::new(Cow::Borrowed(key)) + } + + /// Get access to the byte representation of the storage key. + /// + /// This key is guaranteed to be correct. + pub fn as_ref(&self) -> &[u8] { + &*self.storage_key + } + + /// Destruct this instance into an owned vector that represents the storage key. + /// + /// This key is guaranteed to be correct. + pub fn into_owned(self) -> Vec { + self.storage_key.into_owned() + } +} diff --git a/substrate/core/primitives/src/lib.rs b/substrate/core/primitives/src/lib.rs index 5c918e4964..144aa7b997 100644 --- a/substrate/core/primitives/src/lib.rs +++ b/substrate/core/primitives/src/lib.rs @@ -54,6 +54,7 @@ pub mod crypto; pub mod u32_trait; +pub mod child_storage_key; pub mod ed25519; pub mod sr25519; pub mod hash; diff --git a/substrate/core/primitives/src/offchain.rs b/substrate/core/primitives/src/offchain.rs index 6f024c5c02..c9e78d48e1 100644 --- a/substrate/core/primitives/src/offchain.rs +++ b/substrate/core/primitives/src/offchain.rs @@ -663,6 +663,112 @@ impl Externalities for LimitedExternalities { } } +/// An implementation of offchain extensions that should never be triggered. +pub enum NeverOffchainExt {} + +impl NeverOffchainExt { + /// Create new offchain extensions. + pub fn new<'a>() -> Option<&'a mut Self> { + None + } +} + +impl Externalities for NeverOffchainExt { + fn is_validator(&self) -> bool { + unreachable!() + } + + fn submit_transaction(&mut self, _extrinsic: Vec) -> Result<(), ()> { + unreachable!() + } + + fn network_state( + &self, + ) -> Result { + unreachable!() + } + + fn timestamp(&mut self) -> Timestamp { + unreachable!() + } + + fn sleep_until(&mut self, _deadline: Timestamp) { + unreachable!() + } + + fn random_seed(&mut self) -> [u8; 32] { + unreachable!() + } + + fn local_storage_set(&mut self, _kind: StorageKind, _key: &[u8], _value: &[u8]) { + unreachable!() + } + + fn local_storage_compare_and_set( + &mut self, + _kind: StorageKind, + _key: &[u8], + _old_value: Option<&[u8]>, + _new_value: &[u8], + ) -> bool { + unreachable!() + } + + fn local_storage_get(&mut self, _kind: StorageKind, _key: &[u8]) -> Option> { + unreachable!() + } + + fn http_request_start( + &mut self, + _method: &str, + _uri: &str, + _meta: &[u8] + ) -> Result { + unreachable!() + } + + fn http_request_add_header( + &mut self, + _request_id: HttpRequestId, + _name: &str, + _value: &str + ) -> Result<(), ()> { + unreachable!() + } + + fn http_request_write_body( + &mut self, + _request_id: HttpRequestId, + _chunk: &[u8], + _deadline: Option + ) -> Result<(), HttpError> { + unreachable!() + } + + fn http_response_wait( + &mut self, + _ids: &[HttpRequestId], + _deadline: Option + ) -> Vec { + unreachable!() + } + + fn http_response_headers( + &mut self, + _request_id: HttpRequestId + ) -> Vec<(Vec, Vec)> { + unreachable!() + } + + fn http_response_read_body( + &mut self, + _request_id: HttpRequestId, + _buffer: &mut [u8], + _deadline: Option + ) -> Result { + unreachable!() + } +} #[cfg(test)] mod tests { diff --git a/substrate/core/primitives/src/storage.rs b/substrate/core/primitives/src/storage.rs index 8fdb7bdcc4..14c49bfaa9 100644 --- a/substrate/core/primitives/src/storage.rs +++ b/substrate/core/primitives/src/storage.rs @@ -75,4 +75,22 @@ pub mod well_known_keys { // Other code might depend on this, so be careful changing this. key.starts_with(CHILD_STORAGE_KEY_PREFIX) } + + /// Determine whether a child trie key is valid. + /// + /// For now, the only valid child trie keys are those starting with `:child_storage:default:`. + /// + /// `child_trie_root` and `child_delta_trie_root` can panic if invalid value is provided to them. + pub fn is_child_trie_key_valid(storage_key: &[u8]) -> bool { + let has_right_prefix = storage_key.starts_with(b":child_storage:default:"); + if has_right_prefix { + // This is an attempt to catch a change of `is_child_storage_key`, which + // just checks if the key has prefix `:child_storage:` at the moment of writing. + debug_assert!( + is_child_storage_key(&storage_key), + "`is_child_trie_key_valid` is a subset of `is_child_storage_key`", + ); + } + has_right_prefix + } } diff --git a/substrate/core/primitives/src/traits.rs b/substrate/core/primitives/src/traits.rs index 8e2f0c0213..0274c44ace 100644 --- a/substrate/core/primitives/src/traits.rs +++ b/substrate/core/primitives/src/traits.rs @@ -17,7 +17,11 @@ //! Shareable Substrate traits. #[cfg(feature = "std")] -use crate::{crypto::KeyTypeId, ed25519, sr25519}; +use crate::{crypto::KeyTypeId, ed25519, sr25519, child_storage_key::ChildStorageKey}; +#[cfg(feature = "std")] +use std::{fmt::{Debug, Display}, panic::UnwindSafe}; +#[cfg(feature = "std")] +use hash_db::Hasher; /// Something that generates, stores and provides access to keys. #[cfg(feature = "std")] @@ -68,3 +72,134 @@ pub trait BareCryptoStore: Send + Sync { /// A pointer to the key store. #[cfg(feature = "std")] pub type BareCryptoStorePtr = std::sync::Arc>; + +/// Externalities: pinned to specific active address. +#[cfg(feature = "std")] +pub trait Externalities { + /// Read runtime storage. + fn storage(&self, key: &[u8]) -> Option>; + + /// Get storage value hash. This may be optimized for large values. + fn storage_hash(&self, key: &[u8]) -> Option { + self.storage(key).map(|v| H::hash(&v)) + } + + /// Get child storage value hash. This may be optimized for large values. + fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { + self.child_storage(storage_key, key).map(|v| H::hash(&v)) + } + + /// Read original runtime storage, ignoring any overlayed changes. + fn original_storage(&self, key: &[u8]) -> Option>; + + /// Read original runtime child storage, ignoring any overlayed changes. + 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 { + self.original_storage(key).map(|v| H::hash(&v)) + } + + /// 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 { + self.original_child_storage(storage_key, key).map(|v| H::hash(&v)) + } + + /// Read child runtime storage. + fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; + + /// Set storage entry `key` of current contract being called (effective immediately). + fn set_storage(&mut self, key: Vec, value: Vec) { + self.place_storage(key, Some(value)); + } + + /// Set child storage entry `key` of current contract being called (effective immediately). + fn set_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Vec) { + self.place_child_storage(storage_key, key, Some(value)) + } + + /// Clear a storage entry (`key`) of current contract being called (effective immediately). + fn clear_storage(&mut self, key: &[u8]) { + self.place_storage(key.to_vec(), None); + } + + /// Clear a child storage entry (`key`) of current contract being called (effective immediately). + fn clear_child_storage(&mut self, storage_key: ChildStorageKey, key: &[u8]) { + self.place_child_storage(storage_key, key.to_vec(), None) + } + + /// Whether a storage entry exists. + fn exists_storage(&self, key: &[u8]) -> bool { + self.storage(key).is_some() + } + + /// Whether a child storage entry exists. + fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { + self.child_storage(storage_key, key).is_some() + } + + /// Clear an entire child storage. + fn kill_child_storage(&mut self, storage_key: ChildStorageKey); + + /// Clear storage entries which keys are start with the given prefix. + fn clear_prefix(&mut self, prefix: &[u8]); + + /// Clear child storage entries which keys are start with the given prefix. + fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]); + + /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). + 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>); + + /// 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) -> H::Out where H::Out: Ord; + + /// 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. + /// If the storage root equals the default hash as defined by the trie, the key in the top-level + /// storage map will be removed. + 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: H::Out) -> Result, ()> where H::Out: Ord; + + /// Returns offchain externalities extension if present. + fn offchain(&mut self) -> Option<&mut dyn crate::offchain::Externalities>; + + /// Returns the keystore. + fn keystore(&self) -> Option; +} + +/// Code execution engine. +#[cfg(feature = "std")] +pub trait CodeExecutor: Sized + Send + Sync { + /// Externalities error type. + type Error: Display + Debug + Send + 'static; + + /// Call a given method in the runtime. Returns a tuple of the result (either the output data + /// or an execution error) together with a `bool`, which is true if native execution was used. + fn call< + E: Externalities, + R: codec::Codec + PartialEq, + NC: FnOnce() -> Result + UnwindSafe, + >( + &self, + ext: &mut E, + method: &str, + data: &[u8], + use_native: bool, + native_call: Option, + ) -> (Result, Self::Error>, bool); +} diff --git a/substrate/core/rpc/src/state/state_full.rs b/substrate/core/rpc/src/state/state_full.rs index 3115a525a8..8b3dcd3d69 100644 --- a/substrate/core/rpc/src/state/state_full.rs +++ b/substrate/core/rpc/src/state/state_full.rs @@ -27,11 +27,11 @@ use client::{ backend::Backend, error::Result as ClientResult, }; use primitives::{ - H256, Blake2Hasher, Bytes, + H256, Blake2Hasher, Bytes, offchain::NeverOffchainExt, storage::{StorageKey, StorageData, StorageChangeSet}, }; use runtime_version::RuntimeVersion; -use state_machine::{NeverOffchainExt, ExecutionStrategy}; +use state_machine::ExecutionStrategy; use sr_primitives::{ generic::BlockId, traits::{Block as BlockT, Header, NumberFor, ProvideRuntimeApi, SaturatedConversion}, diff --git a/substrate/core/sr-io/with_std.rs b/substrate/core/sr-io/with_std.rs index cee17a5bdd..ca2a2554c3 100644 --- a/substrate/core/sr-io/with_std.rs +++ b/substrate/core/sr-io/with_std.rs @@ -16,12 +16,11 @@ use primitives::{ blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair, + traits::Externalities, child_storage_key::ChildStorageKey, }; // Switch to this after PoC-3 // pub use primitives::BlakeHasher; -pub use substrate_state_machine::{ - Externalities, BasicExternalities, TestExternalities, ChildStorageKey, -}; +pub use substrate_state_machine::{BasicExternalities, TestExternalities}; use environmental::environmental; use primitives::{offchain, hexdisplay::HexDisplay, H256}; @@ -40,7 +39,7 @@ impl HasherBounds for T {} /// /// Panicking here is aligned with what the `without_std` environment would do /// in the case of an invalid child storage key. -fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { +fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { match ChildStorageKey::from_slice(storage_key) { Some(storage_key) => storage_key, None => panic!("child storage key is invalid"), diff --git a/substrate/core/sr-io/without_std.rs b/substrate/core/sr-io/without_std.rs index d6ad3e1434..f7b0ce9b02 100644 --- a/substrate/core/sr-io/without_std.rs +++ b/substrate/core/sr-io/without_std.rs @@ -1239,4 +1239,3 @@ impl Printable for u64 { unsafe { ext_print_num.get()(*self); } } } - diff --git a/substrate/core/sr-std/without_std.rs b/substrate/core/sr-std/without_std.rs index 845ea79aa4..ed9eea6c31 100755 --- a/substrate/core/sr-std/without_std.rs +++ b/substrate/core/sr-std/without_std.rs @@ -49,7 +49,6 @@ mod __impl { pub use alloc::boxed; pub use alloc::rc; pub use alloc::vec; -pub use core::borrow; pub use core::cell; pub use core::clone; pub use core::cmp; @@ -76,3 +75,8 @@ pub mod collections { pub use alloc::collections::btree_set; pub use alloc::collections::vec_deque; } + +pub mod borrow { + pub use core::borrow::*; + pub use alloc::borrow::*; +} diff --git a/substrate/core/state-machine/src/backend.rs b/substrate/core/state-machine/src/backend.rs index 28ab61a5ed..86d415de1c 100644 --- a/substrate/core/state-machine/src/backend.rs +++ b/substrate/core/state-machine/src/backend.rs @@ -16,16 +16,15 @@ //! State machine backends. These manage the code and storage of contracts. -use std::{error, fmt}; -use std::cmp::Ord; -use std::collections::HashMap; -use std::marker::PhantomData; +use std::{error, fmt, cmp::Ord, collections::HashMap, marker::PhantomData}; use log::warn; use hash_db::Hasher; use crate::trie_backend::TrieBackend; use crate::trie_backend_essence::TrieBackendStorage; -use trie::{TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration}; -use trie::trie_types::{TrieDBMut, Layout}; +use trie::{ + TrieMut, MemoryDB, child_trie_root, default_child_trie_root, TrieConfiguration, + trie_types::{TrieDBMut, Layout}, +}; /// A state backend is used to read state data and can have changes committed /// to it. @@ -119,7 +118,9 @@ pub trait Backend { } /// Try convert into trie backend. - fn as_trie_backend(&mut self) -> Option<&TrieBackend>; + fn as_trie_backend(&mut self) -> Option<&TrieBackend> { + None + } /// Calculate the storage root, with given delta over what is already stored /// in the backend, and produce a "transaction" that can be used to commit. @@ -154,7 +155,56 @@ pub trait Backend { txs.consolidate(parent_txs); (root, txs) } +} +impl<'a, T: Backend, H: Hasher> Backend for &'a T { + type Error = T::Error; + type Transaction = T::Transaction; + type TrieBackendStorage = T::TrieBackendStorage; + + fn storage(&self, key: &[u8]) -> Result>, Self::Error> { + (*self).storage(key) + } + + fn child_storage(&self, storage_key: &[u8], key: &[u8]) -> Result>, Self::Error> { + (*self).child_storage(storage_key, key) + } + + fn for_keys_in_child_storage(&self, storage_key: &[u8], f: F) { + (*self).for_keys_in_child_storage(storage_key, f) + } + + fn for_keys_with_prefix(&self, prefix: &[u8], f: F) { + (*self).for_keys_with_prefix(prefix, f) + } + + fn for_child_keys_with_prefix(&self, storage_key: &[u8], prefix: &[u8], f: F) { + (*self).for_child_keys_with_prefix(storage_key, prefix, f) + } + + fn storage_root(&self, delta: I) -> (H::Out, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord, + { + (*self).storage_root(delta) + } + + fn child_storage_root(&self, storage_key: &[u8], delta: I) -> (Vec, bool, Self::Transaction) + where + I: IntoIterator, Option>)>, + H::Out: Ord, + { + (*self).child_storage_root(storage_key, delta) + } + + fn pairs(&self) -> Vec<(Vec, Vec)> { + (*self).pairs() + } + + fn for_key_values_with_prefix(&self, prefix: &[u8], f: F) { + (*self).for_key_values_with_prefix(prefix, f); + } } /// Trait that allows consolidate two transactions together. @@ -298,8 +348,6 @@ impl From>, Vec, Option>)>> for InMem } } -impl super::Error for Void {} - impl InMemory { /// child storage key iterator pub fn child_storage_keys(&self) -> impl Iterator { diff --git a/substrate/core/state-machine/src/basic.rs b/substrate/core/state-machine/src/basic.rs index 1d36a0ddad..e45af45c9f 100644 --- a/substrate/core/state-machine/src/basic.rs +++ b/substrate/core/state-machine/src/basic.rs @@ -22,9 +22,10 @@ use crate::backend::{Backend, InMemory}; use hash_db::Hasher; use trie::{TrieConfiguration, default_child_trie_root}; use trie::trie_types::Layout; -use primitives::offchain; -use primitives::storage::well_known_keys::is_child_storage_key; -use super::{ChildStorageKey, Externalities}; +use primitives::{ + storage::well_known_keys::is_child_storage_key, child_storage_key::ChildStorageKey, offchain, + traits::Externalities, +}; use log::warn; /// Simple HashMap-based Externalities impl. @@ -35,7 +36,6 @@ pub struct BasicExternalities { } impl BasicExternalities { - /// Create a new instance of `BasicExternalities` pub fn new( top: HashMap, Vec>, @@ -97,11 +97,11 @@ impl Externalities for BasicExternalities where H::Out: Ord { Externalities::::storage(self, key) } - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { self.children.get(storage_key.as_ref()).and_then(|child| child.get(key)).cloned() } - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { Externalities::::child_storage(self, storage_key, key) } @@ -119,9 +119,9 @@ impl Externalities for BasicExternalities where H::Out: Ord { fn place_child_storage( &mut self, - storage_key: ChildStorageKey, + storage_key: ChildStorageKey, key: Vec, - value: Option> + value: Option>, ) { let child_map = self.children.entry(storage_key.into_owned()).or_default(); if let Some(value) = value { @@ -131,7 +131,7 @@ impl Externalities for BasicExternalities where H::Out: Ord { } } - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { + fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { self.children.remove(storage_key.as_ref()); } @@ -147,7 +147,7 @@ impl Externalities for BasicExternalities where H::Out: Ord { self.top.retain(|key, _| !key.starts_with(prefix)); } - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { + fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { if let Some(child) = self.children.get_mut(storage_key.as_ref()) { child.retain(|key, _| !key.starts_with(prefix)); } @@ -163,9 +163,10 @@ impl Externalities for BasicExternalities where H::Out: Ord { // type of child trie support. let empty_hash = default_child_trie_root::>(&[]); for storage_key in keys { - let child_root = self.child_storage_root( - ChildStorageKey::::from_slice(storage_key.as_slice()) - .expect("Map only feed by valid keys; qed") + let child_root = Externalities::::child_storage_root( + self, + ChildStorageKey::from_slice(storage_key.as_slice()) + .expect("Map only feed by valid keys; qed"), ); if &empty_hash[..] == &child_root[..] { top.remove(&storage_key); @@ -173,10 +174,11 @@ impl Externalities for BasicExternalities where H::Out: Ord { top.insert(storage_key, child_root); } } + Layout::::trie_root(self.top.clone()) } - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { + fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { if let Some(child) = self.children.get(storage_key.as_ref()) { let delta = child.clone().into_iter().map(|(k, v)| (k, Some(v))); diff --git a/substrate/core/state-machine/src/error.rs b/substrate/core/state-machine/src/error.rs new file mode 100644 index 0000000000..6e6ce99585 --- /dev/null +++ b/substrate/core/state-machine/src/error.rs @@ -0,0 +1,47 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +/// State Machine Errors + +use std::fmt; + +/// State Machine Error bound. +/// +/// This should reflect Wasm error type bound for future compatibility. +pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} + +impl Error for T {} + +/// Externalities Error. +/// +/// Externalities are not really allowed to have errors, since it's assumed that dependent code +/// would not be executed unless externalities were available. This is included for completeness, +/// and as a transition away from the pre-existing framework. +#[derive(Debug, Eq, PartialEq)] +pub enum ExecutionError { + /// Backend error. + Backend(String), + /// The entry `:code` doesn't exist in storage so there's no way we can execute anything. + CodeEntryDoesNotExist, + /// Backend is incompatible with execution proof generation process. + UnableToGenerateProof, + /// Invalid execution proof. + InvalidProof, +} + +impl fmt::Display for ExecutionError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } +} diff --git a/substrate/core/state-machine/src/ext.rs b/substrate/core/state-machine/src/ext.rs index fde3ba2b01..129ed96ab9 100644 --- a/substrate/core/state-machine/src/ext.rs +++ b/substrate/core/state-machine/src/ext.rs @@ -18,14 +18,17 @@ use std::{error, fmt, cmp::Ord}; use log::warn; -use crate::backend::Backend; -use crate::changes_trie::{ - Storage as ChangesTrieStorage, CacheAction as ChangesTrieCacheAction, - build_changes_trie, +use crate::{ + backend::Backend, OverlayedChanges, + changes_trie::{ + Storage as ChangesTrieStorage, CacheAction as ChangesTrieCacheAction, build_changes_trie, + }, }; -use crate::{Externalities, OverlayedChanges, ChildStorageKey}; use hash_db::Hasher; -use primitives::{offchain, storage::well_known_keys::is_child_storage_key, traits::BareCryptoStorePtr}; +use primitives::{ + offchain, storage::well_known_keys::is_child_storage_key, + traits::{BareCryptoStorePtr, Externalities}, child_storage_key::ChildStorageKey, +}; use trie::{MemoryDB, default_child_trie_root}; use trie::trie_types::Layout; @@ -201,24 +204,24 @@ where self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL) } - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { let _guard = panic_handler::AbortGuard::force_abort(); self.overlay.child_storage(storage_key.as_ref(), key).map(|x| x.map(|x| x.to_vec())).unwrap_or_else(|| self.backend.child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL)) } - 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(); self.overlay.child_storage(storage_key.as_ref(), key).map(|x| x.map(|x| H::hash(x))).unwrap_or_else(|| self.backend.storage_hash(key).expect(EXT_NOT_ALLOWED_TO_FAIL)) } - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { let _guard = panic_handler::AbortGuard::force_abort(); self.backend.child_storage(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL) } - 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(); self.backend.child_storage_hash(storage_key.as_ref(), key).expect(EXT_NOT_ALLOWED_TO_FAIL) } @@ -231,7 +234,7 @@ where } } - fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { + fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { let _guard = panic_handler::AbortGuard::force_abort(); match self.overlay.child_storage(storage_key.as_ref(), key) { @@ -251,14 +254,14 @@ where self.overlay.set_storage(key, value); } - 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>) { let _guard = panic_handler::AbortGuard::force_abort(); self.mark_dirty(); self.overlay.set_child_storage(storage_key.into_owned(), key, value); } - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { + fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { let _guard = panic_handler::AbortGuard::force_abort(); self.mark_dirty(); @@ -282,7 +285,7 @@ where }); } - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { + fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { let _guard = panic_handler::AbortGuard::force_abort(); self.mark_dirty(); @@ -323,7 +326,7 @@ where root } - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { + fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { let _guard = panic_handler::AbortGuard::force_abort(); if self.storage_transaction.is_some() { self diff --git a/substrate/core/state-machine/src/lib.rs b/substrate/core/state-machine/src/lib.rs index 0ffac5e688..41d9b092bd 100644 --- a/substrate/core/state-machine/src/lib.rs +++ b/substrate/core/state-machine/src/lib.rs @@ -19,17 +19,17 @@ #![warn(missing_docs)] use std::{fmt, panic::UnwindSafe, result, marker::PhantomData}; -use std::borrow::Cow; use log::warn; use hash_db::Hasher; use codec::{Decode, Encode}; use primitives::{ - storage::well_known_keys, NativeOrEncoded, NeverNativeValue, offchain, - traits::BareCryptoStorePtr, + storage::well_known_keys, NativeOrEncoded, NeverNativeValue, offchain::{self, NeverOffchainExt}, + traits::{BareCryptoStorePtr, CodeExecutor}, }; pub mod backend; mod changes_trie; +mod error; mod ext; mod testing; mod basic; @@ -64,6 +64,11 @@ pub use proving_backend::{ }; pub use trie_backend_essence::{TrieBackendStorage, Storage}; pub use trie_backend::TrieBackend; +pub use error::{Error, ExecutionError}; + +type CallResult = Result, E>; + +type DefaultHandler = fn(CallResult, CallResult) -> CallResult; /// Type of changes trie transaction. pub type ChangesTrieTransaction = ( @@ -71,321 +76,6 @@ pub type ChangesTrieTransaction = ( ChangesTrieCacheAction<::Out, N>, ); -/// A wrapper around a child storage key. -/// -/// This wrapper ensures that the child storage key is correct and properly used. It is -/// impossible to create an instance of this struct without providing a correct `storage_key`. -pub struct ChildStorageKey<'a, H: Hasher> { - storage_key: Cow<'a, [u8]>, - _hasher: PhantomData, -} - -impl<'a, H: Hasher> ChildStorageKey<'a, H> { - fn new(storage_key: Cow<'a, [u8]>) -> Option { - if !trie::is_child_trie_key_valid::>(&storage_key) { - return None; - } - - Some(ChildStorageKey { - storage_key, - _hasher: PhantomData, - }) - } - - /// Create a new `ChildStorageKey` from a vector. - /// - /// `storage_key` has should start with `:child_storage:default:` - /// See `is_child_trie_key_valid` for more details. - pub fn from_vec(key: Vec) -> Option { - Self::new(Cow::Owned(key)) - } - - /// Create a new `ChildStorageKey` from a slice. - /// - /// `storage_key` has should start with `:child_storage:default:` - /// See `is_child_trie_key_valid` for more details. - pub fn from_slice(key: &'a [u8]) -> Option { - Self::new(Cow::Borrowed(key)) - } - - /// Get access to the byte representation of the storage key. - /// - /// This key is guaranteed to be correct. - pub fn as_ref(&self) -> &[u8] { - &*self.storage_key - } - - /// Destruct this instance into an owned vector that represents the storage key. - /// - /// This key is guaranteed to be correct. - pub fn into_owned(self) -> Vec { - self.storage_key.into_owned() - } -} - -/// State Machine Error bound. -/// -/// This should reflect WASM error type bound for future compatibility. -pub trait Error: 'static + fmt::Debug + fmt::Display + Send {} - -impl Error for ExecutionError {} - -/// Externalities Error. -/// -/// Externalities are not really allowed to have errors, since it's assumed that dependent code -/// would not be executed unless externalities were available. This is included for completeness, -/// and as a transition away from the pre-existing framework. -#[derive(Debug, Eq, PartialEq)] -pub enum ExecutionError { - /// Backend error. - Backend(String), - /// The entry `:code` doesn't exist in storage so there's no way we can execute anything. - CodeEntryDoesNotExist, - /// Backend is incompatible with execution proof generation process. - UnableToGenerateProof, - /// Invalid execution proof. - InvalidProof, -} - -impl fmt::Display for ExecutionError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Externalities Error") } -} - -type CallResult = Result, E>; - -/// Externalities: pinned to specific active address. -pub trait Externalities { - /// Read runtime storage. - fn storage(&self, key: &[u8]) -> Option>; - - /// Get storage value hash. This may be optimized for large values. - fn storage_hash(&self, key: &[u8]) -> Option { - self.storage(key).map(|v| H::hash(&v)) - } - - /// Get child storage value hash. This may be optimized for large values. - fn child_storage_hash(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option { - self.child_storage(storage_key, key).map(|v| H::hash(&v)) - } - - /// Read original runtime storage, ignoring any overlayed changes. - fn original_storage(&self, key: &[u8]) -> Option>; - - /// Read original runtime child storage, ignoring any overlayed changes. - 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 { - self.original_storage(key).map(|v| H::hash(&v)) - } - - /// 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 { - self.original_child_storage(storage_key, key).map(|v| H::hash(&v)) - } - - /// Read child runtime storage. - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option>; - - /// Set storage entry `key` of current contract being called (effective immediately). - fn set_storage(&mut self, key: Vec, value: Vec) { - self.place_storage(key, Some(value)); - } - - /// Set child storage entry `key` of current contract being called (effective immediately). - fn set_child_storage(&mut self, storage_key: ChildStorageKey, key: Vec, value: Vec) { - self.place_child_storage(storage_key, key, Some(value)) - } - - /// Clear a storage entry (`key`) of current contract being called (effective immediately). - fn clear_storage(&mut self, key: &[u8]) { - self.place_storage(key.to_vec(), None); - } - - /// Clear a child storage entry (`key`) of current contract being called (effective immediately). - fn clear_child_storage(&mut self, storage_key: ChildStorageKey, key: &[u8]) { - self.place_child_storage(storage_key, key.to_vec(), None) - } - - /// Whether a storage entry exists. - fn exists_storage(&self, key: &[u8]) -> bool { - self.storage(key).is_some() - } - - /// Whether a child storage entry exists. - fn exists_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> bool { - self.child_storage(storage_key, key).is_some() - } - - /// Clear an entire child storage. - fn kill_child_storage(&mut self, storage_key: ChildStorageKey); - - /// Clear storage entries which keys start with the given prefix. - fn clear_prefix(&mut self, prefix: &[u8]); - - /// Clear child storage entries which keys start with the given prefix. - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]); - - /// Set or clear a storage entry (`key`) of current contract being called (effective immediately). - 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>); - - /// 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) -> H::Out where H::Out: Ord; - - /// 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. - /// If the storage root equals the default hash as defined by the trie, the key in the top-level - /// storage map will be removed. - 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: H::Out) -> Result, ()> where H::Out: Ord; - - /// Returns offchain externalities extension if present. - fn offchain(&mut self) -> Option<&mut dyn offchain::Externalities>; - - /// Returns the keystore. - fn keystore(&self) -> Option; -} - -/// An implementation of offchain extensions that should never be triggered. -pub enum NeverOffchainExt {} - -impl NeverOffchainExt { - /// Create new offchain extensions. - pub fn new<'a>() -> Option<&'a mut Self> { - None - } -} - -impl offchain::Externalities for NeverOffchainExt { - fn is_validator(&self) -> bool { - unreachable!() - } - - fn submit_transaction(&mut self, _extrinsic: Vec) -> Result<(), ()> { - unreachable!() - } - - fn network_state( - &self, - ) -> Result { - unreachable!() - } - - fn timestamp(&mut self) -> offchain::Timestamp { - unreachable!() - } - - fn sleep_until(&mut self, _deadline: offchain::Timestamp) { - unreachable!() - } - - fn random_seed(&mut self) -> [u8; 32] { - unreachable!() - } - - fn local_storage_set(&mut self, _kind: offchain::StorageKind, _key: &[u8], _value: &[u8]) { - unreachable!() - } - - fn local_storage_compare_and_set( - &mut self, - _kind: offchain::StorageKind, - _key: &[u8], - _old_value: Option<&[u8]>, - _new_value: &[u8], - ) -> bool { - unreachable!() - } - - fn local_storage_get(&mut self, _kind: offchain::StorageKind, _key: &[u8]) -> Option> { - unreachable!() - } - - fn http_request_start( - &mut self, - _method: &str, - _uri: &str, - _meta: &[u8] - ) -> Result { - unreachable!() - } - - fn http_request_add_header( - &mut self, - _request_id: offchain::HttpRequestId, - _name: &str, - _value: &str - ) -> Result<(), ()> { - unreachable!() - } - - fn http_request_write_body( - &mut self, - _request_id: offchain::HttpRequestId, - _chunk: &[u8], - _deadline: Option - ) -> Result<(), offchain::HttpError> { - unreachable!() - } - - fn http_response_wait( - &mut self, - _ids: &[offchain::HttpRequestId], - _deadline: Option - ) -> Vec { - unreachable!() - } - - fn http_response_headers( - &mut self, - _request_id: offchain::HttpRequestId - ) -> Vec<(Vec, Vec)> { - unreachable!() - } - - fn http_response_read_body( - &mut self, - _request_id: offchain::HttpRequestId, - _buffer: &mut [u8], - _deadline: Option - ) -> Result { - unreachable!() - } -} - -/// Code execution engine. -pub trait CodeExecutor: Sized + Send + Sync { - /// Externalities error type. - type Error: Error; - - /// Call a given method in the runtime. Returns a tuple of the result (either the output data - /// or an execution error) together with a `bool`, which is true if native execution was used. - fn call< - E: Externalities, R: Encode + Decode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe - >( - &self, - ext: &mut E, - method: &str, - data: &[u8], - use_native: bool, - native_call: Option, - ) -> (CallResult, bool); -} - /// Strategy for executing a call into the runtime. #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum ExecutionStrategy { @@ -399,11 +89,6 @@ pub enum ExecutionStrategy { NativeElseWasm, } -type DefaultHandler = fn( - CallResult, - CallResult, -) -> CallResult; - /// Like `ExecutionStrategy` only it also stores a handler in case of consensus failure. #[derive(Clone)] pub enum ExecutionManager { @@ -430,7 +115,9 @@ impl<'a, F> From<&'a ExecutionManager> for ExecutionStrategy { impl ExecutionStrategy { /// Gets the corresponding manager for the execution strategy. - pub fn get_manager(self) -> ExecutionManager> { + pub fn get_manager( + self, + ) -> ExecutionManager> { match self { ExecutionStrategy::AlwaysWasm => ExecutionManager::AlwaysWasm, ExecutionStrategy::NativeWhenPossible => ExecutionManager::NativeWhenPossible, @@ -447,49 +134,14 @@ impl ExecutionStrategy { } } - -/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. -pub fn native_when_possible() -> ExecutionManager> { - ExecutionManager::NativeWhenPossible -} - /// Evaluate to ExecutionManager::NativeElseWasm, without having to figure out the type. pub fn native_else_wasm() -> ExecutionManager> { ExecutionManager::NativeElseWasm } -/// Evaluate to ExecutionManager::NativeWhenPossible, without having to figure out the type. -pub fn always_wasm() -> ExecutionManager> { - ExecutionManager::AlwaysWasm -} - -/// Creates new substrate state machine. -pub fn new<'a, H, N, B, T, O, Exec>( - backend: &'a B, - changes_trie_storage: Option<&'a T>, - offchain_ext: Option<&'a mut O>, - overlay: &'a mut OverlayedChanges, - exec: &'a Exec, - method: &'a str, - call_data: &'a [u8], - keystore: Option, -) -> StateMachine<'a, H, N, B, T, O, Exec> { - StateMachine { - backend, - changes_trie_storage, - offchain_ext, - overlay, - exec, - method, - call_data, - keystore, - _hasher: PhantomData, - } -} - /// The substrate state machine. -pub struct StateMachine<'a, H, N, B, T, O, Exec> { - backend: &'a B, +pub struct StateMachine<'a, B, H, N, T, O, Exec> { + backend: B, changes_trie_storage: Option<&'a T>, offchain_ext: Option<&'a mut O>, overlay: &'a mut OverlayedChanges, @@ -500,7 +152,7 @@ pub struct StateMachine<'a, H, N, B, T, O, Exec> { _hasher: PhantomData<(H, N)>, } -impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where +impl<'a, B, H, N, T, O, Exec> StateMachine<'a, B, H, N, T, O, Exec> where H: Hasher, Exec: CodeExecutor, B: Backend, @@ -509,6 +161,30 @@ impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where H::Out: Ord + 'static, N: crate::changes_trie::BlockNumber, { + /// Creates new substrate state machine. + pub fn new( + backend: B, + changes_trie_storage: Option<&'a T>, + offchain_ext: Option<&'a mut O>, + overlay: &'a mut OverlayedChanges, + exec: &'a Exec, + method: &'a str, + call_data: &'a [u8], + keystore: Option, + ) -> Self { + Self { + backend, + changes_trie_storage, + offchain_ext, + overlay, + exec, + method, + call_data, + keystore, + _hasher: PhantomData, + } + } + /// Execute a call using the given state backend, overlayed changes, and call executor. /// Produces a state-backend-specific "transaction" which can be used to apply the changes /// to the backing store, such as the disk. @@ -551,7 +227,7 @@ impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where { let mut externalities = ext::Ext::new( self.overlay, - self.backend, + &self.backend, self.changes_trie_storage, self.offchain_ext.as_mut().map(|x| &mut **x), self.keystore.clone(), @@ -586,11 +262,19 @@ impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where CallResult ) -> CallResult { - let (result, was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call.take()); + let (result, was_native, storage_delta, changes_delta) = self.execute_aux( + compute_tx, + true, + native_call.take(), + ); if was_native { self.overlay.prospective = orig_prospective.clone(); - let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux(compute_tx, false, native_call); + let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux( + compute_tx, + false, + native_call, + ); if (result.is_ok() && wasm_result.is_ok() && result.as_ref().ok() == wasm_result.as_ref().ok()) @@ -613,13 +297,21 @@ impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where R: Decode + Encode + PartialEq, NC: FnOnce() -> result::Result + UnwindSafe, { - let (result, was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call.take()); + let (result, was_native, storage_delta, changes_delta) = self.execute_aux( + compute_tx, + true, + native_call.take(), + ); if !was_native || result.is_ok() { (result, storage_delta, changes_delta) } else { self.overlay.prospective = orig_prospective.clone(); - let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux(compute_tx, false, native_call); + let (wasm_result, _, wasm_storage_delta, wasm_changes_delta) = self.execute_aux( + compute_tx, + false, + native_call, + ); (wasm_result, wasm_storage_delta, wasm_changes_delta) } } @@ -646,7 +338,7 @@ impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where NC: FnOnce() -> result::Result + UnwindSafe, Handler: FnOnce( CallResult, - CallResult + CallResult, ) -> CallResult { // read changes trie configuration. The reason why we're doing it here instead of the @@ -654,8 +346,7 @@ impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where // proof-of-execution on light clients. And the proof is recorded by the backend which // is created after OverlayedChanges - let backend = self.backend.clone(); - let init_overlay = |overlay: &mut OverlayedChanges, final_check: bool| { + let init_overlay = |overlay: &mut OverlayedChanges, final_check: bool, backend: &B| { let changes_trie_config = try_read_overlay_value( overlay, backend, @@ -663,32 +354,41 @@ impl<'a, H, N, B, T, O, Exec> StateMachine<'a, H, N, B, T, O, Exec> where )?; set_changes_trie_config(overlay, changes_trie_config, final_check) }; - init_overlay(self.overlay, false)?; + init_overlay(self.overlay, false, &self.backend)?; let result = { let orig_prospective = self.overlay.prospective.clone(); let (result, storage_delta, changes_delta) = match manager { ExecutionManager::Both(on_consensus_failure) => { - self.execute_call_with_both_strategy(compute_tx, native_call.take(), orig_prospective, on_consensus_failure) + self.execute_call_with_both_strategy( + compute_tx, + native_call.take(), + orig_prospective, + on_consensus_failure, + ) }, ExecutionManager::NativeElseWasm => { - self.execute_call_with_native_else_wasm_strategy(compute_tx, native_call.take(), orig_prospective) + self.execute_call_with_native_else_wasm_strategy( + compute_tx, + native_call.take(), + orig_prospective, + ) }, ExecutionManager::AlwaysWasm => { - let (result, _, storage_delta, changes_delta) = self.execute_aux(compute_tx, false, native_call); - (result, storage_delta, changes_delta) + let res = self.execute_aux(compute_tx, false, native_call); + (res.0, res.2, res.3) }, ExecutionManager::NativeWhenPossible => { - let (result, _was_native, storage_delta, changes_delta) = self.execute_aux(compute_tx, true, native_call); - (result, storage_delta, changes_delta) + let res = self.execute_aux(compute_tx, true, native_call); + (res.0, res.2, res.3) }, }; result.map(move |out| (out, storage_delta, changes_delta)) }; if result.is_ok() { - init_overlay(self.overlay, true)?; + init_overlay(self.overlay, true, &self.backend)?; } result.map_err(|e| Box::new(e) as _) @@ -739,23 +439,16 @@ where H::Out: Ord + 'static, { let proving_backend = proving_backend::ProvingBackend::new(trie_backend); - let mut sm = StateMachine { - backend: &proving_backend, - changes_trie_storage: None as Option<&changes_trie::InMemoryStorage>, - offchain_ext: NeverOffchainExt::new(), - overlay, - exec, - method, - call_data, - keystore, - _hasher: PhantomData, - }; + let mut sm = StateMachine::<_, H, _, InMemoryChangesTrieStorage, _, Exec>::new( + proving_backend, None, NeverOffchainExt::new(), overlay, exec, method, call_data, keystore, + ); + let (result, _, _) = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( native_else_wasm(), false, None, )?; - let proof = proving_backend.extract_proof(); + let proof = sm.backend.extract_proof(); Ok((result.into_encoded(), proof)) } @@ -792,17 +485,10 @@ where Exec: CodeExecutor, H::Out: Ord + 'static, { - let mut sm = StateMachine { - backend: trie_backend, - changes_trie_storage: None as Option<&changes_trie::InMemoryStorage>, - offchain_ext: NeverOffchainExt::new(), - overlay, - exec, - method, - call_data, - keystore, - _hasher: PhantomData, - }; + let mut sm = StateMachine::<_, H, _, InMemoryChangesTrieStorage, _, Exec>::new( + trie_backend, None, NeverOffchainExt::new(), overlay, exec, method, call_data, keystore, + ); + sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( native_else_wasm(), false, @@ -818,11 +504,11 @@ pub fn prove_read( where B: Backend, H: Hasher, - H::Out: Ord + H::Out: Ord, { let trie_backend = backend.as_trie_backend() .ok_or_else( - ||Box::new(ExecutionError::UnableToGenerateProof) as Box + || Box::new(ExecutionError::UnableToGenerateProof) as Box )?; prove_read_on_trie_backend(trie_backend, key) } @@ -836,14 +522,13 @@ pub fn prove_child_read( where B: Backend, H: Hasher, - H::Out: Ord + H::Out: Ord, { let trie_backend = backend.as_trie_backend() .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; prove_child_read_on_trie_backend(trie_backend, storage_key, key) } - /// Generate storage read proof on pre-created trie backend. pub fn prove_read_on_trie_backend( trie_backend: &TrieBackend, @@ -852,7 +537,7 @@ pub fn prove_read_on_trie_backend( where S: trie_backend_essence::TrieBackendStorage, H: Hasher, - H::Out: Ord + H::Out: Ord, { let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); let result = proving_backend.storage(key).map_err(|e| Box::new(e) as Box)?; @@ -868,10 +553,11 @@ pub fn prove_child_read_on_trie_backend( where S: trie_backend_essence::TrieBackendStorage, H: Hasher, - H::Out: Ord + H::Out: Ord, { let proving_backend = proving_backend::ProvingBackend::<_, H>::new(trie_backend); - let result = proving_backend.child_storage(storage_key, key).map_err(|e| Box::new(e) as Box)?; + let result = proving_backend.child_storage(storage_key, key) + .map_err(|e| Box::new(e) as Box)?; Ok((result, proving_backend.extract_proof())) } @@ -883,7 +569,7 @@ pub fn read_proof_check( ) -> Result>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, { let proving_backend = create_proof_check_backend::(root, proof)?; read_proof_check_on_proving_backend(&proving_backend, key) @@ -898,13 +584,12 @@ pub fn read_child_proof_check( ) -> Result>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, { let proving_backend = create_proof_check_backend::(root, proof)?; read_child_proof_check_on_proving_backend(&proving_backend, storage_key, key) } - /// Check storage read proof on pre-created proving backend. pub fn read_proof_check_on_proving_backend( proving_backend: &TrieBackend, H>, @@ -912,7 +597,7 @@ pub fn read_proof_check_on_proving_backend( ) -> Result>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, { proving_backend.storage(key).map_err(|e| Box::new(e) as Box) } @@ -925,14 +610,14 @@ pub fn read_child_proof_check_on_proving_backend( ) -> Result>, Box> where H: Hasher, - H::Out: Ord + H::Out: Ord, { proving_backend.child_storage(storage_key, key).map_err(|e| Box::new(e) as Box) } /// Sets overlayed changes' changes trie configuration. Returns error if configuration /// differs from previous OR config decode has failed. -pub(crate) fn set_changes_trie_config( +fn set_changes_trie_config( overlay: &mut OverlayedChanges, config: Option>, final_check: bool, @@ -956,12 +641,10 @@ pub(crate) fn set_changes_trie_config( } /// Reads storage value from overlay or from the backend. -fn try_read_overlay_value(overlay: &OverlayedChanges, backend: &B, key: &[u8]) - -> Result>, Box> -where - H: Hasher, - B: Backend, -{ +fn try_read_overlay_value( + overlay: &OverlayedChanges, + backend: &B, key: &[u8], +) -> Result>, Box> where H: Hasher, B: Backend { match overlay.storage(key).map(|x| x.map(|x| x.to_vec())) { Some(value) => Ok(value), None => backend @@ -982,7 +665,7 @@ mod tests { InMemoryStorage as InMemoryChangesTrieStorage, Configuration as ChangesTrieConfig, }; - use primitives::{Blake2Hasher, map}; + use primitives::{Blake2Hasher, map, traits::Externalities, child_storage_key::ChildStorageKey}; struct DummyCodeExecutor { change_changes_trie_config: bool, @@ -1034,15 +717,17 @@ mod tests { } } - impl Error for u8 {} - #[test] fn execute_works() { - assert_eq!(new( - &trie_backend::tests::test_trie(), - Some(&InMemoryChangesTrieStorage::::new()), + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + backend, + Some(&changes_trie_storage), NeverOffchainExt::new(), - &mut Default::default(), + &mut overlayed_changes, &DummyCodeExecutor { change_changes_trie_config: false, native_available: true, @@ -1052,19 +737,26 @@ mod tests { "test", &[], None, - ).execute( - ExecutionStrategy::NativeWhenPossible - ).unwrap().0, vec![66]); + ); + + assert_eq!( + state_machine.execute(ExecutionStrategy::NativeWhenPossible).unwrap().0, + vec![66], + ); } #[test] fn execute_works_with_native_else_wasm() { - assert_eq!(new( - &trie_backend::tests::test_trie(), - Some(&InMemoryChangesTrieStorage::::new()), + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + backend, + Some(&changes_trie_storage), NeverOffchainExt::new(), - &mut Default::default(), + &mut overlayed_changes, &DummyCodeExecutor { change_changes_trie_config: false, native_available: true, @@ -1074,19 +766,23 @@ mod tests { "test", &[], None, - ).execute( - ExecutionStrategy::NativeElseWasm - ).unwrap().0, vec![66]); + ); + + assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap().0, vec![66]); } #[test] fn dual_execution_strategy_detects_consensus_failure() { let mut consensus_failed = false; - assert!(new( - &trie_backend::tests::test_trie(), - Some(&InMemoryChangesTrieStorage::::new()), + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + backend, + Some(&changes_trie_storage), NeverOffchainExt::new(), - &mut Default::default(), + &mut overlayed_changes, &DummyCodeExecutor { change_changes_trie_config: false, native_available: true, @@ -1096,14 +792,18 @@ mod tests { "test", &[], None, - ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( - ExecutionManager::Both(|we, _ne| { - consensus_failed = true; - we - }), - true, - None, - ).is_err()); + ); + + assert!( + state_machine.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( + ExecutionManager::Both(|we, _ne| { + consensus_failed = true; + we + }), + true, + None, + ).is_err() + ); assert!(consensus_failed); } @@ -1276,47 +976,51 @@ mod tests { #[test] fn cannot_change_changes_trie_config() { - assert!( - new( - &trie_backend::tests::test_trie(), - Some(&InMemoryChangesTrieStorage::::new()), - NeverOffchainExt::new(), - &mut Default::default(), - &DummyCodeExecutor { - change_changes_trie_config: true, - native_available: false, - native_succeeds: true, - fallback_succeeds: true, - }, - "test", - &[], - None, - ) - .execute(ExecutionStrategy::NativeWhenPossible) - .is_err() + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + backend, + Some(&changes_trie_storage), + NeverOffchainExt::new(), + &mut overlayed_changes, + &DummyCodeExecutor { + change_changes_trie_config: true, + native_available: false, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + None, ); + + assert!(state_machine.execute(ExecutionStrategy::NativeWhenPossible).is_err()); } #[test] fn cannot_change_changes_trie_config_with_native_else_wasm() { - assert!( - new( - &trie_backend::tests::test_trie(), - Some(&InMemoryChangesTrieStorage::::new()), - NeverOffchainExt::new(), - &mut Default::default(), - &DummyCodeExecutor { - change_changes_trie_config: true, - native_available: false, - native_succeeds: true, - fallback_succeeds: true, - }, - "test", - &[], - None, - ) - .execute(ExecutionStrategy::NativeElseWasm) - .is_err() + let backend = trie_backend::tests::test_trie(); + let mut overlayed_changes = Default::default(); + let changes_trie_storage = InMemoryChangesTrieStorage::::new(); + + let mut state_machine = StateMachine::new( + backend, + Some(&changes_trie_storage), + NeverOffchainExt::new(), + &mut overlayed_changes, + &DummyCodeExecutor { + change_changes_trie_config: true, + native_available: false, + native_succeeds: true, + fallback_succeeds: true, + }, + "test", + &[], + None, ); + + assert!(state_machine.execute(ExecutionStrategy::NativeElseWasm).is_err()); } } diff --git a/substrate/core/state-machine/src/overlayed_changes.rs b/substrate/core/state-machine/src/overlayed_changes.rs index 1dbf2a4352..a4952ddf73 100644 --- a/substrate/core/state-machine/src/overlayed_changes.rs +++ b/substrate/core/state-machine/src/overlayed_changes.rs @@ -16,7 +16,8 @@ //! The overlayed changes to state. -#[cfg(test)] use std::iter::FromIterator; +#[cfg(test)] +use std::iter::FromIterator; use std::collections::{HashMap, BTreeSet}; use codec::Decode; use crate::changes_trie::{NO_EXTRINSIC_INDEX, Configuration as ChangesTrieConfig}; @@ -350,12 +351,12 @@ impl From>> for OverlayedValue { #[cfg(test)] mod tests { use hex_literal::hex; - use primitives::{Blake2Hasher, H256}; - use primitives::storage::well_known_keys::EXTRINSIC_INDEX; + use primitives::{ + Blake2Hasher, H256, traits::Externalities, storage::well_known_keys::EXTRINSIC_INDEX, + }; use crate::backend::InMemory; use crate::changes_trie::InMemoryStorage as InMemoryChangesTrieStorage; use crate::ext::Ext; - use crate::Externalities; use super::*; fn strip_extrinsic_index(map: &HashMap, OverlayedValue>) -> HashMap, OverlayedValue> { diff --git a/substrate/core/state-machine/src/proving_backend.rs b/substrate/core/state-machine/src/proving_backend.rs index 2b44aae778..64ec7de81b 100644 --- a/substrate/core/state-machine/src/proving_backend.rs +++ b/substrate/core/state-machine/src/proving_backend.rs @@ -128,9 +128,8 @@ impl<'a, S: 'a + TrieBackendStorage, H: 'a + Hasher> ProvingBackend<'a, S, H> } } - /// Consume the backend, extracting the gathered proof in lexicographical order - /// by value. - pub fn extract_proof(self) -> Vec> { + /// Consume the backend, extracting the gathered proof in lexicographical order by value. + pub fn extract_proof(&self) -> Vec> { self.proof_recorder .borrow_mut() .drain() @@ -207,10 +206,6 @@ impl<'a, S, H> Backend for ProvingBackend<'a, S, H> { self.backend.child_storage_root(storage_key, delta) } - - fn as_trie_backend(&mut self) -> Option<&TrieBackend> { - None - } } /// Create proof check backend. @@ -249,8 +244,7 @@ mod tests { use crate::backend::{InMemory}; use crate::trie_backend::tests::test_trie; use super::*; - use primitives::{Blake2Hasher}; - use crate::ChildStorageKey; + use primitives::{Blake2Hasher, child_storage_key::ChildStorageKey}; fn test_proving<'a>( trie_backend: &'a TrieBackend,Blake2Hasher>, @@ -315,12 +309,8 @@ mod tests { #[test] fn proof_recorded_and_checked_with_child() { - let subtrie1 = ChildStorageKey::::from_slice( - b":child_storage:default:sub1" - ).unwrap(); - let subtrie2 = ChildStorageKey::::from_slice( - b":child_storage:default:sub2" - ).unwrap(); + let subtrie1 = ChildStorageKey::from_slice(b":child_storage:default:sub1").unwrap(); + let subtrie2 = ChildStorageKey::from_slice(b":child_storage:default:sub2").unwrap(); let own1 = subtrie1.into_owned(); let own2 = subtrie2.into_owned(); let contents = (0..64).map(|i| (None, vec![i], Some(vec![i]))) diff --git a/substrate/core/state-machine/src/testing.rs b/substrate/core/state-machine/src/testing.rs index a40026b271..2ee2268c0e 100644 --- a/substrate/core/state-machine/src/testing.rs +++ b/substrate/core/state-machine/src/testing.rs @@ -18,17 +18,18 @@ use std::collections::{HashMap}; use hash_db::Hasher; -use crate::backend::{InMemory, Backend}; -use primitives::storage::well_known_keys::is_child_storage_key; -use crate::changes_trie::{ - build_changes_trie, InMemoryStorage as ChangesTrieInMemoryStorage, - BlockNumber as ChangesTrieBlockNumber, +use crate::{ + backend::{InMemory, Backend}, OverlayedChanges, + changes_trie::{ + build_changes_trie, InMemoryStorage as ChangesTrieInMemoryStorage, + BlockNumber as ChangesTrieBlockNumber, + }, }; use primitives::{ - storage::well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES}, traits::BareCryptoStorePtr, offchain + storage::well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES, is_child_storage_key}, + traits::{BareCryptoStorePtr, Externalities}, offchain, child_storage_key::ChildStorageKey, }; use codec::Encode; -use super::{ChildStorageKey, Externalities, OverlayedChanges}; const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; @@ -156,7 +157,7 @@ impl Externalities for TestExternalities self.backend.storage(key).expect(EXT_NOT_ALLOWED_TO_FAIL) } - fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { self.overlay .child_storage(storage_key.as_ref(), key) .map(|x| x.map(|x| x.to_vec())) @@ -166,7 +167,7 @@ impl Externalities for TestExternalities ) } - fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { + fn original_child_storage(&self, storage_key: ChildStorageKey, key: &[u8]) -> Option> { self.backend .child_storage(storage_key.as_ref(), key) .map(|x| x.map(|x| x.to_vec())) @@ -183,14 +184,14 @@ impl Externalities for TestExternalities fn place_child_storage( &mut self, - storage_key: ChildStorageKey, + storage_key: ChildStorageKey, key: Vec, value: Option> ) { self.overlay.set_child_storage(storage_key.into_owned(), key, value); } - fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { + fn kill_child_storage(&mut self, storage_key: ChildStorageKey) { let backend = &self.backend; let overlay = &mut self.overlay; @@ -214,7 +215,7 @@ impl Externalities for TestExternalities }); } - fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { + fn clear_child_prefix(&mut self, storage_key: ChildStorageKey, prefix: &[u8]) { self.overlay.clear_child_prefix(storage_key.as_ref(), prefix); @@ -249,7 +250,7 @@ impl Externalities for TestExternalities } - fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { + fn child_storage_root(&mut self, storage_key: ChildStorageKey) -> Vec { let storage_key = storage_key.as_ref(); let (root, is_empty, _) = { diff --git a/substrate/core/state-machine/src/trie_backend.rs b/substrate/core/state-machine/src/trie_backend.rs index 01e36a5810..105e20c9b7 100644 --- a/substrate/core/state-machine/src/trie_backend.rs +++ b/substrate/core/state-machine/src/trie_backend.rs @@ -57,8 +57,6 @@ impl, H: Hasher> TrieBackend { } } -impl super::Error for String {} - impl, H: Hasher> Backend for TrieBackend where H::Out: Ord, { diff --git a/substrate/core/trie/src/lib.rs b/substrate/core/trie/src/lib.rs index e526a27ebe..3cc85731d8 100644 --- a/substrate/core/trie/src/lib.rs +++ b/substrate/core/trie/src/lib.rs @@ -166,25 +166,6 @@ pub fn read_trie_value_with< Ok(TrieDB::::new(&*db, root)?.get_with(key, query).map(|x| x.map(|val| val.to_vec()))?) } -/// Determine whether a child trie key is valid. -/// -/// For now, the only valid child trie key is `:child_storage:default:`. -/// -/// `child_trie_root` and `child_delta_trie_root` can panic if invalid value is provided to them. -pub fn is_child_trie_key_valid(storage_key: &[u8]) -> bool { - use primitives::storage::well_known_keys; - let has_right_prefix = storage_key.starts_with(b":child_storage:default:"); - if has_right_prefix { - // This is an attempt to catch a change of `is_child_storage_key`, which - // just checks if the key has prefix `:child_storage:` at the moment of writing. - debug_assert!( - well_known_keys::is_child_storage_key(&storage_key), - "`is_child_trie_key_valid` is a subset of `is_child_storage_key`", - ); - } - has_right_prefix -} - /// 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() diff --git a/substrate/node/executor/src/lib.rs b/substrate/node/executor/src/lib.rs index fc0ca39049..1fef4bba7a 100644 --- a/substrate/node/executor/src/lib.rs +++ b/substrate/node/executor/src/lib.rs @@ -40,10 +40,13 @@ mod tests { use runtime_io; use substrate_executor::WasmExecutor; use codec::{Encode, Decode, Joiner}; - use runtime_support::{Hashable, StorageValue, StorageMap, assert_eq_error_rate, traits::Currency}; - use state_machine::{CodeExecutor, Externalities, TestExternalities as CoreTestExternalities}; - use primitives::{Blake2Hasher, NeverNativeValue, NativeOrEncoded, map}; - use node_primitives::{Hash, BlockNumber, Balance}; + use runtime_support::{ + Hashable, StorageValue, StorageMap, assert_eq_error_rate, traits::Currency, + }; + use state_machine::TestExternalities as CoreTestExternalities; + use primitives::{ + Blake2Hasher, NeverNativeValue, NativeOrEncoded, map, traits::{CodeExecutor, Externalities}, + }; use sr_primitives::{ traits::{Header as HeaderT, Hash as HashT, Convert}, ApplyOutcome, ApplyResult, transaction_validity::InvalidTransaction, weights::{WeightMultiplier, GetDispatchInfo}, @@ -53,9 +56,9 @@ mod tests { use node_runtime::{ Header, Block, UncheckedExtrinsic, CheckedExtrinsic, Call, Runtime, Balances, BuildStorage, System, Event, TransferFee, TransactionBaseFee, TransactionByteFee, + constants::currency::*, impls::WeightToFee, }; - use node_runtime::constants::currency::*; - use node_runtime::impls::WeightToFee; + use node_primitives::{Balance, Hash, BlockNumber}; use node_testing::keyring::*; use wabt;