diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index ac67db2e52..cb7d7c713b 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1479,6 +1479,7 @@ dependencies = [ "sc-client-db", "sc-executor", "sc-service", + "sp-core", "sp-runtime", "sp-state-machine", "structopt", @@ -7158,6 +7159,7 @@ dependencies = [ "byteorder 1.3.4", "criterion 0.2.11", "ed25519-dalek", + "futures 0.3.4", "hash-db", "hash256-std-hasher", "hex", diff --git a/substrate/bin/node/testing/src/bench.rs b/substrate/bin/node/testing/src/bench.rs index d49a6411cf..3bc8d483ea 100644 --- a/substrate/bin/node/testing/src/bench.rs +++ b/substrate/bin/node/testing/src/bench.rs @@ -197,6 +197,7 @@ impl BenchDb { None, None, ExecutionExtensions::new(profile.into_execution_strategies(), None), + sp_core::tasks::executor(), None, ).expect("Should not fail"); diff --git a/substrate/client/api/src/lib.rs b/substrate/client/api/src/lib.rs index 66f51e75c7..e4080323c1 100644 --- a/substrate/client/api/src/lib.rs +++ b/substrate/client/api/src/lib.rs @@ -34,7 +34,7 @@ pub use light::*; pub use notifications::*; pub use proof_provider::*; -pub use sp_state_machine::{StorageProof, ExecutionStrategy}; +pub use sp_state_machine::{StorageProof, ExecutionStrategy, CloneableSpawn}; /// Utility methods for the client. pub mod utils { diff --git a/substrate/client/db/src/lib.rs b/substrate/client/db/src/lib.rs index 4494978aee..62a8a5b43e 100644 --- a/substrate/client/db/src/lib.rs +++ b/substrate/client/db/src/lib.rs @@ -47,7 +47,7 @@ use std::io; use std::collections::HashMap; use sc_client_api::{ - ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo, MemorySize, + ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo, MemorySize, CloneableSpawn, execution_extensions::ExecutionExtensions, backend::{NewBlockState, PrunableStateChangesTrieStorage}, }; @@ -292,6 +292,7 @@ pub fn new_client( fork_blocks: ForkBlocks, bad_blocks: BadBlocks, execution_extensions: ExecutionExtensions, + spawn_handle: Box, prometheus_registry: Option, ) -> Result<( sc_client::Client< @@ -309,7 +310,7 @@ pub fn new_client( E: CodeExecutor + RuntimeInfo, { let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); - let executor = sc_client::LocalCallExecutor::new(backend.clone(), executor); + let executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle); Ok(( sc_client::Client::new( backend.clone(), diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs index 7237a55377..4363e204c0 100644 --- a/substrate/client/service/src/builder.rs +++ b/substrate/client/service/src/builder.rs @@ -263,6 +263,7 @@ fn new_full_parts( fork_blocks, bad_blocks, extensions, + Box::new(tasks_builder.spawn_handle()), config.prometheus_config.as_ref().map(|config| config.registry.clone()), )? }; @@ -366,6 +367,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { sc_client::light::new_fetch_checker::<_, TBl, _>( light_blockchain.clone(), executor.clone(), + Box::new(tasks_builder.spawn_handle()), ), ); let fetcher = Arc::new(sc_network::config::OnDemand::new(fetch_checker)); @@ -375,6 +377,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> { backend.clone(), config.expect_chain_spec().as_storage_builder(), executor, + Box::new(tasks_builder.spawn_handle()), config.prometheus_config.as_ref().map(|config| config.registry.clone()), )?); diff --git a/substrate/client/service/src/task_manager.rs b/substrate/client/service/src/task_manager.rs index d7041e44b9..15dc33abfa 100644 --- a/substrate/client/service/src/task_manager.rs +++ b/substrate/client/service/src/task_manager.rs @@ -26,6 +26,7 @@ use futures::{ compat::*, task::{Spawn, FutureObj, SpawnError}, }; +use sc_client_api::CloneableSpawn; /// Type alias for service task executor (usually runtime). pub type ServiceTaskExecutor = Arc + Send>>) + Send + Sync>; @@ -118,6 +119,12 @@ impl Spawn for SpawnTaskHandle { } } +impl sc_client_api::CloneableSpawn for SpawnTaskHandle { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } +} + type Boxed01Future01 = Box + Send + 'static>; impl futures01::future::Executor for SpawnTaskHandle { diff --git a/substrate/client/src/call_executor.rs b/substrate/client/src/call_executor.rs index 3fb6123640..5a374a8102 100644 --- a/substrate/client/src/call_executor.rs +++ b/substrate/client/src/call_executor.rs @@ -27,13 +27,14 @@ use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; use sp_externalities::Extensions; use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor}; use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; -use sc_client_api::{backend, call_executor::CallExecutor}; +use sc_client_api::{backend, call_executor::CallExecutor, CloneableSpawn}; /// Call executor that executes methods locally, querying all required /// data from local backend. pub struct LocalCallExecutor { backend: Arc, executor: E, + spawn_handle: Box, } impl LocalCallExecutor { @@ -41,10 +42,12 @@ impl LocalCallExecutor { pub fn new( backend: Arc, executor: E, + spawn_handle: Box, ) -> Self { LocalCallExecutor { backend, executor, + spawn_handle, } } } @@ -54,6 +57,7 @@ impl Clone for LocalCallExecutor where E: Clone { LocalCallExecutor { backend: self.backend.clone(), executor: self.executor.clone(), + spawn_handle: self.spawn_handle.clone(), } } } @@ -91,6 +95,7 @@ where call_data, extensions.unwrap_or_default(), &state_runtime_code.runtime_code()?, + self.spawn_handle.clone(), ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( strategy.get_manager(), None, @@ -164,6 +169,7 @@ where call_data, extensions.unwrap_or_default(), &runtime_code, + self.spawn_handle.clone(), ) // TODO: https://github.com/paritytech/substrate/issues/4455 // .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)) @@ -180,6 +186,7 @@ where call_data, extensions.unwrap_or_default(), &state_runtime_code.runtime_code()?, + self.spawn_handle.clone(), ) .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)) .execute_using_consensus_failure_handler(execution_manager, native_call) @@ -218,6 +225,7 @@ where trie_state, overlay, &self.executor, + self.spawn_handle.clone(), method, call_data, &sp_state_machine::backend::BackendRuntimeCode::new(trie_state).runtime_code()?, diff --git a/substrate/client/src/client.rs b/substrate/client/src/client.rs index f6feb0e858..5c7fa80291 100644 --- a/substrate/client/src/client.rs +++ b/substrate/client/src/client.rs @@ -76,7 +76,7 @@ pub use sc_client_api::{ }, execution_extensions::{ExecutionExtensions, ExecutionStrategies}, notifications::{StorageNotifications, StorageEventStream}, - CallExecutor, ExecutorProvider, ProofProvider, + CallExecutor, ExecutorProvider, ProofProvider, CloneableSpawn, }; use sp_blockchain::Error; use prometheus_endpoint::Registry; @@ -135,6 +135,7 @@ pub fn new_in_mem( genesis_storage: &S, keystore: Option, prometheus_registry: Option, + spawn_handle: Box, ) -> sp_blockchain::Result, LocalCallExecutor, E>, @@ -145,7 +146,7 @@ pub fn new_in_mem( S: BuildStorage, Block: BlockT, { - new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage, keystore, prometheus_registry) + new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage, keystore, spawn_handle, prometheus_registry) } /// Create a client with the explicitly provided backend. @@ -155,6 +156,7 @@ pub fn new_with_backend( executor: E, build_genesis_storage: &S, keystore: Option, + spawn_handle: Box, prometheus_registry: Option, ) -> sp_blockchain::Result, Block, RA>> where @@ -163,7 +165,7 @@ pub fn new_with_backend( Block: BlockT, B: backend::LocalBackend + 'static, { - let call_executor = LocalCallExecutor::new(backend.clone(), executor); + let call_executor = LocalCallExecutor::new(backend.clone(), executor, spawn_handle); let extensions = ExecutionExtensions::new(Default::default(), keystore); Client::new( backend, @@ -1124,7 +1126,13 @@ impl ProofProvider for Client where let state = self.state_at(id)?; let header = self.prepare_environment_block(id)?; - prove_execution(state, header, &self.executor, method, call_data).map(|(r, p)| { + prove_execution( + state, + header, + &self.executor, + method, + call_data, + ).map(|(r, p)| { (r, StorageProof::merge(vec![p, code_proof])) }) } @@ -3482,6 +3490,7 @@ pub(crate) mod tests { &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), None, None, + sp_core::tasks::executor(), ) .unwrap(); diff --git a/substrate/client/src/genesis.rs b/substrate/client/src/genesis.rs index 37c0a19a9b..2c84ff1e43 100644 --- a/substrate/client/src/genesis.rs +++ b/substrate/client/src/genesis.rs @@ -54,6 +54,7 @@ mod tests { AccountKeyring, Sr25519Keyring, }; use sp_runtime::traits::BlakeTwo256; + use sp_core::tasks::executor as tasks_executor; use hex_literal::*; native_executor_instance!( @@ -101,6 +102,7 @@ mod tests { &header.encode(), Default::default(), &runtime_code, + tasks_executor(), ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -115,6 +117,7 @@ mod tests { &tx.encode(), Default::default(), &runtime_code, + tasks_executor(), ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -129,6 +132,7 @@ mod tests { &[], Default::default(), &runtime_code, + tasks_executor(), ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -179,6 +183,7 @@ mod tests { &b1data, Default::default(), &runtime_code, + tasks_executor(), ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -210,6 +215,7 @@ mod tests { &b1data, Default::default(), &runtime_code, + tasks_executor(), ).execute( ExecutionStrategy::AlwaysWasm, ).unwrap(); @@ -241,6 +247,7 @@ mod tests { &b1data, Default::default(), &runtime_code, + tasks_executor(), ).execute( ExecutionStrategy::NativeElseWasm, ); diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index e5365e2e64..20a3ed058a 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -62,6 +62,7 @@ //! LocalCallExecutor::new( //! backend.clone(), //! NativeExecutor::::new(WasmExecutionMethod::Interpreted, None, 8), +//! sp_core::tasks::executor(), //! ), //! // This parameter provides the storage for the chain genesis. //! &::default(), diff --git a/substrate/client/src/light/call_executor.rs b/substrate/client/src/light/call_executor.rs index a08b0f4c44..b439a268d2 100644 --- a/substrate/client/src/light/call_executor.rs +++ b/substrate/client/src/light/call_executor.rs @@ -28,7 +28,7 @@ use sp_runtime::{ use sp_externalities::Extensions; use sp_state_machine::{ self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend, - execution_proof_check_on_trie_backend, ExecutionManager, StorageProof, + execution_proof_check_on_trie_backend, ExecutionManager, StorageProof, CloneableSpawn, }; use hash_db::Hasher; @@ -216,6 +216,7 @@ pub fn prove_execution( /// Proof should include both environment preparation proof and method execution proof. pub fn check_execution_proof( executor: &E, + spawn_handle: Box, request: &RemoteCallRequest
, remote_proof: StorageProof, ) -> ClientResult> @@ -227,6 +228,7 @@ pub fn check_execution_proof( { check_execution_proof_with_make_header::( executor, + spawn_handle, request, remote_proof, |header|
::new( @@ -241,6 +243,7 @@ pub fn check_execution_proof( fn check_execution_proof_with_make_header Header>( executor: &E, + spawn_handle: Box, request: &RemoteCallRequest
, remote_proof: StorageProof, make_next_header: MakeNextHeader, @@ -267,6 +270,7 @@ fn check_execution_proof_with_make_header( &local_executor(), + tasks_executor(), &RemoteCallRequest { block: substrate_test_runtime_client::runtime::Hash::default(), header: remote_header, @@ -414,6 +420,7 @@ mod tests { // check remote execution proof locally let execution_result = check_execution_proof_with_make_header::<_, _, BlakeTwo256, _>( &local_executor(), + tasks_executor(), &RemoteCallRequest { block: substrate_test_runtime_client::runtime::Hash::default(), header: remote_header, diff --git a/substrate/client/src/light/fetcher.rs b/substrate/client/src/light/fetcher.rs index b48e3a3b78..0ae0e68e0c 100644 --- a/substrate/client/src/light/fetcher.rs +++ b/substrate/client/src/light/fetcher.rs @@ -30,7 +30,7 @@ use sp_runtime::traits::{ use sp_state_machine::{ ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db, - read_child_proof_check, + read_child_proof_check, CloneableSpawn, }; pub use sp_state_machine::StorageProof; use sp_blockchain::{Error as ClientError, Result as ClientResult}; @@ -50,14 +50,15 @@ use crate::light::call_executor::check_execution_proof; pub struct LightDataChecker> { blockchain: Arc>, executor: E, + spawn_handle: Box, _hasher: PhantomData<(B, H)>, } impl> LightDataChecker { /// Create new light data checker. - pub fn new(blockchain: Arc>, executor: E) -> Self { + pub fn new(blockchain: Arc>, executor: E, spawn_handle: Box) -> Self { Self { - blockchain, executor, _hasher: PhantomData + blockchain, executor, spawn_handle, _hasher: PhantomData } } @@ -254,7 +255,12 @@ impl FetchChecker for LightDataChecker request: &RemoteCallRequest, remote_proof: StorageProof, ) -> ClientResult> { - check_execution_proof::<_, _, H>(&self.executor, request, remote_proof) + check_execution_proof::<_, _, H>( + &self.executor, + self.spawn_handle.clone(), + request, + remote_proof, + ) } fn check_changes_proof( @@ -338,7 +344,8 @@ pub mod tests { use sc_client_api::backend::NewBlockState; use substrate_test_runtime_client::{ blockchain::HeaderBackend, AccountKeyring, ClientBlockImportExt, - runtime::{self, Hash, Block, Header, Extrinsic} + runtime::{self, Hash, Block, Header, Extrinsic}, + tasks_executor, }; use sp_consensus::BlockOrigin; @@ -395,7 +402,8 @@ pub mod tests { ).unwrap(); let local_checker = LightDataChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), - local_executor() + local_executor(), + tasks_executor(), ); (local_checker, remote_block_header, remote_read_proof, heap_pages) } @@ -444,6 +452,7 @@ pub mod tests { let local_checker = LightDataChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), + tasks_executor(), ); (local_checker, remote_block_header, remote_read_proof, child_value) } @@ -474,6 +483,7 @@ pub mod tests { let local_checker = LightDataChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), + tasks_executor(), ); (local_checker, local_cht_root, remote_block_header, remote_header_proof) } @@ -559,6 +569,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), + tasks_executor(), ); let local_checker = &local_checker as &dyn FetchChecker; let max = remote_client.chain_info().best_number; @@ -633,6 +644,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), local_executor(), + tasks_executor(), ); // check proof on local client @@ -667,6 +679,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), + tasks_executor(), ); let local_checker = &local_checker as &dyn FetchChecker; let max = remote_client.chain_info().best_number; @@ -754,6 +767,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), + tasks_executor(), ); assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, remote_proof.roots_proof.clone()).is_err()); @@ -764,6 +778,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), local_executor(), + tasks_executor(), ); let result = local_checker.check_changes_tries_proof( 4, &remote_proof.roots, StorageProof::empty() @@ -781,6 +796,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), + tasks_executor(), ); let body_request = RemoteBodyRequest { @@ -804,6 +820,7 @@ pub mod tests { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), + tasks_executor(), ); let body_request = RemoteBodyRequest { diff --git a/substrate/client/src/light/mod.rs b/substrate/client/src/light/mod.rs index 865e6e9ac9..2bb6c85376 100644 --- a/substrate/client/src/light/mod.rs +++ b/substrate/client/src/light/mod.rs @@ -33,7 +33,7 @@ use prometheus_endpoint::Registry; use crate::call_executor::LocalCallExecutor; use crate::client::Client; use sc_client_api::{ - light::Storage as BlockchainStorage, + light::Storage as BlockchainStorage, CloneableSpawn, }; use crate::light::backend::Backend; use crate::light::blockchain::Blockchain; @@ -59,6 +59,7 @@ pub fn new_light( backend: Arc>>, genesis_storage: &dyn BuildStorage, code_executor: E, + spawn_handle: Box, prometheus_registry: Option, ) -> ClientResult< Client< @@ -76,7 +77,7 @@ pub fn new_light( S: BlockchainStorage + 'static, E: CodeExecutor + RuntimeInfo + Clone + 'static, { - let local_executor = LocalCallExecutor::new(backend.clone(), code_executor); + let local_executor = LocalCallExecutor::new(backend.clone(), code_executor, spawn_handle.clone()); let executor = GenesisCallExecutor::new(backend.clone(), local_executor); Client::new( backend, @@ -93,9 +94,10 @@ pub fn new_light( pub fn new_fetch_checker>( blockchain: Arc>, executor: E, + spawn_handle: Box, ) -> LightDataChecker, B, S> where E: CodeExecutor, { - LightDataChecker::new(blockchain, executor) + LightDataChecker::new(blockchain, executor, spawn_handle) } diff --git a/substrate/primitives/api/test/tests/runtime_calls.rs b/substrate/primitives/api/test/tests/runtime_calls.rs index eb128a512c..a907ac8095 100644 --- a/substrate/primitives/api/test/tests/runtime_calls.rs +++ b/substrate/primitives/api/test/tests/runtime_calls.rs @@ -200,6 +200,7 @@ fn record_proof_works() { &backend, &mut overlay, &executor, + sp_core::tasks::executor(), "Core_execute_block", &block.encode(), &runtime_code, diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml index 4112aff01f..2b694fea30 100644 --- a/substrate/primitives/core/Cargo.toml +++ b/substrate/primitives/core/Cargo.toml @@ -34,6 +34,7 @@ sp-debug-derive = { version = "2.0.0-alpha.2", path = "../debug-derive" } sp-externalities = { version = "0.8.0-alpha.2", optional = true, path = "../externalities" } sp-storage = { version = "2.0.0-alpha.2", default-features = false, path = "../storage" } parity-util-mem = { version = "0.5.2", default-features = false, features = ["primitive-types"] } +futures = { version = "0.3.1", optional = true } # full crypto ed25519-dalek = { version = "1.0.0-pre.3", default-features = false, features = ["u64_backend", "alloc"], optional = true } @@ -102,7 +103,9 @@ std = [ "sp-externalities", "sp-storage/std", "sp-runtime-interface/std", - "zeroize/alloc" + "zeroize/alloc", + "futures", + "futures/thread-pool", ] # This feature enables all crypto primitives for `no_std` builds like microcontrollers diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs index 79721b9b76..79380a6fc6 100644 --- a/substrate/primitives/core/src/lib.rs +++ b/substrate/primitives/core/src/lib.rs @@ -70,6 +70,8 @@ mod changes_trie; #[cfg(feature = "std")] pub mod traits; pub mod testing; +#[cfg(feature = "std")] +pub mod tasks; pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::uint::U256; diff --git a/substrate/primitives/core/src/tasks.rs b/substrate/primitives/core/src/tasks.rs new file mode 100644 index 0000000000..199a185e53 --- /dev/null +++ b/substrate/primitives/core/src/tasks.rs @@ -0,0 +1,56 @@ +// Copyright 2020 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 . + +//! Module for low-level asynchronous processing. + +use crate::traits::CloneableSpawn; +use futures::{executor, task}; + +/// Simple task executor. +/// +/// Uses single thread for scheduling tasks. Can be cloned and used in +/// runtime host (implements `CloneableSpawn`). +#[derive(Debug, Clone)] +pub struct Executor { + pool: executor::ThreadPool, +} + +impl Executor { + fn new() -> Self { + Self { + pool: executor::ThreadPool::builder().pool_size(1).create() + .expect("Failed to create task executor") + } + } +} + +impl task::Spawn for Executor { + fn spawn_obj(&self, future: task::FutureObj<'static, ()>) + -> Result<(), task::SpawnError> { + self.pool.spawn_obj(future) + } +} + +impl CloneableSpawn for Executor { + fn clone(&self) -> Box { + Box::new(Clone::clone(self)) + } +} + +/// Create tasks executor. +pub fn executor() -> Box { + Box::new(Executor::new()) +} \ No newline at end of file diff --git a/substrate/primitives/core/src/traits.rs b/substrate/primitives/core/src/traits.rs index 83cbebd7d6..21a0b77ca7 100644 --- a/substrate/primitives/core/src/traits.rs +++ b/substrate/primitives/core/src/traits.rs @@ -212,3 +212,21 @@ impl CallInWasmExt { Self(Box::new(inner)) } } + +/// Something that can spawn tasks and also can be cloned. +pub trait CloneableSpawn: futures::task::Spawn + Send + Sync { + /// Clone as heap-allocated handle. + fn clone(&self) -> Box; +} + +sp_externalities::decl_extension! { + /// Task executor extension. + pub struct TaskExecutorExt(Box); +} + +impl TaskExecutorExt { + /// New instance of task executor extension. + pub fn new(spawn_handle: Box) -> Self { + Self(spawn_handle) + } +} diff --git a/substrate/primitives/externalities/Cargo.toml b/substrate/primitives/externalities/Cargo.toml index f462b7670e..dc47515dcc 100644 --- a/substrate/primitives/externalities/Cargo.toml +++ b/substrate/primitives/externalities/Cargo.toml @@ -12,4 +12,4 @@ documentation = "https://docs.rs/sp-externalities" [dependencies] sp-storage = { version = "2.0.0-alpha.2", path = "../storage" } sp-std = { version = "2.0.0-alpha.2", path = "../std" } -environmental = { version = "1.1.1" } +environmental = { version = "1.1.1" } \ No newline at end of file diff --git a/substrate/primitives/state-machine/src/ext.rs b/substrate/primitives/state-machine/src/ext.rs index bbb25355a8..b29446de2e 100644 --- a/substrate/primitives/state-machine/src/ext.rs +++ b/substrate/primitives/state-machine/src/ext.rs @@ -573,7 +573,6 @@ mod tests { const CHILD_UUID_1: &[u8] = b"unique_id_1"; const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(CHILD_UUID_1); - fn prepare_overlay_with_changes() -> OverlayedChanges { OverlayedChanges { prospective: vec![ diff --git a/substrate/primitives/state-machine/src/lib.rs b/substrate/primitives/state-machine/src/lib.rs index 4d80ee37c9..2d992e778e 100644 --- a/substrate/primitives/state-machine/src/lib.rs +++ b/substrate/primitives/state-machine/src/lib.rs @@ -74,6 +74,7 @@ pub use trie_backend::TrieBackend; pub use error::{Error, ExecutionError}; pub use in_memory_backend::InMemory as InMemoryBackend; pub use stats::{UsageInfo, UsageUnit}; +pub use sp_core::traits::CloneableSpawn; type CallResult = Result, E>; @@ -210,8 +211,10 @@ impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> where call_data: &'a [u8], mut extensions: Extensions, runtime_code: &'a RuntimeCode, + spawn_handle: Box, ) -> Self { extensions.register(CallInWasmExt::new(exec.clone())); + extensions.register(sp_core::traits::TaskExecutorExt::new(spawn_handle)); Self { backend, @@ -437,6 +440,7 @@ pub fn prove_execution( mut backend: B, overlay: &mut OverlayedChanges, exec: &Exec, + spawn_handle: Box, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -454,6 +458,7 @@ where trie_backend, overlay, exec, + spawn_handle, method, call_data, runtime_code, @@ -473,6 +478,7 @@ pub fn prove_execution_on_trie_backend( trie_backend: &TrieBackend, overlay: &mut OverlayedChanges, exec: &Exec, + spawn_handle: Box, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -494,6 +500,7 @@ where call_data, Extensions::default(), runtime_code, + spawn_handle, ); let result = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( @@ -510,6 +517,7 @@ pub fn execution_proof_check( proof: StorageProof, overlay: &mut OverlayedChanges, exec: &Exec, + spawn_handle: Box, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -525,6 +533,7 @@ where &trie_backend, overlay, exec, + spawn_handle, method, call_data, runtime_code, @@ -536,6 +545,7 @@ pub fn execution_proof_check_on_trie_backend( trie_backend: &TrieBackend, H>, overlay: &mut OverlayedChanges, exec: &Exec, + spawn_handle: Box, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -555,6 +565,7 @@ where call_data, Extensions::default(), runtime_code, + spawn_handle, ); sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( @@ -820,6 +831,7 @@ mod tests { &[], Default::default(), &wasm_code, + sp_core::tasks::executor(), ); assert_eq!( @@ -849,6 +861,7 @@ mod tests { &[], Default::default(), &wasm_code, + sp_core::tasks::executor(), ); assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap(), vec![66]); @@ -875,6 +888,7 @@ mod tests { &[], Default::default(), &wasm_code, + sp_core::tasks::executor(), ); assert!( @@ -905,6 +919,7 @@ mod tests { remote_backend, &mut Default::default(), &executor, + sp_core::tasks::executor(), "test", &[], &RuntimeCode::empty(), @@ -916,6 +931,7 @@ mod tests { remote_proof, &mut Default::default(), &executor, + sp_core::tasks::executor(), "test", &[], &RuntimeCode::empty(), diff --git a/substrate/test-utils/client/src/lib.rs b/substrate/test-utils/client/src/lib.rs index 104a800d21..d04e85fd10 100644 --- a/substrate/test-utils/client/src/lib.rs +++ b/substrate/test-utils/client/src/lib.rs @@ -23,7 +23,7 @@ pub mod client_ext; pub use sc_client::{blockchain, self}; pub use sc_client_api::{ execution_extensions::{ExecutionStrategies, ExecutionExtensions}, - ForkBlocks, BadBlocks, + ForkBlocks, BadBlocks, CloneableSpawn, }; pub use sc_client_db::{Backend, self}; pub use sp_consensus; @@ -33,7 +33,7 @@ pub use sp_keyring::{ ed25519::Keyring as Ed25519Keyring, sr25519::Keyring as Sr25519Keyring, }; -pub use sp_core::traits::BareCryptoStorePtr; +pub use sp_core::{traits::BareCryptoStorePtr, tasks::executor as tasks_executor}; pub use sp_runtime::{Storage, StorageChild}; pub use sp_state_machine::ExecutionStrategy; pub use self::client_ext::{ClientExt, ClientBlockImportExt}; @@ -246,7 +246,7 @@ impl TestClientBuilder< let executor = executor.into().unwrap_or_else(|| NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8) ); - let executor = LocalCallExecutor::new(self.backend.clone(), executor); + let executor = LocalCallExecutor::new(self.backend.clone(), executor, tasks_executor()); self.build_with_executor(executor) } diff --git a/substrate/test-utils/runtime/client/src/lib.rs b/substrate/test-utils/runtime/client/src/lib.rs index ccaf644b82..f0a405e67e 100644 --- a/substrate/test-utils/runtime/client/src/lib.rs +++ b/substrate/test-utils/runtime/client/src/lib.rs @@ -349,7 +349,7 @@ pub fn new_light() -> ( let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage)); let backend = Arc::new(LightBackend::new(blockchain.clone())); let executor = new_native_executor(); - let local_call_executor = sc_client::LocalCallExecutor::new(backend.clone(), executor); + let local_call_executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor()); let call_executor = LightExecutor::new( backend.clone(), local_call_executor, diff --git a/substrate/utils/frame/benchmarking-cli/Cargo.toml b/substrate/utils/frame/benchmarking-cli/Cargo.toml index a14b37dd46..67b217c287 100644 --- a/substrate/utils/frame/benchmarking-cli/Cargo.toml +++ b/substrate/utils/frame/benchmarking-cli/Cargo.toml @@ -10,6 +10,7 @@ description = "CLI for benchmarking FRAME" [dependencies] frame-benchmarking = { version = "2.0.0-alpha.2", path = "../../../frame/benchmarking" } +sp-core = { version = "2.0.0-alpha.2", path = "../../../primitives/core" } sc-service = { version = "0.8.0-alpha.2", default-features = false, path = "../../../client/service" } sc-cli = { version = "0.8.0-alpha.2", path = "../../../client/cli" } sc-client = { version = "0.8.0-alpha.2", path = "../../../client" } diff --git a/substrate/utils/frame/benchmarking-cli/src/lib.rs b/substrate/utils/frame/benchmarking-cli/src/lib.rs index 4467753c35..79e7e689a6 100644 --- a/substrate/utils/frame/benchmarking-cli/src/lib.rs +++ b/substrate/utils/frame/benchmarking-cli/src/lib.rs @@ -23,6 +23,7 @@ use sc_service::{Configuration, ChainSpec}; use sc_executor::{NativeExecutor, NativeExecutionDispatch}; use codec::{Encode, Decode}; use frame_benchmarking::BenchmarkResults; +use sp_core::tasks; /// The `benchmark` command used to benchmark FRAME Pallets. #[derive(Debug, structopt::StructOpt, Clone)] @@ -121,6 +122,7 @@ impl BenchmarkCmd { ).encode(), Default::default(), &sp_state_machine::backend::BackendRuntimeCode::new(&state).runtime_code()?, + tasks::executor(), ) .execute(strategy.into()) .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?;