From 22429e0dde96cf47412151798953bb099b16e2b7 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 18 Sep 2022 18:35:49 +0800 Subject: [PATCH 01/11] Set genesis block data using the built genesis block --- client/service/src/client/client.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 27561046c3481..7fda20a7f43bd 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -374,13 +374,8 @@ where } else { NewBlockState::Normal }; - op.set_block_data( - genesis_block.deconstruct().0, - Some(vec![]), - None, - None, - block_state, - )?; + let (header, body) = genesis_block.deconstruct(); + op.set_block_data(header, Some(body), None, None, block_state)?; backend.commit_operation(op)?; } From 217770eb4ad8d0596b98ab65ef171158fbc567a3 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 18 Sep 2022 19:05:19 +0800 Subject: [PATCH 02/11] Make resolve_state_version_from_wasm a separate function and some small refactorings Useful for the commit following. --- bin/node/testing/src/bench.rs | 21 +++++----- client/service/src/client/client.rs | 62 +++++++++++++++-------------- client/service/src/client/mod.rs | 2 +- client/service/src/lib.rs | 2 +- 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 7980cc102fb38..a36f5427118a0 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -397,16 +397,19 @@ impl BenchDb { let task_executor = TaskExecutor::new(); let backend = sc_service::new_db_backend(db_config).expect("Should not fail"); + let executor = NativeElseWasmExecutor::new( + WasmExecutionMethod::Compiled { + instantiation_strategy: WasmtimeInstantiationStrategy::PoolingCopyOnWrite, + }, + None, + 8, + 2, + ); + let client_config = sc_service::ClientConfig::default(); + let client = sc_service::new_client( backend.clone(), - NativeElseWasmExecutor::new( - WasmExecutionMethod::Compiled { - instantiation_strategy: WasmtimeInstantiationStrategy::PoolingCopyOnWrite, - }, - None, - 8, - 2, - ), + executor, &keyring.generate_genesis(), None, None, @@ -414,7 +417,7 @@ impl BenchDb { Box::new(task_executor.clone()), None, None, - Default::default(), + client_config, ) .expect("Should not fail"); diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 7fda20a7f43bd..2f279c10a5584 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -357,7 +357,7 @@ where let genesis_storage = build_genesis_storage.build_storage().map_err(sp_blockchain::Error::Storage)?; let genesis_state_version = - Self::resolve_state_version_from_wasm(&genesis_storage, &executor)?; + resolve_state_version_from_wasm::(&genesis_storage, &executor)?; let mut op = backend.begin_operation()?; let state_root = op.set_genesis_state(genesis_storage, !config.no_genesis, genesis_state_version)?; @@ -631,7 +631,7 @@ where // This is use by fast sync for runtime version to be resolvable from // changes. let state_version = - Self::resolve_state_version_from_wasm(&storage, &self.executor)?; + resolve_state_version_from_wasm::(&storage, &self.executor)?; let state_root = operation.op.reset_storage(storage, state_version)?; if state_root != *import_headers.post().state_root() { // State root mismatch when importing state. This should not happen in @@ -1095,34 +1095,38 @@ where trace!("Collected {} uncles", uncles.len()); Ok(uncles) } +} - fn resolve_state_version_from_wasm( - storage: &Storage, - executor: &E, - ) -> sp_blockchain::Result { - 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(), - )) - } +/// 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 + Block: BlockT, + 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(), + )) } } diff --git a/client/service/src/client/mod.rs b/client/service/src/client/mod.rs index eac744923d501..dafeb68831885 100644 --- a/client/service/src/client/mod.rs +++ b/client/service/src/client/mod.rs @@ -53,7 +53,7 @@ mod wasm_substitutes; pub use self::{ call_executor::LocalCallExecutor, - client::{Client, ClientConfig}, + client::{resolve_state_version_from_wasm, Client, ClientConfig}, }; #[cfg(feature = "test-helpers")] diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 19358c1e5bc4c..4606eb360ae75 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -58,7 +58,7 @@ pub use self::{ new_full_parts, spawn_tasks, BuildNetworkParams, KeystoreContainer, NetworkStarter, SpawnTasksParams, TFullBackend, TFullCallExecutor, TFullClient, }, - client::{ClientConfig, LocalCallExecutor}, + client::{resolve_state_version_from_wasm, ClientConfig, LocalCallExecutor}, error::Error, }; pub use config::{ From 2f2ae4a5b94a1c9b0a36faf4cfb3406c5c21fb1a Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 18 Sep 2022 19:38:35 +0800 Subject: [PATCH 03/11] Introduce trait BuildGenesisBlock Substrate users can use this trait to implement their custom genesis block when constructing the client. --- bin/node-template/node/src/service.rs | 13 +++- bin/node/cli/src/service.rs | 13 +++- bin/node/inspect/src/command.rs | 17 +++++- bin/node/testing/src/bench.rs | 9 ++- client/service/src/builder.rs | 47 ++++++++------- client/service/src/client/call_executor.rs | 10 +++- client/service/src/client/client.rs | 50 +++++++++------- client/service/src/client/genesis.rs | 69 +++++++++++++++++++++- client/service/src/config.rs | 17 ++++++ client/service/src/lib.rs | 5 +- client/service/test/src/client/mod.rs | 19 +++++- test-utils/client/src/lib.rs | 24 +++++--- 12 files changed, 234 insertions(+), 59 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index caa01761636df..8f5da3e5261cf 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -80,11 +80,22 @@ pub fn new_partial( config.runtime_cache_size, ); + let backend = sc_service::new_db_backend(config.db_config())?; + + let genesis_block_builder = sc_service::GenesisBlockBuilder::new( + config.chain_spec.as_storage_builder(), + !config.no_genesis(), + backend.clone(), + executor.clone(), + )?; + let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, + backend, + genesis_block_builder, )?; let client = Arc::new(client); diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index c058e22fa7a97..3a849c7d51042 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -167,11 +167,22 @@ pub fn new_partial( config.runtime_cache_size, ); + let backend = sc_service::new_db_backend(config.db_config())?; + + let genesis_block_builder = sc_service::GenesisBlockBuilder::new( + config.chain_spec.as_storage_builder(), + !config.no_genesis(), + backend.clone(), + executor.clone(), + )?; + let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, + backend, + genesis_block_builder, )?; let client = Arc::new(client); diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index ce164e0768fbc..fc39d76d590fe 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -44,7 +44,22 @@ impl InspectCmd { config.runtime_cache_size, ); - let client = new_full_client::(&config, None, executor)?; + let backend = sc_service::new_db_backend(config.db_config())?; + + let genesis_block_builder = sc_service::GenesisBlockBuilder::new( + config.chain_spec.as_storage_builder(), + !config.no_genesis(), + backend.clone(), + executor.clone(), + )?; + + let client = new_full_client::( + &config, + None, + executor, + backend, + genesis_block_builder, + )?; let inspect = Inspector::::new(client); match &self.command { diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index a36f5427118a0..aa4150eb81ec0 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -406,11 +406,18 @@ impl BenchDb { 2, ); let client_config = sc_service::ClientConfig::default(); + let genesis_block_builder = sc_service::GenesisBlockBuilder::new( + &keyring.generate_genesis(), + client_config.no_genesis, + backend.clone(), + executor.clone(), + ) + .expect("Failed to create genesis block builder"); let client = sc_service::new_client( backend.clone(), executor, - &keyring.generate_genesis(), + genesis_block_builder, None, None, ExecutionExtensions::new(profile.into_execution_strategies(), None, None), diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 5a2f4cf978b41..26753989eb81c 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -22,7 +22,8 @@ use crate::{ config::{Configuration, KeystoreConfig, PrometheusConfig}, error::Error, metrics::MetricsService, - start_rpc_servers, RpcHandlers, SpawnTaskHandle, TaskManager, TransactionPoolAdapter, + start_rpc_servers, BuildGenesisBlock, RpcHandlers, SpawnTaskHandle, TaskManager, + TransactionPoolAdapter, }; use futures::{channel::oneshot, future::ready, FutureExt, StreamExt}; use jsonrpsee::RpcModule; @@ -69,7 +70,6 @@ use sp_keystore::{CryptoStore, SyncCryptoStore, SyncCryptoStorePtr}; use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, BlockIdTo, NumberFor, Zero}, - BuildStorage, }; use std::{str::FromStr, sync::Arc, time::SystemTime}; @@ -167,27 +167,39 @@ impl KeystoreContainer { } /// Creates a new full client for the given config. -pub fn new_full_client( +pub fn new_full_client( config: &Configuration, telemetry: Option, executor: TExec, + backend: Arc>, + genesis_block_builder: TBuildGenesisBlock, ) -> Result, Error> where TBl: BlockT, TExec: CodeExecutor + RuntimeVersionOf + Clone, + TBuildGenesisBlock: BuildGenesisBlock< + TBl, + BlockImportOperation = as sc_client_api::backend::Backend>::BlockImportOperation + >, { - new_full_parts(config, telemetry, executor).map(|parts| parts.0) + new_full_parts(config, telemetry, executor, backend, genesis_block_builder).map(|parts| parts.0) } /// Create the initial parts of a full node. -pub fn new_full_parts( +pub fn new_full_parts( config: &Configuration, telemetry: Option, executor: TExec, + backend: Arc>, + genesis_block_builder: TBuildGenesisBlock, ) -> Result, Error> where TBl: BlockT, TExec: CodeExecutor + RuntimeVersionOf + Clone, + TBuildGenesisBlock: BuildGenesisBlock< + TBl, + BlockImportOperation = as sc_client_api::backend::Backend>::BlockImportOperation + >, { let keystore_container = KeystoreContainer::new(&config.keystore)?; @@ -205,16 +217,7 @@ where .cloned() .unwrap_or_default(); - let (client, backend) = { - let db_config = sc_client_db::DatabaseSettings { - trie_cache_maximum_size: config.trie_cache_maximum_size, - state_pruning: config.state_pruning.clone(), - source: config.database.clone(), - blocks_pruning: config.blocks_pruning, - }; - - let backend = new_db_backend(db_config)?; - + let client = { let extensions = sc_client_api::execution_extensions::ExecutionExtensions::new( config.execution_strategies.clone(), Some(keystore_container.sync_keystore()), @@ -241,7 +244,7 @@ where let client = new_client( backend.clone(), executor, - chain_spec.as_storage_builder(), + genesis_block_builder, fork_blocks, bad_blocks, extensions, @@ -260,7 +263,7 @@ where }, )?; - (client, backend) + client }; Ok((client, backend, keystore_container, task_manager)) @@ -279,10 +282,10 @@ where } /// Create an instance of client backed by given backend. -pub fn new_client( +pub fn new_client( backend: Arc>, executor: E, - genesis_storage: &dyn BuildStorage, + genesis_block_builder: G, fork_blocks: ForkBlocks, bad_blocks: BadBlocks, execution_extensions: ExecutionExtensions, @@ -302,6 +305,10 @@ pub fn new_client( where Block: BlockT, E: CodeExecutor + RuntimeVersionOf, + G: BuildGenesisBlock< + Block, + BlockImportOperation = as sc_client_api::backend::Backend>::BlockImportOperation + >, { let executor = crate::client::LocalCallExecutor::new( backend.clone(), @@ -312,7 +319,7 @@ where crate::client::Client::new( backend, executor, - genesis_storage, + genesis_block_builder, fork_blocks, bad_blocks, execution_extensions, diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index e39436ec641d7..e22c804f02c1a 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -364,6 +364,14 @@ mod tests { // LocalCallExecutor directly later on let client_config = ClientConfig::default(); + let genesis_block_builder = crate::GenesisBlockBuilder::new( + &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), + !client_config.no_genesis, + backend.clone(), + executor.clone(), + ) + .expect("Creates genesis block builder"); + // client is used for the convenience of creating and inserting the genesis block. let _client = substrate_test_runtime_client::client::new_with_backend::< _, @@ -374,7 +382,7 @@ mod tests { >( backend.clone(), executor.clone(), - &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), + genesis_block_builder, None, Box::new(TaskExecutor::new()), None, diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 2f279c10a5584..971c1971e93dc 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -20,7 +20,7 @@ use super::{ block_rules::{BlockRules, LookupResult as BlockLookupResult}, - genesis, + genesis::BuildGenesisBlock, }; use log::{info, trace, warn}; use parking_lot::{Mutex, RwLock}; @@ -69,7 +69,7 @@ use sp_runtime::{ traits::{ Block as BlockT, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion, Zero, }, - BuildStorage, Digest, Justification, Justifications, StateVersion, + Digest, Justification, Justifications, StateVersion, }; use sp_state_machine::{ prove_child_read, prove_range_read_with_child_with_size, prove_read, @@ -155,9 +155,10 @@ enum PrepareStorageChangesResult, Block: BlockT> { /// Create an instance of in-memory client. #[cfg(feature = "test-helpers")] -pub fn new_in_mem( +pub fn new_in_mem( + backend: Arc>, executor: E, - genesis_storage: &S, + genesis_block_builder: G, keystore: Option, prometheus_registry: Option, telemetry: Option, @@ -168,13 +169,16 @@ pub fn new_in_mem( > where E: CodeExecutor + RuntimeVersionOf, - S: BuildStorage, Block: BlockT, + G: BuildGenesisBlock< + Block, + BlockImportOperation = as backend::Backend>::BlockImportOperation, + >, { new_with_backend( - Arc::new(in_mem::Backend::new()), + backend, executor, - genesis_storage, + genesis_block_builder, keystore, spawn_handle, prometheus_registry, @@ -214,10 +218,10 @@ impl Default for ClientConfig { /// Create a client with the explicitly provided backend. /// This is useful for testing backend implementations. #[cfg(feature = "test-helpers")] -pub fn new_with_backend( +pub fn new_with_backend( backend: Arc, executor: E, - build_genesis_storage: &S, + genesis_block_builder: G, keystore: Option, spawn_handle: Box, prometheus_registry: Option, @@ -226,7 +230,10 @@ pub fn new_with_backend( ) -> sp_blockchain::Result, Block, RA>> where E: CodeExecutor + RuntimeVersionOf, - S: BuildStorage, + G: BuildGenesisBlock< + Block, + BlockImportOperation = >::BlockImportOperation, + >, Block: BlockT, B: backend::LocalBackend + 'static, { @@ -240,7 +247,7 @@ where Client::new( backend, call_executor, - build_genesis_storage, + genesis_block_builder, Default::default(), Default::default(), extensions, @@ -341,27 +348,26 @@ where Block::Header: Clone, { /// Creates new Substrate Client with given blockchain and code executor. - pub fn new( + pub fn new( backend: Arc, executor: E, - build_genesis_storage: &dyn BuildStorage, + genesis_block_builder: G, fork_blocks: ForkBlocks, bad_blocks: BadBlocks, execution_extensions: ExecutionExtensions, prometheus_registry: Option, telemetry: Option, config: ClientConfig, - ) -> sp_blockchain::Result { + ) -> sp_blockchain::Result + where + G: BuildGenesisBlock< + Block, + BlockImportOperation = >::BlockImportOperation, + >, + { let info = backend.blockchain().info(); if info.finalized_state.is_none() { - let genesis_storage = - build_genesis_storage.build_storage().map_err(sp_blockchain::Error::Storage)?; - 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, !config.no_genesis, genesis_state_version)?; - let genesis_block = genesis::construct_genesis_block::(state_root); + let (genesis_block, mut op) = genesis_block_builder.build_genesis_block()?; info!( "🔨 Initializing Genesis block/state (state: {}, header-hash: {})", genesis_block.header().state_root(), diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index 35fb11f04972a..53542079017a7 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -18,7 +18,14 @@ //! Tool for creating the genesis block. -use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero}; +use sc_client_api::{backend::Backend, BlockImportOperation}; +use sc_executor::RuntimeVersionOf; +use sp_core::storage::Storage; +use sp_runtime::{ + traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero}, + BuildStorage, +}; +use std::{marker::PhantomData, sync::Arc}; /// Create a genesis block, given the initial storage. pub fn construct_genesis_block(state_root: Block::Hash) -> Block { @@ -38,3 +45,63 @@ pub fn construct_genesis_block(state_root: Block::Hash) -> Block Default::default(), ) } + +/// Trait for building the genesis block. +pub trait BuildGenesisBlock { + /// Same type with `sc_client_api::backend::Backend::BlockImportOperation`. + type BlockImportOperation; + + /// Returns the built genesis block along with the block import operation + /// after setting the genesis storage. + fn build_genesis_block(self) -> sp_blockchain::Result<(Block, Self::BlockImportOperation)>; +} + +/// Build the genesis block. +pub struct GenesisBlockBuilder { + genesis_storage: Storage, + commit_genesis_state: bool, + backend: Arc, + executor: E, + _phantom: PhantomData, +} + +impl, E: RuntimeVersionOf> GenesisBlockBuilder { + /// Constructs a new instance of [`GenesisBlockBuilder`]. + pub fn new( + build_genesis_storage: &dyn BuildStorage, + commit_genesis_state: bool, + backend: Arc, + executor: E, + ) -> sp_blockchain::Result { + let genesis_storage = + build_genesis_storage.build_storage().map_err(sp_blockchain::Error::Storage)?; + Ok(Self { + genesis_storage, + commit_genesis_state, + backend, + executor, + _phantom: PhantomData::, + }) + } +} + +impl, E: RuntimeVersionOf> BuildGenesisBlock + for GenesisBlockBuilder +{ + type BlockImportOperation = >::BlockImportOperation; + fn build_genesis_block(self) -> 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 mut op = backend.begin_operation()?; + let state_root = op.set_genesis_state( + genesis_storage.clone(), + commit_genesis_state, + genesis_state_version, + )?; + let genesis_block = construct_genesis_block::(state_root); + + Ok((genesis_block, op)) + } +} diff --git a/client/service/src/config.rs b/client/service/src/config.rs index 44153e3b914f3..718d8c4654839 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -38,6 +38,7 @@ pub use sc_network_common::{ use prometheus_endpoint::Registry; use sc_chain_spec::ChainSpec; +use sc_network::config::SyncMode; pub use sc_telemetry::TelemetryEndpoints; pub use sc_transaction_pool::Options as TransactionPoolOptions; use sp_core::crypto::SecretString; @@ -242,6 +243,22 @@ impl Configuration { }; ProtocolId::from(protocol_id_full) } + + /// Returns true if the genesis state writting will be skipped while initializing the genesis + /// block. + pub fn no_genesis(&self) -> bool { + matches!(self.network.sync_mode, SyncMode::Fast { .. } | SyncMode::Warp { .. }) + } + + /// Returns the database config for creating the backend. + pub fn db_config(&self) -> sc_client_db::DatabaseSettings { + sc_client_db::DatabaseSettings { + trie_cache_maximum_size: self.trie_cache_maximum_size, + state_pruning: self.state_pruning.clone(), + source: self.database.clone(), + blocks_pruning: self.blocks_pruning, + } + } } /// Available RPC methods. diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 4606eb360ae75..0306bd52b7708 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -58,7 +58,10 @@ pub use self::{ new_full_parts, spawn_tasks, BuildNetworkParams, KeystoreContainer, NetworkStarter, SpawnTasksParams, TFullBackend, TFullCallExecutor, TFullClient, }, - client::{resolve_state_version_from_wasm, ClientConfig, LocalCallExecutor}, + client::{ + genesis::{BuildGenesisBlock, GenesisBlockBuilder}, + resolve_state_version_from_wasm, ClientConfig, LocalCallExecutor, + }, error::Error, }; pub use config::{ diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index f02b1321d2922..92bdd00892561 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -1726,17 +1726,30 @@ fn storage_keys_iter_works() { fn cleans_up_closed_notification_sinks_on_block_import() { use substrate_test_runtime_client::GenesisInit; + let backend = Arc::new(sc_client_api::in_mem::Backend::new()); + let executor = substrate_test_runtime_client::new_native_executor(); + let client_config = sc_service::ClientConfig::default(); + + let genesis_block_builder = sc_service::GenesisBlockBuilder::new( + &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), + !client_config.no_genesis, + backend.clone(), + executor.clone(), + ) + .unwrap(); + // NOTE: we need to build the client here instead of using the client // provided by test_runtime_client otherwise we can't access the private // `import_notification_sinks` and `finality_notification_sinks` fields. let mut client = new_in_mem::<_, Block, _, RuntimeApi>( - substrate_test_runtime_client::new_native_executor(), - &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), + backend, + executor, + genesis_block_builder, None, None, None, Box::new(TaskExecutor::new()), - Default::default(), + client_config, ) .unwrap(); diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 3115be58425e6..5f9fd7438edea 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -202,7 +202,7 @@ impl ) where ExecutorDispatch: - sc_client_api::CallExecutor + sc_executor::RuntimeVersionOf + 'static, + sc_client_api::CallExecutor + sc_executor::RuntimeVersionOf + Clone + 'static, Backend: sc_client_api::backend::Backend, >::OffchainStorage: 'static, { @@ -222,10 +222,24 @@ impl storage }; + let client_config = ClientConfig { + offchain_indexing_api: self.enable_offchain_indexing_api, + no_genesis: self.no_genesis, + ..Default::default() + }; + + let genesis_block_builder = sc_service::GenesisBlockBuilder::new( + &storage, + !client_config.no_genesis, + self.backend.clone(), + executor.clone(), + ) + .expect("Creates genesis block builder"); + let client = client::Client::new( self.backend.clone(), executor, - &storage, + genesis_block_builder, self.fork_blocks, self.bad_blocks, ExecutionExtensions::new( @@ -235,11 +249,7 @@ impl ), None, None, - ClientConfig { - offchain_indexing_api: self.enable_offchain_indexing_api, - no_genesis: self.no_genesis, - ..Default::default() - }, + client_config, ) .expect("Creates new client"); From db96310eeab92981fa0014fd9b6f20d092b88212 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 18 Sep 2022 20:21:19 +0800 Subject: [PATCH 04/11] Make call_executor test compile --- client/service/src/client/call_executor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index e22c804f02c1a..7106044b1069d 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -373,7 +373,7 @@ mod tests { .expect("Creates genesis block builder"); // client is used for the convenience of creating and inserting the genesis block. - let _client = substrate_test_runtime_client::client::new_with_backend::< + let _client = crate::client::new_with_backend::< _, _, runtime::Block, From 2d538e8929f9ce8c0481841d69660c96aead10bf Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 18 Sep 2022 20:23:37 +0800 Subject: [PATCH 05/11] cargo +nightly fmt --all --- client/service/src/client/call_executor.rs | 29 +++++++++------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 7106044b1069d..b7733c52663ca 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -373,23 +373,18 @@ mod tests { .expect("Creates genesis block builder"); // client is used for the convenience of creating and inserting the genesis block. - let _client = crate::client::new_with_backend::< - _, - _, - runtime::Block, - _, - runtime::RuntimeApi, - >( - backend.clone(), - executor.clone(), - genesis_block_builder, - None, - Box::new(TaskExecutor::new()), - None, - None, - Default::default(), - ) - .expect("Creates a client"); + let _client = + crate::client::new_with_backend::<_, _, runtime::Block, _, runtime::RuntimeApi>( + backend.clone(), + executor.clone(), + genesis_block_builder, + None, + Box::new(TaskExecutor::new()), + None, + None, + Default::default(), + ) + .expect("Creates a client"); let call_executor = LocalCallExecutor { backend: backend.clone(), From 96361d023a66712b3fa656ea68152f2bad3facaa Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Mon, 26 Sep 2022 06:53:24 +0800 Subject: [PATCH 06/11] Fix test --- bin/node/testing/src/bench.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index aa4150eb81ec0..971d88b5b1b02 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -408,7 +408,7 @@ impl BenchDb { let client_config = sc_service::ClientConfig::default(); let genesis_block_builder = sc_service::GenesisBlockBuilder::new( &keyring.generate_genesis(), - client_config.no_genesis, + !client_config.no_genesis, backend.clone(), executor.clone(), ) From 61861be55ae173174e2ffd536154ade75c6a0b72 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Mon, 26 Sep 2022 07:01:53 +0800 Subject: [PATCH 07/11] Remove unnecessary clone --- client/service/src/client/genesis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index 53542079017a7..383bf12ffd9e1 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -96,7 +96,7 @@ impl, E: RuntimeVersionOf> BuildGenesisBlock(&genesis_storage, &executor)?; let mut op = backend.begin_operation()?; let state_root = op.set_genesis_state( - genesis_storage.clone(), + genesis_storage, commit_genesis_state, genesis_state_version, )?; From 3d1867305515f5690ab955a8a3c56cbcb6924901 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Thu, 27 Oct 2022 20:41:30 +0800 Subject: [PATCH 08/11] FMT --- client/service/src/client/genesis.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index 383bf12ffd9e1..5d523c9c08846 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -95,11 +95,8 @@ impl, E: RuntimeVersionOf> BuildGenesisBlock(&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 state_root = + op.set_genesis_state(genesis_storage, commit_genesis_state, genesis_state_version)?; let genesis_block = construct_genesis_block::(state_root); Ok((genesis_block, op)) From 9691b25ee5c2af5b4170d5b200b1183cdc8a8962 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 18 Dec 2022 10:56:08 +0800 Subject: [PATCH 09/11] Apply review suggestions --- bin/node-template/node/src/service.rs | 10 +------- bin/node/cli/src/service.rs | 10 +------- bin/node/inspect/src/command.rs | 15 +---------- client/service/src/builder.rs | 36 +++++++++++++++++++-------- client/service/src/client/genesis.rs | 5 ++-- 5 files changed, 32 insertions(+), 44 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 832e9d2e376ed..d44a8a395a99b 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -82,20 +82,12 @@ pub fn new_partial( let backend = sc_service::new_db_backend(config.db_config())?; - let genesis_block_builder = sc_service::GenesisBlockBuilder::new( - config.chain_spec.as_storage_builder(), - !config.no_genesis(), - backend.clone(), - executor.clone(), - )?; - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, backend, - genesis_block_builder, )?; let client = Arc::new(client); diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index a3903f07b35b8..72cca7a9325ce 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -169,20 +169,12 @@ pub fn new_partial( let backend = sc_service::new_db_backend(config.db_config())?; - let genesis_block_builder = sc_service::GenesisBlockBuilder::new( - config.chain_spec.as_storage_builder(), - !config.no_genesis(), - backend.clone(), - executor.clone(), - )?; - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, backend, - genesis_block_builder, )?; let client = Arc::new(client); diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index fc39d76d590fe..849c39227fdd0 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -46,20 +46,7 @@ impl InspectCmd { let backend = sc_service::new_db_backend(config.db_config())?; - let genesis_block_builder = sc_service::GenesisBlockBuilder::new( - config.chain_spec.as_storage_builder(), - !config.no_genesis(), - backend.clone(), - executor.clone(), - )?; - - let client = new_full_client::( - &config, - None, - executor, - backend, - genesis_block_builder, - )?; + let client = new_full_client::(&config, None, executor, backend)?; let inspect = Inspector::::new(client); match &self.command { diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index b1eeb61b8ac95..cdfd506c949f0 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -22,8 +22,8 @@ use crate::{ config::{Configuration, KeystoreConfig, PrometheusConfig}, error::Error, metrics::MetricsService, - start_rpc_servers, BuildGenesisBlock, RpcHandlers, SpawnTaskHandle, TaskManager, - TransactionPoolAdapter, + start_rpc_servers, BuildGenesisBlock, GenesisBlockBuilder, RpcHandlers, SpawnTaskHandle, + TaskManager, TransactionPoolAdapter, }; use futures::{channel::oneshot, future::ready, FutureExt, StreamExt}; use jsonrpsee::RpcModule; @@ -170,26 +170,42 @@ impl KeystoreContainer { } /// Creates a new full client for the given config. -pub fn new_full_client( +pub fn new_full_client( config: &Configuration, telemetry: Option, executor: TExec, backend: Arc>, - genesis_block_builder: TBuildGenesisBlock, ) -> Result, Error> where TBl: BlockT, TExec: CodeExecutor + RuntimeVersionOf + Clone, - TBuildGenesisBlock: BuildGenesisBlock< - TBl, - BlockImportOperation = as sc_client_api::backend::Backend>::BlockImportOperation - >, { - new_full_parts(config, telemetry, executor, backend, genesis_block_builder).map(|parts| parts.0) + new_full_parts(config, telemetry, executor, backend).map(|parts| parts.0) +} + +/// Create the initial parts of a full node with the default genesis block builder. +pub fn new_full_parts( + config: &Configuration, + telemetry: Option, + executor: TExec, + backend: Arc>, +) -> Result, Error> +where + TBl: BlockT, + TExec: CodeExecutor + RuntimeVersionOf + Clone, +{ + let genesis_block_builder = GenesisBlockBuilder::new( + config.chain_spec.as_storage_builder(), + !config.no_genesis(), + backend.clone(), + executor.clone(), + )?; + + new_full_parts_with_genesis_builder(config, telemetry, executor, backend, genesis_block_builder) } /// Create the initial parts of a full node. -pub fn new_full_parts( +pub fn new_full_parts_with_genesis_builder( config: &Configuration, telemetry: Option, executor: TExec, diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index 5d523c9c08846..561bfeb1b2e88 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -48,7 +48,7 @@ pub fn construct_genesis_block(state_root: Block::Hash) -> Block /// Trait for building the genesis block. pub trait BuildGenesisBlock { - /// Same type with `sc_client_api::backend::Backend::BlockImportOperation`. + /// The import operation used to import the genesis block into the backend. type BlockImportOperation; /// Returns the built genesis block along with the block import operation @@ -56,7 +56,7 @@ pub trait BuildGenesisBlock { fn build_genesis_block(self) -> sp_blockchain::Result<(Block, Self::BlockImportOperation)>; } -/// Build the genesis block. +/// Default genesis block builder in Substrate. pub struct GenesisBlockBuilder { genesis_storage: Storage, commit_genesis_state: bool, @@ -89,6 +89,7 @@ impl, E: RuntimeVersionOf> BuildGenesisBlock { type BlockImportOperation = >::BlockImportOperation; + fn build_genesis_block(self) -> sp_blockchain::Result<(Block, Self::BlockImportOperation)> { let Self { genesis_storage, commit_genesis_state, backend, executor, _phantom } = self; From 27cfafddeda5524fc2eb8843feab8ef788754c02 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Sun, 18 Dec 2022 12:38:21 +0800 Subject: [PATCH 10/11] Revert changes to new_full_client() and new_full_parts() signature --- bin/node-template/node/src/service.rs | 3 --- bin/node/cli/src/service.rs | 3 --- bin/node/inspect/src/command.rs | 4 +--- client/service/src/builder.rs | 6 +++--- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index d44a8a395a99b..ee8464688c79c 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -80,14 +80,11 @@ pub fn new_partial( config.runtime_cache_size, ); - let backend = sc_service::new_db_backend(config.db_config())?; - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, - backend, )?; let client = Arc::new(client); diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index d41d2e40b5e5e..e7b825a8e5ef1 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -167,14 +167,11 @@ pub fn new_partial( config.runtime_cache_size, ); - let backend = sc_service::new_db_backend(config.db_config())?; - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, - backend, )?; let client = Arc::new(client); diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index 849c39227fdd0..ce164e0768fbc 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -44,9 +44,7 @@ impl InspectCmd { config.runtime_cache_size, ); - let backend = sc_service::new_db_backend(config.db_config())?; - - let client = new_full_client::(&config, None, executor, backend)?; + let client = new_full_client::(&config, None, executor)?; let inspect = Inspector::::new(client); match &self.command { diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 20f2751eab917..1c8f4c7de717d 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -174,13 +174,12 @@ pub fn new_full_client( config: &Configuration, telemetry: Option, executor: TExec, - backend: Arc>, ) -> Result, Error> where TBl: BlockT, TExec: CodeExecutor + RuntimeVersionOf + Clone, { - new_full_parts(config, telemetry, executor, backend).map(|parts| parts.0) + new_full_parts(config, telemetry, executor).map(|parts| parts.0) } /// Create the initial parts of a full node with the default genesis block builder. @@ -188,12 +187,13 @@ pub fn new_full_parts( config: &Configuration, telemetry: Option, executor: TExec, - backend: Arc>, ) -> Result, Error> where TBl: BlockT, TExec: CodeExecutor + RuntimeVersionOf + Clone, { + let backend = new_db_backend(config.db_config())?; + let genesis_block_builder = GenesisBlockBuilder::new( config.chain_spec.as_storage_builder(), !config.no_genesis(), From 15c7561f1133978754a6b44ffe04e3185c4a7bd9 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Mon, 19 Dec 2022 21:55:12 +0800 Subject: [PATCH 11/11] Remove needless `Block` type in `resolve_state_version_from_wasm` --- client/service/src/client/client.rs | 5 ++--- client/service/src/client/genesis.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 10426dc86bfa9..f81586d424799 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -641,7 +641,7 @@ where // This is use by fast sync for runtime version to be resolvable from // changes. let state_version = - resolve_state_version_from_wasm::(&storage, &self.executor)?; + resolve_state_version_from_wasm(&storage, &self.executor)?; let state_root = operation.op.reset_storage(storage, state_version)?; if state_root != *import_headers.post().state_root() { // State root mismatch when importing state. This should not happen in @@ -1108,12 +1108,11 @@ where } /// Return the genesis state version given the genesis storage and executor. -pub fn resolve_state_version_from_wasm( +pub fn resolve_state_version_from_wasm( storage: &Storage, executor: &E, ) -> sp_blockchain::Result where - Block: BlockT, E: RuntimeVersionOf, { if let Some(wasm) = storage.top.get(well_known_keys::CODE) { diff --git a/client/service/src/client/genesis.rs b/client/service/src/client/genesis.rs index 561bfeb1b2e88..54ef1182b7e7d 100644 --- a/client/service/src/client/genesis.rs +++ b/client/service/src/client/genesis.rs @@ -94,7 +94,7 @@ impl, E: RuntimeVersionOf> BuildGenesisBlock(&genesis_storage, &executor)?; + crate::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)?;