diff --git a/Cargo.lock b/Cargo.lock index a29213b45b545..a412347bde5c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8011,12 +8011,16 @@ version = "4.0.0-dev" dependencies = [ "memmap2", "sc-chain-spec-derive", + "sc-client-api", + "sc-executor", "sc-network-common", "sc-telemetry", "serde", "serde_json", + "sp-blockchain", "sp-core", "sp-runtime", + "sp-state-machine", ] [[package]] @@ -10869,6 +10873,7 @@ dependencies = [ "futures", "parity-scale-codec", "sc-block-builder", + "sc-chain-spec", "sc-client-api", "sc-consensus", "sp-api", diff --git a/client/block-builder/Cargo.toml b/client/block-builder/Cargo.toml index 3b4bea9818c9e..d009826b2fae4 100644 --- a/client/block-builder/Cargo.toml +++ b/client/block-builder/Cargo.toml @@ -23,7 +23,7 @@ sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "7.0.0", path = "../../primitives/core" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sp-runtime = { version = "7.0.0", path = "../../primitives/runtime" } -sp-state-machine = { version = "0.13.0", path = "../../primitives/state-machine" } [dev-dependencies] +sp-state-machine = { version = "0.13.0", path = "../../primitives/state-machine" } substrate-test-runtime-client = { path = "../../test-utils/runtime/client" } diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index d7ef3b1da5123..d97afadd40156 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -39,9 +39,8 @@ use sp_runtime::{ Digest, }; -pub use sp_block_builder::BlockBuilder as BlockBuilderApi; - use sc_client_api::backend; +pub use sp_block_builder::BlockBuilder as BlockBuilderApi; /// Used as parameter to [`BlockBuilderProvider`] to express if proof recording should be enabled. /// diff --git a/client/chain-spec/Cargo.toml b/client/chain-spec/Cargo.toml index 0a4e54e8d6a67..6168a897c962c 100644 --- a/client/chain-spec/Cargo.toml +++ b/client/chain-spec/Cargo.toml @@ -16,8 +16,12 @@ targets = ["x86_64-unknown-linux-gnu"] memmap2 = "0.5.0" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.85" +sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-chain-spec-derive = { version = "4.0.0-dev", path = "./derive" } +sc-executor = { version = "0.10.0-dev", path = "../executor" } sc-network-common = { version = "0.10.0-dev", path = "../network/common" } sc-telemetry = { version = "4.0.0-dev", path = "../telemetry" } +sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "7.0.0", path = "../../primitives/core" } sp-runtime = { version = "7.0.0", path = "../../primitives/runtime" } +sp-state-machine = { version = "0.13.0", path = "../../primitives/state-machine" } diff --git a/client/service/src/client/genesis.rs b/client/chain-spec/src/genesis.rs similarity index 68% rename from client/service/src/client/genesis.rs rename to client/chain-spec/src/genesis.rs index b3ed46c1550c7..6aa156a620a79 100644 --- a/client/service/src/client/genesis.rs +++ b/client/chain-spec/src/genesis.rs @@ -18,20 +18,56 @@ //! Tool for creating the genesis block. +use std::{collections::hash_map::DefaultHasher, marker::PhantomData, sync::Arc}; + use sc_client_api::{backend::Backend, BlockImportOperation}; use sc_executor::RuntimeVersionOf; -use sp_core::storage::Storage; +use sp_core::storage::{well_known_keys, StateVersion, Storage}; use sp_runtime::{ traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero}, BuildStorage, }; -use std::{marker::PhantomData, sync::Arc}; + +/// Return the state version given the genesis storage and executor. +pub fn resolve_state_version_from_wasm( + storage: &Storage, + executor: &E, +) -> sp_blockchain::Result +where + E: RuntimeVersionOf, +{ + if let Some(wasm) = storage.top.get(well_known_keys::CODE) { + let mut ext = sp_state_machine::BasicExternalities::new_empty(); // just to read runtime version. + + let code_fetcher = sp_core::traits::WrappedRuntimeCode(wasm.as_slice().into()); + let runtime_code = sp_core::traits::RuntimeCode { + code_fetcher: &code_fetcher, + heap_pages: None, + hash: { + use std::hash::{Hash, Hasher}; + let mut state = DefaultHasher::new(); + wasm.hash(&mut state); + state.finish().to_le_bytes().to_vec() + }, + }; + let runtime_version = RuntimeVersionOf::runtime_version(executor, &mut ext, &runtime_code) + .map_err(|e| sp_blockchain::Error::VersionInvalid(e.to_string()))?; + Ok(runtime_version.state_version()) + } else { + Err(sp_blockchain::Error::VersionInvalid( + "Runtime missing from initial storage, could not read state version.".to_string(), + )) + } +} /// Create a genesis block, given the initial storage. -pub fn construct_genesis_block(state_root: Block::Hash) -> Block { +pub fn construct_genesis_block( + state_root: Block::Hash, + state_version: StateVersion, +) -> Block { let extrinsics_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root( Vec::new(), - sp_runtime::StateVersion::V0, + state_version, ); Block::new( @@ -93,12 +129,11 @@ impl, E: RuntimeVersionOf> BuildGenesisBlock sp_blockchain::Result<(Block, Self::BlockImportOperation)> { let Self { genesis_storage, commit_genesis_state, backend, executor, _phantom } = self; - let genesis_state_version = - crate::resolve_state_version_from_wasm(&genesis_storage, &executor)?; + let genesis_state_version = resolve_state_version_from_wasm(&genesis_storage, &executor)?; let mut op = backend.begin_operation()?; let state_root = op.set_genesis_state(genesis_storage, commit_genesis_state, genesis_state_version)?; - let genesis_block = construct_genesis_block::(state_root); + let genesis_block = construct_genesis_block::(state_root, genesis_state_version); Ok((genesis_block, op)) } diff --git a/client/chain-spec/src/lib.rs b/client/chain-spec/src/lib.rs index 414df1fe1296f..e43a247961f02 100644 --- a/client/chain-spec/src/lib.rs +++ b/client/chain-spec/src/lib.rs @@ -177,10 +177,15 @@ mod chain_spec; mod extension; +mod genesis; -pub use chain_spec::{ChainSpec as GenericChainSpec, NoExtension}; -pub use extension::{ - get_extension, get_extension_mut, Extension, Fork, Forks, GetExtension, Group, +pub use self::{ + chain_spec::{ChainSpec as GenericChainSpec, NoExtension}, + extension::{get_extension, get_extension_mut, Extension, Fork, Forks, GetExtension, Group}, + genesis::{ + construct_genesis_block, resolve_state_version_from_wasm, BuildGenesisBlock, + GenesisBlockBuilder, + }, }; pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 4b5822ae0e017..9a2a376ebc19f 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -18,16 +18,14 @@ //! Substrate Client -use super::{ - block_rules::{BlockRules, LookupResult as BlockLookupResult}, - genesis::BuildGenesisBlock, -}; +use super::block_rules::{BlockRules, LookupResult as BlockLookupResult}; use futures::{FutureExt, StreamExt}; use log::{error, info, trace, warn}; use parking_lot::{Mutex, RwLock}; use prometheus_endpoint::Registry; use rand::Rng; use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider, RecordProof}; +use sc_chain_spec::{resolve_state_version_from_wasm, BuildGenesisBlock}; use sc_client_api::{ backend::{ self, apply_aux, BlockImportOperation, ClientImportOperation, FinalizeSummary, Finalizer, @@ -46,7 +44,7 @@ use sc_client_api::{ use sc_consensus::{ BlockCheckParams, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction, }; -use sc_executor::{RuntimeVersion, RuntimeVersionOf}; +use sc_executor::RuntimeVersion; use sc_telemetry::{telemetry, TelemetryHandle, SUBSTRATE_INFO}; use sp_api::{ ApiExt, ApiRef, CallApiAt, CallApiAtParams, ConstructRuntimeApi, Core as CoreApi, @@ -61,8 +59,8 @@ use sp_consensus::{BlockOrigin, BlockStatus, Error as ConsensusError}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_core::{ storage::{ - well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, Storage, StorageChild, - StorageData, StorageKey, + well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, StorageChild, StorageData, + StorageKey, }, traits::SpawnNamed, }; @@ -84,7 +82,7 @@ use sp_state_machine::{ }; use sp_trie::{CompactProof, StorageProof}; use std::{ - collections::{hash_map::DefaultHasher, HashMap, HashSet}, + collections::{HashMap, HashSet}, marker::PhantomData, path::PathBuf, sync::Arc, @@ -172,7 +170,7 @@ pub fn new_in_mem( Client, LocalCallExecutor, E>, Block, RA>, > where - E: CodeExecutor + RuntimeVersionOf, + E: CodeExecutor + sc_executor::RuntimeVersionOf, Block: BlockT, G: BuildGenesisBlock< Block, @@ -233,7 +231,7 @@ pub fn new_with_backend( config: ClientConfig, ) -> sp_blockchain::Result, Block, RA>> where - E: CodeExecutor + RuntimeVersionOf, + E: CodeExecutor + sc_executor::RuntimeVersionOf, G: BuildGenesisBlock< Block, BlockImportOperation = >::BlockImportOperation, @@ -1222,38 +1220,6 @@ where } } -/// Return the genesis state version given the genesis storage and executor. -pub fn resolve_state_version_from_wasm( - storage: &Storage, - executor: &E, -) -> sp_blockchain::Result -where - E: RuntimeVersionOf, -{ - if let Some(wasm) = storage.top.get(well_known_keys::CODE) { - let mut ext = sp_state_machine::BasicExternalities::new_empty(); // just to read runtime version. - - let code_fetcher = sp_core::traits::WrappedRuntimeCode(wasm.as_slice().into()); - let runtime_code = sp_core::traits::RuntimeCode { - code_fetcher: &code_fetcher, - heap_pages: None, - hash: { - use std::hash::{Hash, Hasher}; - let mut state = DefaultHasher::new(); - wasm.hash(&mut state); - state.finish().to_le_bytes().to_vec() - }, - }; - let runtime_version = RuntimeVersionOf::runtime_version(executor, &mut ext, &runtime_code) - .map_err(|e| sp_blockchain::Error::VersionInvalid(e.to_string()))?; - Ok(runtime_version.state_version()) - } else { - Err(sp_blockchain::Error::VersionInvalid( - "Runtime missing from initial storage, could not read state version.".to_string(), - )) - } -} - impl UsageProvider for Client where B: backend::Backend, diff --git a/client/service/src/client/mod.rs b/client/service/src/client/mod.rs index 38d818c498a6a..a13fd4317e155 100644 --- a/client/service/src/client/mod.rs +++ b/client/service/src/client/mod.rs @@ -47,13 +47,12 @@ mod block_rules; mod call_executor; mod client; -pub mod genesis; mod wasm_override; mod wasm_substitutes; pub use self::{ call_executor::LocalCallExecutor, - client::{resolve_state_version_from_wasm, Client, ClientConfig}, + client::{Client, ClientConfig}, }; #[cfg(feature = "test-helpers")] diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index af0b11f2092c4..6bafa9936c0bf 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -61,12 +61,15 @@ pub use self::{ new_full_parts, spawn_tasks, BuildNetworkParams, KeystoreContainer, NetworkStarter, SpawnTasksParams, TFullBackend, TFullCallExecutor, TFullClient, }, - client::{ - genesis::{BuildGenesisBlock, GenesisBlockBuilder}, - resolve_state_version_from_wasm, ClientConfig, LocalCallExecutor, - }, + client::{ClientConfig, LocalCallExecutor}, error::Error, }; + +pub use sc_chain_spec::{ + construct_genesis_block, resolve_state_version_from_wasm, BuildGenesisBlock, + GenesisBlockBuilder, +}; + pub use config::{ BasePath, BlocksPruning, Configuration, DatabaseSource, PruningMode, Role, RpcMethods, TaskType, }; diff --git a/test-utils/runtime/client/Cargo.toml b/test-utils/runtime/client/Cargo.toml index 7d5c9673f6e21..986db0ba60283 100644 --- a/test-utils/runtime/client/Cargo.toml +++ b/test-utils/runtime/client/Cargo.toml @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] codec = { package = "parity-scale-codec", version = "3.2.2" } futures = "0.3.21" sc-block-builder = { version = "0.10.0-dev", path = "../../../client/block-builder" } +sc-chain-spec = { version = "4.0.0-dev", path = "../../../client/chain-spec" } sc-client-api = { version = "4.0.0-dev", path = "../../../client/api" } sc-consensus = { version = "0.10.0-dev", path = "../../../client/consensus/common" } sp-api = { version = "4.0.0-dev", path = "../../../primitives/api" } diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index 97ee525f6eb9a..099aeab11f768 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -30,6 +30,8 @@ pub use substrate_test_runtime as runtime; pub use self::block_builder_ext::BlockBuilderExt; +use sc_chain_spec::construct_genesis_block; +use sp_api::StateVersion; use sp_core::{ sr25519, storage::{ChildInfo, Storage, StorageChild}, @@ -122,7 +124,7 @@ impl GenesisParameters { } } -impl substrate_test_client::GenesisInit for GenesisParameters { +impl GenesisInit for GenesisParameters { fn genesis_storage(&self) -> Storage { use codec::Encode; @@ -148,7 +150,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters { storage.top.clone().into_iter().chain(child_roots).collect(), sp_runtime::StateVersion::V1, ); - let block: runtime::Block = client::genesis::construct_genesis_block(state_root); + let block: runtime::Block = construct_genesis_block(state_root, StateVersion::V1); storage.top.extend(additional_storage_with_genesis(&block)); storage @@ -260,7 +262,7 @@ impl TestClientBuilderExt client::LocalCallExecutor< substrate_test_runtime::Block, B, - sc_executor::NativeElseWasmExecutor, + NativeElseWasmExecutor, >, B, > where @@ -288,11 +290,6 @@ pub fn new() -> Client { } /// Create a new native executor. -pub fn new_native_executor() -> sc_executor::NativeElseWasmExecutor { - sc_executor::NativeElseWasmExecutor::new( - sc_executor::WasmExecutionMethod::Interpreted, - None, - 8, - 2, - ) +pub fn new_native_executor() -> NativeElseWasmExecutor { + NativeElseWasmExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8, 2) } diff --git a/test-utils/runtime/src/genesismap.rs b/test-utils/runtime/src/genesismap.rs index 77fdf59ea8cb4..9e00dd29999f8 100644 --- a/test-utils/runtime/src/genesismap.rs +++ b/test-utils/runtime/src/genesismap.rs @@ -20,10 +20,10 @@ use super::{system, wasm_binary_unwrap, AccountId, AuthorityId, Runtime}; use codec::{Encode, Joiner, KeyedVec}; use frame_support::traits::GenesisBuild; -use sc_service::client::genesis; +use sc_service::construct_genesis_block; use sp_core::{ map, - storage::{well_known_keys, Storage}, + storage::{well_known_keys, StateVersion, Storage}, }; use sp_io::hashing::{blake2_256, twox_128}; use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; @@ -106,7 +106,7 @@ pub fn insert_genesis_block(storage: &mut Storage) -> sp_core::hash::H256 { storage.top.clone().into_iter().collect(), sp_runtime::StateVersion::V1, ); - let block: crate::Block = genesis::construct_genesis_block(state_root); + let block: crate::Block = construct_genesis_block(state_root, StateVersion::V1); let genesis_hash = block.header.hash(); storage.top.extend(additional_storage_with_genesis(&block)); genesis_hash