diff --git a/Cargo.lock b/Cargo.lock index e8a21ea6dd489..f4eb4baf74da0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1194,6 +1194,33 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote 1.0.6", + "syn 1.0.33", +] + +[[package]] +name = "dyn-clone" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c53dc3a653e0f64081026e4bf048d48fec9fce90c66e8326ca7292df0ff2d82" + [[package]] name = "ed25519" version = "1.0.1" @@ -7806,6 +7833,7 @@ dependencies = [ "byteorder", "criterion 0.2.11", "derive_more", + "dyn-clonable", "ed25519-dalek", "futures 0.3.5", "hash-db", diff --git a/bin/node/bench/src/txpool.rs b/bin/node/bench/src/txpool.rs index 8ac0633ae651b..9e57958795731 100644 --- a/bin/node/bench/src/txpool.rs +++ b/bin/node/bench/src/txpool.rs @@ -71,7 +71,7 @@ impl core::Benchmark for PoolBenchmark { std::thread::park_timeout(std::time::Duration::from_secs(3)); } - let executor = sp_core::testing::SpawnBlockingExecutor::new(); + let executor = sp_core::testing::TaskExecutor::new(); let txpool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(context.client.clone(), None)), diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 46a7318333d4a..65f2fdb64a82f 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -407,7 +407,7 @@ pub fn new_light_base(config: Configuration) -> Result<( } /// Builds a new service for a light client. -pub fn new_light(config: Configuration) -> Result { +pub fn new_light(config: Configuration) -> Result { new_light_base(config).map(|(task_manager, _, _, _, _)| { task_manager }) diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 6eaf0c625ddfe..8242886fe95ed 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -50,7 +50,7 @@ use node_runtime::{ AccountId, Signature, }; -use sp_core::{ExecutionContext, blake2_256, traits::CloneableSpawn}; +use sp_core::{ExecutionContext, blake2_256, traits::SpawnNamed, Pair, Public, sr25519, ed25519}; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_inherents::InherentData; @@ -58,9 +58,8 @@ use sc_client_api::{ ExecutionStrategy, BlockBackend, execution_extensions::{ExecutionExtensions, ExecutionStrategies}, }; -use sp_core::{Pair, Public, sr25519, ed25519}; use sc_block_builder::BlockBuilderProvider; -use futures::{executor, task}; +use futures::executor; /// Keyring full of accounts for benching. /// @@ -145,7 +144,7 @@ impl BlockType { pub fn to_content(self, size: Option) -> BlockContent { BlockContent { block_type: self, - size: size, + size, } } } @@ -197,16 +196,13 @@ impl TaskExecutor { } } -impl task::Spawn for TaskExecutor { - fn spawn_obj(&self, future: task::FutureObj<'static, ()>) - -> Result<(), task::SpawnError> { - self.pool.spawn_obj(future) +impl SpawnNamed for TaskExecutor { + fn spawn(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) { + self.pool.spawn_ok(future); } -} -impl CloneableSpawn for TaskExecutor { - fn clone(&self) -> Box { - Box::new(Clone::clone(self)) + fn spawn_blocking(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) { + self.pool.spawn_ok(future); } } diff --git a/client/api/src/lib.rs b/client/api/src/lib.rs index bad61f7687a63..677066936330e 100644 --- a/client/api/src/lib.rs +++ b/client/api/src/lib.rs @@ -37,7 +37,7 @@ pub use light::*; pub use notifications::*; pub use proof_provider::*; -pub use sp_state_machine::{StorageProof, ExecutionStrategy, CloneableSpawn}; +pub use sp_state_machine::{StorageProof, ExecutionStrategy}; /// Usage Information Provider interface /// diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index dd01f8893d27d..78bafb2f126a1 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -358,7 +358,7 @@ mod tests { fn should_cease_building_block_when_deadline_is_reached() { // given let client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let txpool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), @@ -412,7 +412,7 @@ mod tests { #[test] fn should_not_panic_when_deadline_is_reached() { let client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let txpool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), @@ -448,7 +448,7 @@ mod tests { fn proposed_storage_changes_should_match_execute_block_storage_changes() { let (client, backend) = TestClientBuilder::new().build_with_backend(); let client = Arc::new(client); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let txpool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), @@ -511,7 +511,7 @@ mod tests { fn should_not_remove_invalid_transactions_when_skipping() { // given let mut client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let txpool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), diff --git a/client/basic-authorship/src/lib.rs b/client/basic-authorship/src/lib.rs index 68356d0a28ff8..09536044fb89a 100644 --- a/client/basic-authorship/src/lib.rs +++ b/client/basic-authorship/src/lib.rs @@ -31,7 +31,7 @@ //! # }; //! # use sc_transaction_pool::{BasicPool, FullChainApi}; //! # let client = Arc::new(substrate_test_runtime_client::new()); -//! # let spawner = sp_core::testing::SpawnBlockingExecutor::new(); +//! # let spawner = sp_core::testing::TaskExecutor::new(); //! # let txpool = BasicPool::new_full( //! # Default::default(), //! # Arc::new(FullChainApi::new(client.clone(), None)), diff --git a/client/consensus/manual-seal/src/lib.rs b/client/consensus/manual-seal/src/lib.rs index 77fb5043c5dd6..2799a498c1fb8 100644 --- a/client/consensus/manual-seal/src/lib.rs +++ b/client/consensus/manual-seal/src/lib.rs @@ -220,7 +220,7 @@ mod tests { let (client, select_chain) = builder.build_with_longest_chain(); let client = Arc::new(client); let inherent_data_providers = InherentDataProviders::new(); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = Arc::new(BasicPool::with_revalidation_type( Options::default(), api(), None, RevalidationType::Full, spawner, )); @@ -288,7 +288,7 @@ mod tests { let (client, select_chain) = builder.build_with_longest_chain(); let client = Arc::new(client); let inherent_data_providers = InherentDataProviders::new(); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = Arc::new(BasicPool::with_revalidation_type( Options::default(), api(), None, RevalidationType::Full, spawner, )); @@ -360,7 +360,7 @@ mod tests { let client = Arc::new(client); let inherent_data_providers = InherentDataProviders::new(); let pool_api = api(); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = Arc::new(BasicPool::with_revalidation_type( Options::default(), pool_api.clone(), None, RevalidationType::Full, spawner, )); diff --git a/client/light/src/call_executor.rs b/client/light/src/call_executor.rs index 81be65339b696..fa0f02cd5aed9 100644 --- a/client/light/src/call_executor.rs +++ b/client/light/src/call_executor.rs @@ -23,14 +23,17 @@ use std::{ }; use codec::{Encode, Decode}; -use sp_core::{convert_hash, NativeOrEncoded, traits::CodeExecutor, offchain::storage::OffchainOverlayedChanges}; +use sp_core::{ + convert_hash, NativeOrEncoded, traits::{CodeExecutor, SpawnNamed}, + offchain::storage::OffchainOverlayedChanges, +}; use sp_runtime::{ generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, HashFor}, }; 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, CloneableSpawn, + execution_proof_check_on_trie_backend, ExecutionManager, StorageProof, }; use hash_db::Hasher; @@ -220,7 +223,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, + spawn_handle: Box, request: &RemoteCallRequest
, remote_proof: StorageProof, ) -> ClientResult> @@ -251,7 +254,7 @@ pub fn check_execution_proof( /// Proof should include both environment preparation proof and method execution proof. pub fn check_execution_proof_with_make_header( executor: &E, - spawn_handle: Box, + spawn_handle: Box, request: &RemoteCallRequest
, remote_proof: StorageProof, make_next_header: MakeNextHeader, @@ -275,7 +278,7 @@ pub fn check_execution_proof_with_make_header( let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&trie_backend); let runtime_code = backend_runtime_code.runtime_code()?; - execution_proof_check_on_trie_backend::( + execution_proof_check_on_trie_backend::( &trie_backend, &mut changes, executor, @@ -286,7 +289,7 @@ pub fn check_execution_proof_with_make_header( )?; // execute method - execution_proof_check_on_trie_backend::( + execution_proof_check_on_trie_backend::( &trie_backend, &mut changes, executor, diff --git a/client/light/src/fetcher.rs b/client/light/src/fetcher.rs index 88d20cafc903f..33113c2fc7df0 100644 --- a/client/light/src/fetcher.rs +++ b/client/light/src/fetcher.rs @@ -24,8 +24,7 @@ use std::marker::PhantomData; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use codec::{Decode, Encode}; -use sp_core::{convert_hash, traits::CodeExecutor}; -use sp_core::storage::{ChildInfo, ChildType}; +use sp_core::{convert_hash, traits::{CodeExecutor, SpawnNamed}, storage::{ChildInfo, ChildType}}; use sp_runtime::traits::{ Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor, AtLeast32Bit, CheckedConversion, @@ -33,7 +32,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, CloneableSpawn, + read_child_proof_check, }; pub use sp_state_machine::StorageProof; use sp_blockchain::{Error as ClientError, Result as ClientResult}; @@ -46,20 +45,23 @@ pub use sc_client_api::{ }, cht, }; -use crate::blockchain::Blockchain; -use crate::call_executor::check_execution_proof; +use crate::{blockchain::Blockchain, call_executor::check_execution_proof}; /// Remote data checker. pub struct LightDataChecker> { blockchain: Arc>, executor: E, - spawn_handle: Box, + spawn_handle: Box, _hasher: PhantomData<(B, H)>, } impl> LightDataChecker { /// Create new light data checker. - pub fn new(blockchain: Arc>, executor: E, spawn_handle: Box) -> Self { + pub fn new( + blockchain: Arc>, + executor: E, + spawn_handle: Box, + ) -> Self { Self { blockchain, executor, spawn_handle, _hasher: PhantomData } diff --git a/client/light/src/lib.rs b/client/light/src/lib.rs index deea642bd39d0..899d1ae31a3dd 100644 --- a/client/light/src/lib.rs +++ b/client/light/src/lib.rs @@ -19,9 +19,8 @@ //! Light client components. use sp_runtime::traits::{Block as BlockT, HashFor}; -use sc_client_api::CloneableSpawn; use std::sync::Arc; -use sp_core::traits::CodeExecutor; +use sp_core::traits::{CodeExecutor, SpawnNamed}; pub mod backend; pub mod blockchain; @@ -34,7 +33,7 @@ pub use {backend::*, blockchain::*, call_executor::*, fetcher::*}; pub fn new_fetch_checker>( blockchain: Arc>, executor: E, - spawn_handle: Box, + spawn_handle: Box, ) -> LightDataChecker, B, S> where E: CodeExecutor, diff --git a/client/network/src/service/tests.rs b/client/network/src/service/tests.rs index 17d9553fa66bb..0b02153d3d897 100644 --- a/client/network/src/service/tests.rs +++ b/client/network/src/service/tests.rs @@ -88,7 +88,7 @@ fn build_test_full_node(config: config::NetworkConfiguration) Box::new(client.clone()), None, None, - &sp_core::testing::SpawnBlockingExecutor::new(), + &sp_core::testing::TaskExecutor::new(), None, )); diff --git a/client/network/test/src/block_import.rs b/client/network/test/src/block_import.rs index 6762b74b6b8bd..1d2cd3d687de9 100644 --- a/client/network/test/src/block_import.rs +++ b/client/network/test/src/block_import.rs @@ -98,7 +98,7 @@ fn import_single_good_block_without_header_fails() { #[test] fn async_import_queue_drops() { - let executor = sp_core::testing::SpawnBlockingExecutor::new(); + let executor = sp_core::testing::TaskExecutor::new(); // Perform this test multiple times since it exhibits non-deterministic behavior. for _ in 0..100 { let verifier = PassThroughVerifier::new(true); diff --git a/client/network/test/src/lib.rs b/client/network/test/src/lib.rs index 30508711a6a4f..35587cbdc08b3 100644 --- a/client/network/test/src/lib.rs +++ b/client/network/test/src/lib.rs @@ -648,7 +648,7 @@ pub trait TestNetFactory: Sized { Box::new(block_import.clone()), justification_import, finality_proof_import, - &sp_core::testing::SpawnBlockingExecutor::new(), + &sp_core::testing::TaskExecutor::new(), None, )); @@ -728,7 +728,7 @@ pub trait TestNetFactory: Sized { Box::new(block_import.clone()), justification_import, finality_proof_import, - &sp_core::testing::SpawnBlockingExecutor::new(), + &sp_core::testing::TaskExecutor::new(), None, )); diff --git a/client/offchain/src/api.rs b/client/offchain/src/api.rs index 0aa5d4ad788ab..5287ac8251eeb 100644 --- a/client/offchain/src/api.rs +++ b/client/offchain/src/api.rs @@ -334,7 +334,7 @@ mod tests { // Compare. assert!(timestamp.unix_millis() > 0); - assert_eq!(timestamp.unix_millis(), d); + assert!(timestamp.unix_millis() >= d); } #[test] diff --git a/client/offchain/src/lib.rs b/client/offchain/src/lib.rs index f2fb8a8e978a0..bb2965c658913 100644 --- a/client/offchain/src/lib.rs +++ b/client/offchain/src/lib.rs @@ -247,7 +247,7 @@ mod tests { let _ = env_logger::try_init(); let client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = TestPool(BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), diff --git a/client/rpc/src/author/tests.rs b/client/rpc/src/author/tests.rs index 37edcbe263283..7736ea0c86476 100644 --- a/client/rpc/src/author/tests.rs +++ b/client/rpc/src/author/tests.rs @@ -61,7 +61,7 @@ impl Default for TestSetup { let client_builder = substrate_test_runtime_client::TestClientBuilder::new(); let client = Arc::new(client_builder.set_keystore(keystore.clone()).build()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 53a63b449c87e..4b2bd200a842e 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -22,6 +22,11 @@ #![warn(missing_docs)] +use futures::{compat::Future01CompatExt, FutureExt}; +use rpc::futures::future::{Executor, ExecuteError, Future}; +use sp_core::traits::SpawnNamed; +use std::sync::Arc; + mod metadata; pub use sc_rpc_api::DenyUnsafe; @@ -35,3 +40,24 @@ pub mod state; pub mod system; #[cfg(test)] mod testing; + +/// Task executor that is being used by RPC subscriptions. +#[derive(Clone)] +pub struct SubscriptionTaskExecutor(Arc); + +impl SubscriptionTaskExecutor { + /// Create a new `Self` with the given spawner. + pub fn new(spawn: impl SpawnNamed + 'static) -> Self { + Self(Arc::new(spawn)) + } +} + +impl Executor + Send>> for SubscriptionTaskExecutor { + fn execute( + &self, + future: Box + Send>, + ) -> Result<(), ExecuteError + Send>>> { + self.0.spawn("substrate_rpc_subscription", future.compat().map(drop).boxed()); + Ok(()) + } +} diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index c71746f48a890..a262e6488bb23 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -24,8 +24,7 @@ use crate::{ config::{Configuration, KeystoreConfig, PrometheusConfig, OffchainWorkerConfig}, }; use sc_client_api::{ - light::RemoteBlockchain, ForkBlocks, BadBlocks, CloneableSpawn, UsageProvider, - ExecutorProvider, + light::RemoteBlockchain, ForkBlocks, BadBlocks, UsageProvider, ExecutorProvider, }; use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender, TracingUnboundedReceiver}; use sc_chain_spec::get_extension; @@ -55,7 +54,7 @@ use sc_telemetry::{telemetry, SUBSTRATE_INFO}; use sp_transaction_pool::MaintainedTransactionPool; use prometheus_endpoint::Registry; use sc_client_db::{Backend, DatabaseSettings}; -use sp_core::traits::CodeExecutor; +use sp_core::traits::{CodeExecutor, SpawnNamed}; use sp_runtime::BuildStorage; use sc_client_api::{ BlockBackend, BlockchainEvents, @@ -334,7 +333,7 @@ pub fn new_client( fork_blocks: ForkBlocks, bad_blocks: BadBlocks, execution_extensions: ExecutionExtensions, - spawn_handle: Box, + spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, ) -> Result<( @@ -750,7 +749,8 @@ fn gen_handler( chain_type: config.chain_spec.chain_type(), }; - let subscriptions = SubscriptionManager::new(Arc::new(spawn_handle)); + let task_executor = sc_rpc::SubscriptionTaskExecutor::new(spawn_handle); + let subscriptions = SubscriptionManager::new(Arc::new(task_executor)); let (chain, state, child_state) = if let (Some(remote_blockchain), Some(on_demand)) = (remote_blockchain, on_demand) { diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 049bd888b13c7..1919c76ff489b 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -27,9 +27,12 @@ use sp_state_machine::{ }; use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion}; use sp_externalities::Extensions; -use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor, offchain::storage::OffchainOverlayedChanges}; +use sp_core::{ + NativeOrEncoded, NeverNativeValue, traits::{CodeExecutor, SpawnNamed}, + offchain::storage::OffchainOverlayedChanges, +}; use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; -use sc_client_api::{backend, call_executor::CallExecutor, CloneableSpawn}; +use sc_client_api::{backend, call_executor::CallExecutor}; use super::client::ClientConfig; /// Call executor that executes methods locally, querying all required @@ -37,7 +40,7 @@ use super::client::ClientConfig; pub struct LocalCallExecutor { backend: Arc, executor: E, - spawn_handle: Box, + spawn_handle: Box, client_config: ClientConfig, } @@ -46,7 +49,7 @@ impl LocalCallExecutor { pub fn new( backend: Arc, executor: E, - spawn_handle: Box, + spawn_handle: Box, client_config: ClientConfig, ) -> Self { LocalCallExecutor { @@ -242,7 +245,7 @@ where method: &str, call_data: &[u8] ) -> Result<(Vec, StorageProof), sp_blockchain::Error> { - sp_state_machine::prove_execution_on_trie_backend::<_, _, NumberFor, _>( + sp_state_machine::prove_execution_on_trie_backend::<_, _, NumberFor, _, _>( trie_state, overlay, &self.executor, diff --git a/client/service/src/client/client.rs b/client/service/src/client/client.rs index 2f101465d516f..b152415a4a89d 100644 --- a/client/service/src/client/client.rs +++ b/client/service/src/client/client.rs @@ -92,8 +92,8 @@ use rand::Rng; #[cfg(feature="test-helpers")] use { - sp_core::traits::CodeExecutor, - sc_client_api::{CloneableSpawn, in_mem}, + sp_core::traits::{CodeExecutor, SpawnNamed}, + sc_client_api::in_mem, sc_executor::RuntimeInfo, super::call_executor::LocalCallExecutor, }; @@ -149,7 +149,7 @@ pub fn new_in_mem( genesis_storage: &S, keystore: Option, prometheus_registry: Option, - spawn_handle: Box, + spawn_handle: Box, config: ClientConfig, ) -> sp_blockchain::Result, @@ -189,7 +189,7 @@ pub fn new_with_backend( executor: E, build_genesis_storage: &S, keystore: Option, - spawn_handle: Box, + spawn_handle: Box, prometheus_registry: Option, config: ClientConfig, ) -> sp_blockchain::Result, Block, RA>> diff --git a/client/service/src/client/light.rs b/client/service/src/client/light.rs index 8b9b65fc2fadd..e8e1286eccdb0 100644 --- a/client/service/src/client/light.rs +++ b/client/service/src/client/light.rs @@ -21,17 +21,14 @@ use std::sync::Arc; use sc_executor::RuntimeInfo; -use sp_core::traits::CodeExecutor; +use sp_core::traits::{CodeExecutor, SpawnNamed}; use sp_runtime::BuildStorage; use sp_runtime::traits::{Block as BlockT, HashFor}; use sp_blockchain::Result as ClientResult; use prometheus_endpoint::Registry; -use super::call_executor::LocalCallExecutor; -use super::client::{Client,ClientConfig}; -use sc_client_api::{ - light::Storage as BlockchainStorage, CloneableSpawn, -}; +use super::{call_executor::LocalCallExecutor, client::{Client, ClientConfig}}; +use sc_client_api::light::Storage as BlockchainStorage; use sc_light::{Backend, GenesisCallExecutor}; @@ -40,7 +37,7 @@ pub fn new_light( backend: Arc>>, genesis_storage: &dyn BuildStorage, code_executor: E, - spawn_handle: Box, + spawn_handle: Box, prometheus_registry: Option, ) -> ClientResult< Client< diff --git a/client/service/src/lib.rs b/client/service/src/lib.rs index 1eef6493e775e..ff7573f5fac30 100644 --- a/client/service/src/lib.rs +++ b/client/service/src/lib.rs @@ -556,7 +556,7 @@ mod tests { // given let (client, longest_chain) = TestClientBuilder::new().build_with_longest_chain(); let client = Arc::new(client); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), diff --git a/client/service/src/task_manager/mod.rs b/client/service/src/task_manager/mod.rs index bd4b2cfde73ec..e0e8699ce1d37 100644 --- a/client/service/src/task_manager/mod.rs +++ b/client/service/src/task_manager/mod.rs @@ -19,8 +19,6 @@ use log::{debug, error}; use futures::{ Future, FutureExt, StreamExt, future::{select, Either, BoxFuture}, - compat::*, - task::{Spawn, FutureObj, SpawnError}, sink::SinkExt, }; use prometheus_endpoint::{ @@ -28,7 +26,6 @@ use prometheus_endpoint::{ PrometheusError, CounterVec, HistogramOpts, HistogramVec, Opts, Registry, U64 }; -use sc_client_api::CloneableSpawn; use sp_utils::mpsc::{TracingUnboundedSender, TracingUnboundedReceiver, tracing_unbounded}; use crate::{config::{TaskExecutor, TaskType, JoinFuture}, Error}; @@ -132,14 +129,6 @@ impl SpawnTaskHandle { } } -impl Spawn for SpawnTaskHandle { - fn spawn_obj(&self, future: FutureObj<'static, ()>) - -> Result<(), SpawnError> { - self.spawn("unnamed", future); - Ok(()) - } -} - impl sp_core::traits::SpawnNamed for SpawnTaskHandle { fn spawn_blocking(&self, name: &'static str, future: BoxFuture<'static, ()>) { self.spawn_blocking(name, future); @@ -150,21 +139,6 @@ impl sp_core::traits::SpawnNamed 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 { - fn execute(&self, future: Boxed01Future01) -> Result<(), futures01::future::ExecuteError>{ - self.spawn("unnamed", future.compat().map(drop)); - Ok(()) - } -} - /// A wrapper over `SpawnTaskHandle` that will notify a receiver whenever any /// task spawned through it fails. The service should be on the receiver side /// and will shut itself down whenever it receives any message, i.e. an diff --git a/client/service/test/src/client/light.rs b/client/service/test/src/client/light.rs index e72c290d43bbe..031c234c1ab35 100644 --- a/client/service/test/src/client/light.rs +++ b/client/service/test/src/client/light.rs @@ -37,9 +37,9 @@ use substrate_test_runtime_client::{ runtime::{Hash, Block, Header}, TestClient, ClientBlockImportExt, }; use sp_api::{InitializeBlock, StorageTransactionCache, ProofRecorder, OffchainOverlayedChanges}; -use sp_consensus::{BlockOrigin}; +use sp_consensus::BlockOrigin; use sc_executor::{NativeExecutor, WasmExecutionMethod, RuntimeVersion, NativeVersion}; -use sp_core::{H256, tasks::executor as tasks_executor, NativeOrEncoded}; +use sp_core::{H256, NativeOrEncoded, testing::TaskExecutor}; use sc_client_api::{ blockchain::Info, backend::NewBlockState, Backend as ClientBackend, ProofProvider, in_mem::{Backend as InMemBackend, Blockchain as InMemoryBlockchain}, @@ -317,7 +317,7 @@ fn execution_proof_is_generated_and_checked() { // check remote execution proof locally let local_result = check_execution_proof::<_, _, BlakeTwo256>( &local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), &RemoteCallRequest { block: substrate_test_runtime_client::runtime::Hash::default(), header: remote_header, @@ -345,7 +345,7 @@ fn execution_proof_is_generated_and_checked() { // check remote execution proof locally let execution_result = check_execution_proof_with_make_header::<_, _, BlakeTwo256, _>( &local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), &RemoteCallRequest { block: substrate_test_runtime_client::runtime::Hash::default(), header: remote_header, @@ -479,7 +479,7 @@ fn prepare_for_read_proof_check() -> (TestChecker, Header, StorageProof, u32) { let local_checker = LightDataChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); (local_checker, remote_block_header, remote_read_proof, heap_pages) } @@ -527,7 +527,7 @@ fn prepare_for_read_child_proof_check() -> (TestChecker, Header, StorageProof, V let local_checker = LightDataChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); (local_checker, remote_block_header, remote_read_proof, child_value) } @@ -558,7 +558,7 @@ fn prepare_for_header_proof_check(insert_cht: bool) -> (TestChecker, Hash, Heade let local_checker = LightDataChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); (local_checker, local_cht_root, remote_block_header, remote_header_proof) } @@ -642,7 +642,7 @@ fn changes_proof_is_generated_and_checked_when_headers_are_not_pruned() { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); let local_checker = &local_checker as &dyn FetchChecker; let max = remote_client.chain_info().best_number; @@ -717,7 +717,7 @@ fn changes_proof_is_generated_and_checked_when_headers_are_pruned() { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); // check proof on local client @@ -752,7 +752,7 @@ fn check_changes_proof_fails_if_proof_is_wrong() { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); let local_checker = &local_checker as &dyn FetchChecker; let max = remote_client.chain_info().best_number; @@ -840,7 +840,7 @@ fn check_changes_tries_proof_fails_if_proof_is_wrong() { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, remote_proof.roots_proof.clone()).is_err()); @@ -851,7 +851,7 @@ fn check_changes_tries_proof_fails_if_proof_is_wrong() { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(local_storage)), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); let result = local_checker.check_changes_tries_proof( 4, &remote_proof.roots, StorageProof::empty() @@ -869,7 +869,7 @@ fn check_body_proof_faulty() { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); let body_request = RemoteBodyRequest { @@ -893,7 +893,7 @@ fn check_body_proof_of_same_data_should_succeed() { let local_checker = TestChecker::new( Arc::new(DummyBlockchain::new(DummyStorage::new())), local_executor(), - tasks_executor(), + Box::new(TaskExecutor::new()), ); let body_request = RemoteBodyRequest { diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 2124f0ced4122..8d073df272fd9 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -40,8 +40,7 @@ use sp_runtime::traits::{ use substrate_test_runtime::TestAPI; use sp_state_machine::backend::Backend as _; use sp_api::{ProvideRuntimeApi, OffchainOverlayedChanges}; -use sp_core::tasks::executor as tasks_executor; -use sp_core::{H256, ChangesTrieConfiguration, blake2_256}; +use sp_core::{H256, ChangesTrieConfiguration, blake2_256, testing::TaskExecutor}; use std::collections::{HashMap, HashSet}; use std::sync::Arc; use sp_consensus::{ @@ -165,6 +164,7 @@ fn construct_block( let mut offchain_overlay = OffchainOverlayedChanges::default(); let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend); let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend"); + let task_executor = Box::new(TaskExecutor::new()); StateMachine::new( backend, @@ -176,7 +176,7 @@ fn construct_block( &header.encode(), Default::default(), &runtime_code, - tasks_executor(), + task_executor.clone() as Box<_>, ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -192,7 +192,7 @@ fn construct_block( &tx.encode(), Default::default(), &runtime_code, - tasks_executor(), + task_executor.clone() as Box<_>, ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -208,7 +208,7 @@ fn construct_block( &[], Default::default(), &runtime_code, - tasks_executor(), + task_executor.clone() as Box<_>, ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -262,7 +262,7 @@ fn construct_genesis_should_work_with_native() { &b1data, Default::default(), &runtime_code, - tasks_executor(), + TaskExecutor::new(), ).execute( ExecutionStrategy::NativeElseWasm, ).unwrap(); @@ -298,7 +298,7 @@ fn construct_genesis_should_work_with_wasm() { &b1data, Default::default(), &runtime_code, - tasks_executor(), + TaskExecutor::new(), ).execute( ExecutionStrategy::AlwaysWasm, ).unwrap(); @@ -334,7 +334,7 @@ fn construct_genesis_with_bad_transaction_should_panic() { &b1data, Default::default(), &runtime_code, - tasks_executor(), + TaskExecutor::new(), ).execute( ExecutionStrategy::NativeElseWasm, ); @@ -1743,7 +1743,7 @@ fn cleans_up_closed_notification_sinks_on_block_import() { &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), None, None, - sp_core::tasks::executor(), + Box::new(TaskExecutor::new()), Default::default(), ) .unwrap(); diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index 6717ab7a3bb92..d72872959cefa 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -197,11 +197,11 @@ fn record_proof_works() { None, 8, ); - execution_proof_check_on_trie_backend::<_, u64, _>( + execution_proof_check_on_trie_backend::<_, u64, _, _>( &backend, &mut overlay, &executor, - sp_core::tasks::executor(), + sp_core::testing::TaskExecutor::new(), "Core_execute_block", &block.encode(), &runtime_code, diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index fcf614fd63c5e..6787efbd845da 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -39,6 +39,7 @@ sp-externalities = { version = "0.8.0-rc5", optional = true, path = "../external sp-storage = { version = "2.0.0-rc5", default-features = false, path = "../storage" } parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } futures = { version = "0.3.1", optional = true } +dyn-clonable = { version = "0.9.0", optional = true } # full crypto ed25519-dalek = { version = "1.0.0-pre.4", default-features = false, features = ["u64_backend", "alloc"], optional = true } @@ -111,6 +112,7 @@ std = [ "futures", "futures/thread-pool", "libsecp256k1/std", + "dyn-clonable", ] # This feature enables all crypto primitives for `no_std` builds like microcontrollers diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 27f59f4fba7f3..7e52efd52e9f6 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -72,8 +72,6 @@ mod changes_trie; pub mod traits; pub mod testing; #[cfg(feature = "std")] -pub mod tasks; -#[cfg(feature = "std")] pub mod vrf; pub use self::hash::{H160, H256, H512, convert_hash}; diff --git a/primitives/core/src/tasks.rs b/primitives/core/src/tasks.rs deleted file mode 100644 index 731e51d2470c0..0000000000000 --- a/primitives/core/src/tasks.rs +++ /dev/null @@ -1,57 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2020 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! 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()) -} diff --git a/primitives/core/src/testing.rs b/primitives/core/src/testing.rs index e512d3a39e212..5c4af736c4f53 100644 --- a/primitives/core/src/testing.rs +++ b/primitives/core/src/testing.rs @@ -359,16 +359,16 @@ macro_rules! wasm_export_functions { }; } -/// An executor that supports spawning blocking futures in tests. +/// A task executor that can be used in tests. /// /// Internally this just wraps a `ThreadPool` with a pool size of `8`. This /// should ensure that we have enough threads in tests for spawning blocking futures. #[cfg(feature = "std")] #[derive(Clone)] -pub struct SpawnBlockingExecutor(futures::executor::ThreadPool); +pub struct TaskExecutor(futures::executor::ThreadPool); #[cfg(feature = "std")] -impl SpawnBlockingExecutor { +impl TaskExecutor { /// Create a new instance of `Self`. pub fn new() -> Self { let mut builder = futures::executor::ThreadPoolBuilder::new(); @@ -377,7 +377,7 @@ impl SpawnBlockingExecutor { } #[cfg(feature = "std")] -impl crate::traits::SpawnNamed for SpawnBlockingExecutor { +impl crate::traits::SpawnNamed for TaskExecutor { fn spawn_blocking(&self, _: &'static str, future: futures::future::BoxFuture<'static, ()>) { self.0.spawn_ok(future); } diff --git a/primitives/core/src/traits.rs b/primitives/core/src/traits.rs index 4481145818f26..ab409b60d9c70 100644 --- a/primitives/core/src/traits.rs +++ b/primitives/core/src/traits.rs @@ -352,26 +352,21 @@ impl CallInWasmExt { } } -/// 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); + pub struct TaskExecutorExt(Box); } impl TaskExecutorExt { /// New instance of task executor extension. - pub fn new(spawn_handle: Box) -> Self { - Self(spawn_handle) + pub fn new(spawn_handle: impl SpawnNamed + Send + 'static) -> Self { + Self(Box::new(spawn_handle)) } } -/// Something that can spawn futures (blocking and non-blocking) with am assigned name. -pub trait SpawnNamed { +/// Something that can spawn futures (blocking and non-blocking) with an assigned name. +#[dyn_clonable::clonable] +pub trait SpawnNamed: Clone + Send + Sync { /// Spawn the given blocking future. /// /// The given `name` is used to identify the future in tracing. @@ -381,3 +376,13 @@ pub trait SpawnNamed { /// The given `name` is used to identify the future in tracing. fn spawn(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>); } + +impl SpawnNamed for Box { + fn spawn_blocking(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>) { + (**self).spawn_blocking(name, future) + } + + fn spawn(&self, name: &'static str, future: futures::future::BoxFuture<'static, ()>) { + (**self).spawn(name, future) + } +} diff --git a/primitives/externalities/src/extensions.rs b/primitives/externalities/src/extensions.rs index c75877e67db96..08d81e46c88fc 100644 --- a/primitives/externalities/src/extensions.rs +++ b/primitives/externalities/src/extensions.rs @@ -108,9 +108,9 @@ pub struct Extensions { } impl std::fmt::Debug for Extensions { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Extensions: ({})", self.extensions.len()) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Extensions: ({})", self.extensions.len()) + } } impl Extensions { diff --git a/primitives/io/src/batch_verifier.rs b/primitives/io/src/batch_verifier.rs index 642e77504d00f..39229b1200b91 100644 --- a/primitives/io/src/batch_verifier.rs +++ b/primitives/io/src/batch_verifier.rs @@ -17,9 +17,9 @@ //! Batch/parallel verification. -use sp_core::{ed25519, sr25519, ecdsa, crypto::Pair, traits::CloneableSpawn}; +use sp_core::{ed25519, sr25519, ecdsa, crypto::Pair, traits::SpawnNamed}; use std::sync::{Arc, atomic::{AtomicBool, Ordering as AtomicOrdering}}; -use futures::{future::FutureExt, task::FutureObj, channel::oneshot}; +use futures::{future::FutureExt, channel::oneshot}; #[derive(Debug, Clone)] struct Sr25519BatchItem { @@ -35,14 +35,14 @@ struct Sr25519BatchItem { /// call `verify_and_clear to get a result. After that, batch verifier is ready for the /// next batching job. pub struct BatchVerifier { - scheduler: Box, + scheduler: Box, sr25519_items: Vec, invalid: Arc, pending_tasks: Vec>, } impl BatchVerifier { - pub fn new(scheduler: Box) -> Self { + pub fn new(scheduler: Box) -> Self { BatchVerifier { scheduler, sr25519_items: Default::default(), @@ -56,7 +56,9 @@ impl BatchVerifier { /// Returns `false` if there was already an invalid verification or if /// the verification could not be spawned. fn spawn_verification_task( - &mut self, f: impl FnOnce() -> bool + Send + 'static, + &mut self, + f: impl FnOnce() -> bool + Send + 'static, + name: &'static str, ) -> bool { // there is already invalid transaction encountered if self.invalid.load(AtomicOrdering::Relaxed) { return false; } @@ -65,7 +67,8 @@ impl BatchVerifier { let (sender, receiver) = oneshot::channel(); self.pending_tasks.push(receiver); - self.scheduler.spawn_obj(FutureObj::new( + self.scheduler.spawn( + name, async move { if !f() { invalid_clone.store(true, AtomicOrdering::Relaxed); @@ -75,15 +78,10 @@ impl BatchVerifier { log::warn!("Verification halted while result was pending"); invalid_clone.store(true, AtomicOrdering::Relaxed); } - }.boxed() - )) - .map_err(|_| { - log::debug!( - target: "runtime", - "Batch-verification returns false because failed to spawn background task.", - ) - }) - .is_ok() + }.boxed(), + ); + + true } /// Push ed25519 signature to verify. @@ -96,7 +94,10 @@ impl BatchVerifier { pub_key: ed25519::Public, message: Vec, ) -> bool { - self.spawn_verification_task(move || ed25519::Pair::verify(&signature, &message, &pub_key)) + self.spawn_verification_task( + move || ed25519::Pair::verify(&signature, &message, &pub_key), + "substrate_ed25519_verify", + ) } /// Push sr25519 signature to verify. @@ -114,7 +115,10 @@ impl BatchVerifier { if self.sr25519_items.len() >= 128 { let items = std::mem::take(&mut self.sr25519_items); - self.spawn_verification_task(move || Self::verify_sr25519_batch(items)) + self.spawn_verification_task( + move || Self::verify_sr25519_batch(items), + "substrate_sr25519_verify", + ) } else { true } @@ -130,7 +134,10 @@ impl BatchVerifier { pub_key: ecdsa::Public, message: Vec, ) -> bool { - self.spawn_verification_task(move || ecdsa::Pair::verify(&signature, &message, &pub_key)) + self.spawn_verification_task( + move || ecdsa::Pair::verify(&signature, &message, &pub_key), + "substrate_ecdsa_verify", + ) } fn verify_sr25519_batch(items: Vec) -> bool { @@ -161,23 +168,24 @@ impl BatchVerifier { if pending.len() > 0 { let (sender, receiver) = std::sync::mpsc::channel(); - if self.scheduler.spawn_obj(FutureObj::new(async move { - futures::future::join_all(pending).await; - sender.send(()) - .expect("Channel never panics if receiver is live. \ - Receiver is always live until received this data; qed. "); - }.boxed())).is_err() { - log::debug!( + self.scheduler.spawn( + "substrate_batch_verify_join", + async move { + futures::future::join_all(pending).await; + sender.send(()) + .expect("Channel never panics if receiver is live. \ + Receiver is always live until received this data; qed. "); + }.boxed(), + ); + + if receiver.recv().is_err() { + log::warn!( target: "runtime", - "Batch-verification returns false because failed to spawn background task.", + "Haven't received async result from verification task. Returning false.", ); return false; } - if receiver.recv().is_err() { - log::warn!(target: "runtime", "Haven't received async result from verification task. Returning false."); - return false; - } } log::trace!( diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 6c99a5c75195b..59d1c4f37ef27 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -1206,9 +1206,10 @@ pub type SubstrateHostFunctions = ( #[cfg(test)] mod tests { use super::*; - use sp_core::map; use sp_state_machine::BasicExternalities; - use sp_core::storage::Storage; + use sp_core::{ + storage::Storage, map, traits::TaskExecutorExt, testing::TaskExecutor, + }; use std::any::TypeId; #[test] @@ -1274,7 +1275,9 @@ mod tests { #[test] fn batch_verify_start_finish_works() { - let mut ext = BasicExternalities::with_tasks_executor(); + let mut ext = BasicExternalities::default(); + ext.register_extension(TaskExecutorExt::new(TaskExecutor::new())); + ext.execute_with(|| { crypto::start_batch_verify(); }); @@ -1290,7 +1293,8 @@ mod tests { #[test] fn long_sr25519_batching() { - let mut ext = BasicExternalities::with_tasks_executor(); + let mut ext = BasicExternalities::default(); + ext.register_extension(TaskExecutorExt::new(TaskExecutor::new())); ext.execute_with(|| { let pair = sr25519::Pair::generate_with_phrase(None).0; crypto::start_batch_verify(); @@ -1320,7 +1324,8 @@ mod tests { #[test] fn batching_works() { - let mut ext = BasicExternalities::with_tasks_executor(); + let mut ext = BasicExternalities::default(); + ext.register_extension(TaskExecutorExt::new(TaskExecutor::new())); ext.execute_with(|| { // invalid ed25519 signature crypto::start_batch_verify(); diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 02031a2df9a55..5d65c13c664b7 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -871,7 +871,11 @@ mod tests { #[test] #[should_panic(expected = "Signature verification has not been called")] fn batching_still_finishes_when_not_called_directly() { - let mut ext = sp_state_machine::BasicExternalities::with_tasks_executor(); + let mut ext = sp_state_machine::BasicExternalities::default(); + ext.register_extension( + sp_core::traits::TaskExecutorExt::new(sp_core::testing::TaskExecutor::new()), + ); + ext.execute_with(|| { let _batching = SignatureBatching::start(); sp_io::crypto::sr25519_verify( diff --git a/primitives/state-machine/src/basic.rs b/primitives/state-machine/src/basic.rs index 6f1d2a4b5ad91..3ddf79dbd9127 100644 --- a/primitives/state-machine/src/basic.rs +++ b/primitives/state-machine/src/basic.rs @@ -33,7 +33,7 @@ use sp_core::{ }; use log::warn; use codec::Encode; -use sp_externalities::Extensions; +use sp_externalities::{Extensions, Extension}; /// Simple Map-based Externalities impl. #[derive(Debug)] @@ -53,17 +53,6 @@ impl BasicExternalities { Self::new(Storage::default()) } - /// New basic extternalities with tasks executor. - pub fn with_tasks_executor() -> Self { - let mut extensions = Extensions::default(); - extensions.register(sp_core::traits::TaskExecutorExt(sp_core::tasks::executor())); - - Self { - inner: Storage::default(), - extensions, - } - } - /// Insert key/value pub fn insert(&mut self, k: StorageKey, v: StorageValue) -> Option { self.inner.top.insert(k, v) @@ -107,6 +96,11 @@ impl BasicExternalities { pub fn extensions(&mut self) -> &mut Extensions { &mut self.extensions } + + /// Register an extension. + pub fn register_extension(&mut self, ext: impl Extension) { + self.extensions.register(ext); + } } impl PartialEq for BasicExternalities { diff --git a/primitives/state-machine/src/lib.rs b/primitives/state-machine/src/lib.rs index e5e48bc47cd48..ee0980f59b926 100644 --- a/primitives/state-machine/src/lib.rs +++ b/primitives/state-machine/src/lib.rs @@ -26,7 +26,7 @@ use codec::{Decode, Encode, Codec}; use sp_core::{ offchain::storage::OffchainOverlayedChanges, storage::ChildInfo, NativeOrEncoded, NeverNativeValue, hexdisplay::HexDisplay, - traits::{CodeExecutor, CallInWasmExt, RuntimeCode}, + traits::{CodeExecutor, CallInWasmExt, RuntimeCode, SpawnNamed}, }; use sp_externalities::Extensions; @@ -77,7 +77,6 @@ pub use trie_backend::TrieBackend; pub use error::{Error, ExecutionError}; pub use in_memory_backend::new_in_mem; pub use stats::{UsageInfo, UsageUnit, StateMachineStats}; -pub use sp_core::traits::CloneableSpawn; const PROOF_CLOSE_TRANSACTION: &str = "\ Closing a transaction that was started in this function. Client initiated transactions @@ -233,7 +232,7 @@ 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, + spawn_handle: impl SpawnNamed + Send + 'static, ) -> Self { extensions.register(CallInWasmExt::new(exec.clone())); extensions.register(sp_core::traits::TaskExecutorExt::new(spawn_handle)); @@ -463,11 +462,11 @@ impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> where } /// Prove execution using the given state backend, overlayed changes, and call executor. -pub fn prove_execution( +pub fn prove_execution( mut backend: B, overlay: &mut OverlayedChanges, exec: &Exec, - spawn_handle: Box, + spawn_handle: Spawn, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -478,10 +477,11 @@ where H::Out: Ord + 'static + codec::Codec, Exec: CodeExecutor + Clone + 'static, N: crate::changes_trie::BlockNumber, + Spawn: SpawnNamed + Send + 'static, { let trie_backend = backend.as_trie_backend() .ok_or_else(|| Box::new(ExecutionError::UnableToGenerateProof) as Box)?; - prove_execution_on_trie_backend::<_, _, N, _>( + prove_execution_on_trie_backend::<_, _, N, _, _>( trie_backend, overlay, exec, @@ -501,11 +501,11 @@ where /// /// Note: changes to code will be in place if this call is made again. For running partial /// blocks (e.g. a transaction at a time), ensure a different method is used. -pub fn prove_execution_on_trie_backend( +pub fn prove_execution_on_trie_backend( trie_backend: &TrieBackend, overlay: &mut OverlayedChanges, exec: &Exec, - spawn_handle: Box, + spawn_handle: Spawn, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -516,6 +516,7 @@ where H::Out: Ord + 'static + codec::Codec, Exec: CodeExecutor + 'static + Clone, N: crate::changes_trie::BlockNumber, + Spawn: SpawnNamed + Send + 'static, { let mut offchain_overlay = OffchainOverlayedChanges::default(); let proving_backend = proving_backend::ProvingBackend::new(trie_backend); @@ -541,12 +542,12 @@ where } /// Check execution proof, generated by `prove_execution` call. -pub fn execution_proof_check( +pub fn execution_proof_check( root: H::Out, proof: StorageProof, overlay: &mut OverlayedChanges, exec: &Exec, - spawn_handle: Box, + spawn_handle: Spawn, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -556,9 +557,10 @@ where Exec: CodeExecutor + Clone + 'static, H::Out: Ord + 'static + codec::Codec, N: crate::changes_trie::BlockNumber, + Spawn: SpawnNamed + Send + 'static, { let trie_backend = create_proof_check_backend::(root.into(), proof)?; - execution_proof_check_on_trie_backend::<_, N, _>( + execution_proof_check_on_trie_backend::<_, N, _, _>( &trie_backend, overlay, exec, @@ -570,11 +572,11 @@ where } /// Check execution proof on proving backend, generated by `prove_execution` call. -pub fn execution_proof_check_on_trie_backend( +pub fn execution_proof_check_on_trie_backend( trie_backend: &TrieBackend, H>, overlay: &mut OverlayedChanges, exec: &Exec, - spawn_handle: Box, + spawn_handle: Spawn, method: &str, call_data: &[u8], runtime_code: &RuntimeCode, @@ -584,6 +586,7 @@ where H::Out: Ord + 'static + codec::Codec, Exec: CodeExecutor + Clone + 'static, N: crate::changes_trie::BlockNumber, + Spawn: SpawnNamed + Send + 'static, { let mut offchain_overlay = OffchainOverlayedChanges::default(); let mut sm = StateMachine::<_, H, N, Exec>::new( @@ -765,7 +768,9 @@ mod tests { use super::*; use super::ext::Ext; use super::changes_trie::Configuration as ChangesTrieConfig; - use sp_core::{map, traits::{Externalities, RuntimeCode}}; + use sp_core::{ + map, traits::{Externalities, RuntimeCode}, testing::TaskExecutor, + }; use sp_runtime::traits::BlakeTwo256; #[derive(Clone)] @@ -859,7 +864,7 @@ mod tests { &[], Default::default(), &wasm_code, - sp_core::tasks::executor(), + TaskExecutor::new(), ); assert_eq!( @@ -891,7 +896,7 @@ mod tests { &[], Default::default(), &wasm_code, - sp_core::tasks::executor(), + TaskExecutor::new(), ); assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap(), vec![66]); @@ -920,7 +925,7 @@ mod tests { &[], Default::default(), &wasm_code, - sp_core::tasks::executor(), + TaskExecutor::new(), ); assert!( @@ -947,23 +952,23 @@ mod tests { // fetch execution proof from 'remote' full node let remote_backend = trie_backend::tests::test_trie(); let remote_root = remote_backend.storage_root(std::iter::empty()).0; - let (remote_result, remote_proof) = prove_execution::<_, _, u64, _>( + let (remote_result, remote_proof) = prove_execution::<_, _, u64, _, _>( remote_backend, &mut Default::default(), &executor, - sp_core::tasks::executor(), + TaskExecutor::new(), "test", &[], &RuntimeCode::empty(), ).unwrap(); // check proof locally - let local_result = execution_proof_check::( + let local_result = execution_proof_check::( remote_root, remote_proof, &mut Default::default(), &executor, - sp_core::tasks::executor(), + TaskExecutor::new(), "test", &[], &RuntimeCode::empty(), diff --git a/primitives/state-machine/src/testing.rs b/primitives/state-machine/src/testing.rs index cccb044f7e33d..be7dc6df9de9a 100644 --- a/primitives/state-machine/src/testing.rs +++ b/primitives/state-machine/src/testing.rs @@ -39,6 +39,8 @@ use sp_core::{ well_known_keys::{CHANGES_TRIE_CONFIG, CODE, HEAP_PAGES, is_child_storage_key}, Storage, }, + traits::TaskExecutorExt, + testing::TaskExecutor, }; use codec::Encode; use sp_externalities::{Extensions, Extension}; @@ -109,8 +111,7 @@ impl TestExternalities let offchain_overlay = OffchainOverlayedChanges::enabled(); let mut extensions = Extensions::default(); - extensions.register(sp_core::traits::TaskExecutorExt(sp_core::tasks::executor())); - + extensions.register(TaskExecutorExt::new(TaskExecutor::new())); let offchain_db = TestPersistentOffchainDB::new(); diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index fd5b0e29192ae..060d487967583 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -23,7 +23,7 @@ pub mod client_ext; pub use sc_client_api::{ execution_extensions::{ExecutionStrategies, ExecutionExtensions}, - ForkBlocks, BadBlocks, CloneableSpawn, + ForkBlocks, BadBlocks, }; 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, tasks::executor as tasks_executor}; +pub use sp_core::traits::BareCryptoStorePtr; pub use sp_runtime::{Storage, StorageChild}; pub use sp_state_machine::ExecutionStrategy; pub use sc_service::{RpcHandlers, RpcSession, client}; @@ -254,7 +254,12 @@ impl TestClientBuilder< let executor = executor.into().unwrap_or_else(|| NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8) ); - let executor = LocalCallExecutor::new(self.backend.clone(), executor, tasks_executor(), Default::default()); + let executor = LocalCallExecutor::new( + self.backend.clone(), + executor, + Box::new(sp_core::testing::TaskExecutor::new()), + Default::default(), + ); self.build_with_executor(executor) } diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index 97cf13ed2ae56..5b343f7748ead 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -350,7 +350,12 @@ pub fn new_light() -> ( let blockchain = Arc::new(sc_light::Blockchain::new(storage)); let backend = Arc::new(LightBackend::new(blockchain)); let executor = new_native_executor(); - let local_call_executor = client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor(), Default::default()); + let local_call_executor = client::LocalCallExecutor::new( + backend.clone(), + executor, + Box::new(sp_core::testing::TaskExecutor::new()), + Default::default(), + ); let call_executor = LightExecutor::new( backend.clone(), local_call_executor, diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index 550d2c12c83e5..7df23f8dbfc9a 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -24,11 +24,8 @@ use sc_executor::NativeExecutor; use sp_state_machine::StateMachine; use sp_externalities::Extensions; use sc_service::{Configuration, NativeExecutionDispatch}; -use sp_runtime::{ - traits::{Block as BlockT, Header as HeaderT, NumberFor}, -}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use sp_core::{ - tasks, testing::KeyStore, traits::KeystoreExt, offchain::{OffchainExt, testing::TestOffchainExt}, @@ -81,7 +78,7 @@ impl BenchmarkCmd { ).encode(), extensions, &sp_state_machine::backend::BackendRuntimeCode::new(&state).runtime_code()?, - tasks::executor(), + sp_core::testing::TaskExecutor::new(), ) .execute(strategy.into()) .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; diff --git a/utils/frame/rpc/system/src/lib.rs b/utils/frame/rpc/system/src/lib.rs index 320423623668a..99e38aaac0308 100644 --- a/utils/frame/rpc/system/src/lib.rs +++ b/utils/frame/rpc/system/src/lib.rs @@ -298,7 +298,7 @@ mod tests { // given let client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), @@ -338,7 +338,7 @@ mod tests { // given let client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), @@ -362,7 +362,7 @@ mod tests { // given let client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)), @@ -395,7 +395,7 @@ mod tests { // given let client = Arc::new(substrate_test_runtime_client::new()); - let spawner = sp_core::testing::SpawnBlockingExecutor::new(); + let spawner = sp_core::testing::TaskExecutor::new(); let pool = BasicPool::new_full( Default::default(), Arc::new(FullChainApi::new(client.clone(), None)),