create parallel tasks extension (#5249)

This commit is contained in:
Nikolay Volf
2020-03-16 08:30:39 -07:00
committed by GitHub
parent 418b7b8bc2
commit 372745705d
25 changed files with 189 additions and 26 deletions
+2
View File
@@ -1479,6 +1479,7 @@ dependencies = [
"sc-client-db", "sc-client-db",
"sc-executor", "sc-executor",
"sc-service", "sc-service",
"sp-core",
"sp-runtime", "sp-runtime",
"sp-state-machine", "sp-state-machine",
"structopt", "structopt",
@@ -7158,6 +7159,7 @@ dependencies = [
"byteorder 1.3.4", "byteorder 1.3.4",
"criterion 0.2.11", "criterion 0.2.11",
"ed25519-dalek", "ed25519-dalek",
"futures 0.3.4",
"hash-db", "hash-db",
"hash256-std-hasher", "hash256-std-hasher",
"hex", "hex",
+1
View File
@@ -197,6 +197,7 @@ impl BenchDb {
None, None,
None, None,
ExecutionExtensions::new(profile.into_execution_strategies(), None), ExecutionExtensions::new(profile.into_execution_strategies(), None),
sp_core::tasks::executor(),
None, None,
).expect("Should not fail"); ).expect("Should not fail");
+1 -1
View File
@@ -34,7 +34,7 @@ pub use light::*;
pub use notifications::*; pub use notifications::*;
pub use proof_provider::*; pub use proof_provider::*;
pub use sp_state_machine::{StorageProof, ExecutionStrategy}; pub use sp_state_machine::{StorageProof, ExecutionStrategy, CloneableSpawn};
/// Utility methods for the client. /// Utility methods for the client.
pub mod utils { pub mod utils {
+3 -2
View File
@@ -47,7 +47,7 @@ use std::io;
use std::collections::HashMap; use std::collections::HashMap;
use sc_client_api::{ use sc_client_api::{
ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo, MemorySize, ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo, MemorySize, CloneableSpawn,
execution_extensions::ExecutionExtensions, execution_extensions::ExecutionExtensions,
backend::{NewBlockState, PrunableStateChangesTrieStorage}, backend::{NewBlockState, PrunableStateChangesTrieStorage},
}; };
@@ -292,6 +292,7 @@ pub fn new_client<E, Block, RA>(
fork_blocks: ForkBlocks<Block>, fork_blocks: ForkBlocks<Block>,
bad_blocks: BadBlocks<Block>, bad_blocks: BadBlocks<Block>,
execution_extensions: ExecutionExtensions<Block>, execution_extensions: ExecutionExtensions<Block>,
spawn_handle: Box<dyn CloneableSpawn>,
prometheus_registry: Option<Registry>, prometheus_registry: Option<Registry>,
) -> Result<( ) -> Result<(
sc_client::Client< sc_client::Client<
@@ -309,7 +310,7 @@ pub fn new_client<E, Block, RA>(
E: CodeExecutor + RuntimeInfo, E: CodeExecutor + RuntimeInfo,
{ {
let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?); 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(( Ok((
sc_client::Client::new( sc_client::Client::new(
backend.clone(), backend.clone(),
+3
View File
@@ -263,6 +263,7 @@ fn new_full_parts<TBl, TRtApi, TExecDisp>(
fork_blocks, fork_blocks,
bad_blocks, bad_blocks,
extensions, extensions,
Box::new(tasks_builder.spawn_handle()),
config.prometheus_config.as_ref().map(|config| config.registry.clone()), config.prometheus_config.as_ref().map(|config| config.registry.clone()),
)? )?
}; };
@@ -366,6 +367,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> {
sc_client::light::new_fetch_checker::<_, TBl, _>( sc_client::light::new_fetch_checker::<_, TBl, _>(
light_blockchain.clone(), light_blockchain.clone(),
executor.clone(), executor.clone(),
Box::new(tasks_builder.spawn_handle()),
), ),
); );
let fetcher = Arc::new(sc_network::config::OnDemand::new(fetch_checker)); let fetcher = Arc::new(sc_network::config::OnDemand::new(fetch_checker));
@@ -375,6 +377,7 @@ impl ServiceBuilder<(), (), (), (), (), (), (), (), (), (), ()> {
backend.clone(), backend.clone(),
config.expect_chain_spec().as_storage_builder(), config.expect_chain_spec().as_storage_builder(),
executor, executor,
Box::new(tasks_builder.spawn_handle()),
config.prometheus_config.as_ref().map(|config| config.registry.clone()), config.prometheus_config.as_ref().map(|config| config.registry.clone()),
)?); )?);
@@ -26,6 +26,7 @@ use futures::{
compat::*, compat::*,
task::{Spawn, FutureObj, SpawnError}, task::{Spawn, FutureObj, SpawnError},
}; };
use sc_client_api::CloneableSpawn;
/// Type alias for service task executor (usually runtime). /// Type alias for service task executor (usually runtime).
pub type ServiceTaskExecutor = Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>; pub type ServiceTaskExecutor = Arc<dyn Fn(Pin<Box<dyn Future<Output = ()> + Send>>) + Send + Sync>;
@@ -118,6 +119,12 @@ impl Spawn for SpawnTaskHandle {
} }
} }
impl sc_client_api::CloneableSpawn for SpawnTaskHandle {
fn clone(&self) -> Box<dyn CloneableSpawn> {
Box::new(Clone::clone(self))
}
}
type Boxed01Future01 = Box<dyn futures01::Future<Item = (), Error = ()> + Send + 'static>; type Boxed01Future01 = Box<dyn futures01::Future<Item = (), Error = ()> + Send + 'static>;
impl futures01::future::Executor<Boxed01Future01> for SpawnTaskHandle { impl futures01::future::Executor<Boxed01Future01> for SpawnTaskHandle {
+9 -1
View File
@@ -27,13 +27,14 @@ use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion};
use sp_externalities::Extensions; use sp_externalities::Extensions;
use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor}; use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor};
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache}; 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 /// Call executor that executes methods locally, querying all required
/// data from local backend. /// data from local backend.
pub struct LocalCallExecutor<B, E> { pub struct LocalCallExecutor<B, E> {
backend: Arc<B>, backend: Arc<B>,
executor: E, executor: E,
spawn_handle: Box<dyn CloneableSpawn>,
} }
impl<B, E> LocalCallExecutor<B, E> { impl<B, E> LocalCallExecutor<B, E> {
@@ -41,10 +42,12 @@ impl<B, E> LocalCallExecutor<B, E> {
pub fn new( pub fn new(
backend: Arc<B>, backend: Arc<B>,
executor: E, executor: E,
spawn_handle: Box<dyn CloneableSpawn>,
) -> Self { ) -> Self {
LocalCallExecutor { LocalCallExecutor {
backend, backend,
executor, executor,
spawn_handle,
} }
} }
} }
@@ -54,6 +57,7 @@ impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
LocalCallExecutor { LocalCallExecutor {
backend: self.backend.clone(), backend: self.backend.clone(),
executor: self.executor.clone(), executor: self.executor.clone(),
spawn_handle: self.spawn_handle.clone(),
} }
} }
} }
@@ -91,6 +95,7 @@ where
call_data, call_data,
extensions.unwrap_or_default(), extensions.unwrap_or_default(),
&state_runtime_code.runtime_code()?, &state_runtime_code.runtime_code()?,
self.spawn_handle.clone(),
).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( ).execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
strategy.get_manager(), strategy.get_manager(),
None, None,
@@ -164,6 +169,7 @@ where
call_data, call_data,
extensions.unwrap_or_default(), extensions.unwrap_or_default(),
&runtime_code, &runtime_code,
self.spawn_handle.clone(),
) )
// TODO: https://github.com/paritytech/substrate/issues/4455 // TODO: https://github.com/paritytech/substrate/issues/4455
// .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)) // .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c))
@@ -180,6 +186,7 @@ where
call_data, call_data,
extensions.unwrap_or_default(), extensions.unwrap_or_default(),
&state_runtime_code.runtime_code()?, &state_runtime_code.runtime_code()?,
self.spawn_handle.clone(),
) )
.with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c)) .with_storage_transaction_cache(storage_transaction_cache.as_mut().map(|c| &mut **c))
.execute_using_consensus_failure_handler(execution_manager, native_call) .execute_using_consensus_failure_handler(execution_manager, native_call)
@@ -218,6 +225,7 @@ where
trie_state, trie_state,
overlay, overlay,
&self.executor, &self.executor,
self.spawn_handle.clone(),
method, method,
call_data, call_data,
&sp_state_machine::backend::BackendRuntimeCode::new(trie_state).runtime_code()?, &sp_state_machine::backend::BackendRuntimeCode::new(trie_state).runtime_code()?,
+13 -4
View File
@@ -76,7 +76,7 @@ pub use sc_client_api::{
}, },
execution_extensions::{ExecutionExtensions, ExecutionStrategies}, execution_extensions::{ExecutionExtensions, ExecutionStrategies},
notifications::{StorageNotifications, StorageEventStream}, notifications::{StorageNotifications, StorageEventStream},
CallExecutor, ExecutorProvider, ProofProvider, CallExecutor, ExecutorProvider, ProofProvider, CloneableSpawn,
}; };
use sp_blockchain::Error; use sp_blockchain::Error;
use prometheus_endpoint::Registry; use prometheus_endpoint::Registry;
@@ -135,6 +135,7 @@ pub fn new_in_mem<E, Block, S, RA>(
genesis_storage: &S, genesis_storage: &S,
keystore: Option<sp_core::traits::BareCryptoStorePtr>, keystore: Option<sp_core::traits::BareCryptoStorePtr>,
prometheus_registry: Option<Registry>, prometheus_registry: Option<Registry>,
spawn_handle: Box<dyn CloneableSpawn>,
) -> sp_blockchain::Result<Client< ) -> sp_blockchain::Result<Client<
in_mem::Backend<Block>, in_mem::Backend<Block>,
LocalCallExecutor<in_mem::Backend<Block>, E>, LocalCallExecutor<in_mem::Backend<Block>, E>,
@@ -145,7 +146,7 @@ pub fn new_in_mem<E, Block, S, RA>(
S: BuildStorage, S: BuildStorage,
Block: BlockT, 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. /// Create a client with the explicitly provided backend.
@@ -155,6 +156,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
executor: E, executor: E,
build_genesis_storage: &S, build_genesis_storage: &S,
keystore: Option<sp_core::traits::BareCryptoStorePtr>, keystore: Option<sp_core::traits::BareCryptoStorePtr>,
spawn_handle: Box<dyn CloneableSpawn>,
prometheus_registry: Option<Registry>, prometheus_registry: Option<Registry>,
) -> sp_blockchain::Result<Client<B, LocalCallExecutor<B, E>, Block, RA>> ) -> sp_blockchain::Result<Client<B, LocalCallExecutor<B, E>, Block, RA>>
where where
@@ -163,7 +165,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
Block: BlockT, Block: BlockT,
B: backend::LocalBackend<Block> + 'static, B: backend::LocalBackend<Block> + '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); let extensions = ExecutionExtensions::new(Default::default(), keystore);
Client::new( Client::new(
backend, backend,
@@ -1124,7 +1126,13 @@ impl<B, E, Block, RA> ProofProvider<Block> for Client<B, E, Block, RA> where
let state = self.state_at(id)?; let state = self.state_at(id)?;
let header = self.prepare_environment_block(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])) (r, StorageProof::merge(vec![p, code_proof]))
}) })
} }
@@ -3482,6 +3490,7 @@ pub(crate) mod tests {
&substrate_test_runtime_client::GenesisParameters::default().genesis_storage(), &substrate_test_runtime_client::GenesisParameters::default().genesis_storage(),
None, None,
None, None,
sp_core::tasks::executor(),
) )
.unwrap(); .unwrap();
+7
View File
@@ -54,6 +54,7 @@ mod tests {
AccountKeyring, Sr25519Keyring, AccountKeyring, Sr25519Keyring,
}; };
use sp_runtime::traits::BlakeTwo256; use sp_runtime::traits::BlakeTwo256;
use sp_core::tasks::executor as tasks_executor;
use hex_literal::*; use hex_literal::*;
native_executor_instance!( native_executor_instance!(
@@ -101,6 +102,7 @@ mod tests {
&header.encode(), &header.encode(),
Default::default(), Default::default(),
&runtime_code, &runtime_code,
tasks_executor(),
).execute( ).execute(
ExecutionStrategy::NativeElseWasm, ExecutionStrategy::NativeElseWasm,
).unwrap(); ).unwrap();
@@ -115,6 +117,7 @@ mod tests {
&tx.encode(), &tx.encode(),
Default::default(), Default::default(),
&runtime_code, &runtime_code,
tasks_executor(),
).execute( ).execute(
ExecutionStrategy::NativeElseWasm, ExecutionStrategy::NativeElseWasm,
).unwrap(); ).unwrap();
@@ -129,6 +132,7 @@ mod tests {
&[], &[],
Default::default(), Default::default(),
&runtime_code, &runtime_code,
tasks_executor(),
).execute( ).execute(
ExecutionStrategy::NativeElseWasm, ExecutionStrategy::NativeElseWasm,
).unwrap(); ).unwrap();
@@ -179,6 +183,7 @@ mod tests {
&b1data, &b1data,
Default::default(), Default::default(),
&runtime_code, &runtime_code,
tasks_executor(),
).execute( ).execute(
ExecutionStrategy::NativeElseWasm, ExecutionStrategy::NativeElseWasm,
).unwrap(); ).unwrap();
@@ -210,6 +215,7 @@ mod tests {
&b1data, &b1data,
Default::default(), Default::default(),
&runtime_code, &runtime_code,
tasks_executor(),
).execute( ).execute(
ExecutionStrategy::AlwaysWasm, ExecutionStrategy::AlwaysWasm,
).unwrap(); ).unwrap();
@@ -241,6 +247,7 @@ mod tests {
&b1data, &b1data,
Default::default(), Default::default(),
&runtime_code, &runtime_code,
tasks_executor(),
).execute( ).execute(
ExecutionStrategy::NativeElseWasm, ExecutionStrategy::NativeElseWasm,
); );
+1
View File
@@ -62,6 +62,7 @@
//! LocalCallExecutor::new( //! LocalCallExecutor::new(
//! backend.clone(), //! backend.clone(),
//! NativeExecutor::<LocalExecutor>::new(WasmExecutionMethod::Interpreted, None, 8), //! NativeExecutor::<LocalExecutor>::new(WasmExecutionMethod::Interpreted, None, 8),
//! sp_core::tasks::executor(),
//! ), //! ),
//! // This parameter provides the storage for the chain genesis. //! // This parameter provides the storage for the chain genesis.
//! &<Storage>::default(), //! &<Storage>::default(),
+9 -2
View File
@@ -28,7 +28,7 @@ use sp_runtime::{
use sp_externalities::Extensions; use sp_externalities::Extensions;
use sp_state_machine::{ use sp_state_machine::{
self, Backend as StateBackend, OverlayedChanges, ExecutionStrategy, create_proof_check_backend, 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; use hash_db::Hasher;
@@ -216,6 +216,7 @@ pub fn prove_execution<Block, S, E>(
/// Proof should include both environment preparation proof and method execution proof. /// Proof should include both environment preparation proof and method execution proof.
pub fn check_execution_proof<Header, E, H>( pub fn check_execution_proof<Header, E, H>(
executor: &E, executor: &E,
spawn_handle: Box<dyn CloneableSpawn>,
request: &RemoteCallRequest<Header>, request: &RemoteCallRequest<Header>,
remote_proof: StorageProof, remote_proof: StorageProof,
) -> ClientResult<Vec<u8>> ) -> ClientResult<Vec<u8>>
@@ -227,6 +228,7 @@ pub fn check_execution_proof<Header, E, H>(
{ {
check_execution_proof_with_make_header::<Header, E, H, _>( check_execution_proof_with_make_header::<Header, E, H, _>(
executor, executor,
spawn_handle,
request, request,
remote_proof, remote_proof,
|header| <Header as HeaderT>::new( |header| <Header as HeaderT>::new(
@@ -241,6 +243,7 @@ pub fn check_execution_proof<Header, E, H>(
fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Header) -> Header>( fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Header) -> Header>(
executor: &E, executor: &E,
spawn_handle: Box<dyn CloneableSpawn>,
request: &RemoteCallRequest<Header>, request: &RemoteCallRequest<Header>,
remote_proof: StorageProof, remote_proof: StorageProof,
make_next_header: MakeNextHeader, make_next_header: MakeNextHeader,
@@ -267,6 +270,7 @@ fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Head
&trie_backend, &trie_backend,
&mut changes, &mut changes,
executor, executor,
spawn_handle.clone(),
"Core_initialize_block", "Core_initialize_block",
&next_header.encode(), &next_header.encode(),
&runtime_code, &runtime_code,
@@ -277,6 +281,7 @@ fn check_execution_proof_with_make_header<Header, E, H, MakeNextHeader: Fn(&Head
&trie_backend, &trie_backend,
&mut changes, &mut changes,
executor, executor,
spawn_handle,
&request.method, &request.method,
&request.call_data, &request.call_data,
&runtime_code, &runtime_code,
@@ -292,7 +297,7 @@ mod tests {
runtime::{Header, Digest, Block}, TestClient, ClientBlockImportExt, runtime::{Header, Digest, Block}, TestClient, ClientBlockImportExt,
}; };
use sc_executor::{NativeExecutor, WasmExecutionMethod}; use sc_executor::{NativeExecutor, WasmExecutionMethod};
use sp_core::H256; use sp_core::{H256, tasks::executor as tasks_executor};
use sc_client_api::backend::{Backend, NewBlockState}; use sc_client_api::backend::{Backend, NewBlockState};
use crate::in_mem::Backend as InMemBackend; use crate::in_mem::Backend as InMemBackend;
use sc_client_api::ProofProvider; use sc_client_api::ProofProvider;
@@ -387,6 +392,7 @@ mod tests {
// check remote execution proof locally // check remote execution proof locally
let local_result = check_execution_proof::<_, _, BlakeTwo256>( let local_result = check_execution_proof::<_, _, BlakeTwo256>(
&local_executor(), &local_executor(),
tasks_executor(),
&RemoteCallRequest { &RemoteCallRequest {
block: substrate_test_runtime_client::runtime::Hash::default(), block: substrate_test_runtime_client::runtime::Hash::default(),
header: remote_header, header: remote_header,
@@ -414,6 +420,7 @@ mod tests {
// check remote execution proof locally // check remote execution proof locally
let execution_result = check_execution_proof_with_make_header::<_, _, BlakeTwo256, _>( let execution_result = check_execution_proof_with_make_header::<_, _, BlakeTwo256, _>(
&local_executor(), &local_executor(),
tasks_executor(),
&RemoteCallRequest { &RemoteCallRequest {
block: substrate_test_runtime_client::runtime::Hash::default(), block: substrate_test_runtime_client::runtime::Hash::default(),
header: remote_header, header: remote_header,
+23 -6
View File
@@ -30,7 +30,7 @@ use sp_runtime::traits::{
use sp_state_machine::{ use sp_state_machine::{
ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, ChangesTrieRootsStorage, ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange,
InMemoryChangesTrieStorage, TrieBackend, read_proof_check, key_changes_proof_check_with_db, 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; pub use sp_state_machine::StorageProof;
use sp_blockchain::{Error as ClientError, Result as ClientResult}; use sp_blockchain::{Error as ClientError, Result as ClientResult};
@@ -50,14 +50,15 @@ use crate::light::call_executor::check_execution_proof;
pub struct LightDataChecker<E, H, B: BlockT, S: BlockchainStorage<B>> { pub struct LightDataChecker<E, H, B: BlockT, S: BlockchainStorage<B>> {
blockchain: Arc<Blockchain<S>>, blockchain: Arc<Blockchain<S>>,
executor: E, executor: E,
spawn_handle: Box<dyn CloneableSpawn>,
_hasher: PhantomData<(B, H)>, _hasher: PhantomData<(B, H)>,
} }
impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> { impl<E, H, B: BlockT, S: BlockchainStorage<B>> LightDataChecker<E, H, B, S> {
/// Create new light data checker. /// Create new light data checker.
pub fn new(blockchain: Arc<Blockchain<S>>, executor: E) -> Self { pub fn new(blockchain: Arc<Blockchain<S>>, executor: E, spawn_handle: Box<dyn CloneableSpawn>) -> Self {
Self { Self {
blockchain, executor, _hasher: PhantomData blockchain, executor, spawn_handle, _hasher: PhantomData
} }
} }
@@ -254,7 +255,12 @@ impl<E, Block, H, S> FetchChecker<Block> for LightDataChecker<E, H, Block, S>
request: &RemoteCallRequest<Block::Header>, request: &RemoteCallRequest<Block::Header>,
remote_proof: StorageProof, remote_proof: StorageProof,
) -> ClientResult<Vec<u8>> { ) -> ClientResult<Vec<u8>> {
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( fn check_changes_proof(
@@ -338,7 +344,8 @@ pub mod tests {
use sc_client_api::backend::NewBlockState; use sc_client_api::backend::NewBlockState;
use substrate_test_runtime_client::{ use substrate_test_runtime_client::{
blockchain::HeaderBackend, AccountKeyring, ClientBlockImportExt, blockchain::HeaderBackend, AccountKeyring, ClientBlockImportExt,
runtime::{self, Hash, Block, Header, Extrinsic} runtime::{self, Hash, Block, Header, Extrinsic},
tasks_executor,
}; };
use sp_consensus::BlockOrigin; use sp_consensus::BlockOrigin;
@@ -395,7 +402,8 @@ pub mod tests {
).unwrap(); ).unwrap();
let local_checker = LightDataChecker::new( let local_checker = LightDataChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor() local_executor(),
tasks_executor(),
); );
(local_checker, remote_block_header, remote_read_proof, heap_pages) (local_checker, remote_block_header, remote_read_proof, heap_pages)
} }
@@ -444,6 +452,7 @@ pub mod tests {
let local_checker = LightDataChecker::new( let local_checker = LightDataChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor(), local_executor(),
tasks_executor(),
); );
(local_checker, remote_block_header, remote_read_proof, child_value) (local_checker, remote_block_header, remote_read_proof, child_value)
} }
@@ -474,6 +483,7 @@ pub mod tests {
let local_checker = LightDataChecker::new( let local_checker = LightDataChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor(), local_executor(),
tasks_executor(),
); );
(local_checker, local_cht_root, remote_block_header, remote_header_proof) (local_checker, local_cht_root, remote_block_header, remote_header_proof)
} }
@@ -559,6 +569,7 @@ pub mod tests {
let local_checker = TestChecker::new( let local_checker = TestChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor(), local_executor(),
tasks_executor(),
); );
let local_checker = &local_checker as &dyn FetchChecker<Block>; let local_checker = &local_checker as &dyn FetchChecker<Block>;
let max = remote_client.chain_info().best_number; let max = remote_client.chain_info().best_number;
@@ -633,6 +644,7 @@ pub mod tests {
let local_checker = TestChecker::new( let local_checker = TestChecker::new(
Arc::new(DummyBlockchain::new(local_storage)), Arc::new(DummyBlockchain::new(local_storage)),
local_executor(), local_executor(),
tasks_executor(),
); );
// check proof on local client // check proof on local client
@@ -667,6 +679,7 @@ pub mod tests {
let local_checker = TestChecker::new( let local_checker = TestChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor(), local_executor(),
tasks_executor(),
); );
let local_checker = &local_checker as &dyn FetchChecker<Block>; let local_checker = &local_checker as &dyn FetchChecker<Block>;
let max = remote_client.chain_info().best_number; let max = remote_client.chain_info().best_number;
@@ -754,6 +767,7 @@ pub mod tests {
let local_checker = TestChecker::new( let local_checker = TestChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor(), local_executor(),
tasks_executor(),
); );
assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots, assert!(local_checker.check_changes_tries_proof(4, &remote_proof.roots,
remote_proof.roots_proof.clone()).is_err()); remote_proof.roots_proof.clone()).is_err());
@@ -764,6 +778,7 @@ pub mod tests {
let local_checker = TestChecker::new( let local_checker = TestChecker::new(
Arc::new(DummyBlockchain::new(local_storage)), Arc::new(DummyBlockchain::new(local_storage)),
local_executor(), local_executor(),
tasks_executor(),
); );
let result = local_checker.check_changes_tries_proof( let result = local_checker.check_changes_tries_proof(
4, &remote_proof.roots, StorageProof::empty() 4, &remote_proof.roots, StorageProof::empty()
@@ -781,6 +796,7 @@ pub mod tests {
let local_checker = TestChecker::new( let local_checker = TestChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor(), local_executor(),
tasks_executor(),
); );
let body_request = RemoteBodyRequest { let body_request = RemoteBodyRequest {
@@ -804,6 +820,7 @@ pub mod tests {
let local_checker = TestChecker::new( let local_checker = TestChecker::new(
Arc::new(DummyBlockchain::new(DummyStorage::new())), Arc::new(DummyBlockchain::new(DummyStorage::new())),
local_executor(), local_executor(),
tasks_executor(),
); );
let body_request = RemoteBodyRequest { let body_request = RemoteBodyRequest {
+5 -3
View File
@@ -33,7 +33,7 @@ use prometheus_endpoint::Registry;
use crate::call_executor::LocalCallExecutor; use crate::call_executor::LocalCallExecutor;
use crate::client::Client; use crate::client::Client;
use sc_client_api::{ use sc_client_api::{
light::Storage as BlockchainStorage, light::Storage as BlockchainStorage, CloneableSpawn,
}; };
use crate::light::backend::Backend; use crate::light::backend::Backend;
use crate::light::blockchain::Blockchain; use crate::light::blockchain::Blockchain;
@@ -59,6 +59,7 @@ pub fn new_light<B, S, RA, E>(
backend: Arc<Backend<S, HashFor<B>>>, backend: Arc<Backend<S, HashFor<B>>>,
genesis_storage: &dyn BuildStorage, genesis_storage: &dyn BuildStorage,
code_executor: E, code_executor: E,
spawn_handle: Box<dyn CloneableSpawn>,
prometheus_registry: Option<Registry>, prometheus_registry: Option<Registry>,
) -> ClientResult< ) -> ClientResult<
Client< Client<
@@ -76,7 +77,7 @@ pub fn new_light<B, S, RA, E>(
S: BlockchainStorage<B> + 'static, S: BlockchainStorage<B> + 'static,
E: CodeExecutor + RuntimeInfo + Clone + '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); let executor = GenesisCallExecutor::new(backend.clone(), local_executor);
Client::new( Client::new(
backend, backend,
@@ -93,9 +94,10 @@ pub fn new_light<B, S, RA, E>(
pub fn new_fetch_checker<E, B: BlockT, S: BlockchainStorage<B>>( pub fn new_fetch_checker<E, B: BlockT, S: BlockchainStorage<B>>(
blockchain: Arc<Blockchain<S>>, blockchain: Arc<Blockchain<S>>,
executor: E, executor: E,
spawn_handle: Box<dyn CloneableSpawn>,
) -> LightDataChecker<E, HashFor<B>, B, S> ) -> LightDataChecker<E, HashFor<B>, B, S>
where where
E: CodeExecutor, E: CodeExecutor,
{ {
LightDataChecker::new(blockchain, executor) LightDataChecker::new(blockchain, executor, spawn_handle)
} }
@@ -200,6 +200,7 @@ fn record_proof_works() {
&backend, &backend,
&mut overlay, &mut overlay,
&executor, &executor,
sp_core::tasks::executor(),
"Core_execute_block", "Core_execute_block",
&block.encode(), &block.encode(),
&runtime_code, &runtime_code,
+4 -1
View File
@@ -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-externalities = { version = "0.8.0-alpha.2", optional = true, path = "../externalities" }
sp-storage = { version = "2.0.0-alpha.2", default-features = false, path = "../storage" } 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"] } parity-util-mem = { version = "0.5.2", default-features = false, features = ["primitive-types"] }
futures = { version = "0.3.1", optional = true }
# full crypto # full crypto
ed25519-dalek = { version = "1.0.0-pre.3", default-features = false, features = ["u64_backend", "alloc"], optional = true } 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-externalities",
"sp-storage/std", "sp-storage/std",
"sp-runtime-interface/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 # This feature enables all crypto primitives for `no_std` builds like microcontrollers
+2
View File
@@ -70,6 +70,8 @@ mod changes_trie;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod traits; pub mod traits;
pub mod testing; pub mod testing;
#[cfg(feature = "std")]
pub mod tasks;
pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::hash::{H160, H256, H512, convert_hash};
pub use self::uint::U256; pub use self::uint::U256;
+56
View File
@@ -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 <http://www.gnu.org/licenses/>.
//! 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<dyn CloneableSpawn> {
Box::new(Clone::clone(self))
}
}
/// Create tasks executor.
pub fn executor() -> Box<dyn CloneableSpawn> {
Box::new(Executor::new())
}
+18
View File
@@ -212,3 +212,21 @@ impl CallInWasmExt {
Self(Box::new(inner)) 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<dyn CloneableSpawn>;
}
sp_externalities::decl_extension! {
/// Task executor extension.
pub struct TaskExecutorExt(Box<dyn CloneableSpawn>);
}
impl TaskExecutorExt {
/// New instance of task executor extension.
pub fn new(spawn_handle: Box<dyn CloneableSpawn>) -> Self {
Self(spawn_handle)
}
}
@@ -12,4 +12,4 @@ documentation = "https://docs.rs/sp-externalities"
[dependencies] [dependencies]
sp-storage = { version = "2.0.0-alpha.2", path = "../storage" } sp-storage = { version = "2.0.0-alpha.2", path = "../storage" }
sp-std = { version = "2.0.0-alpha.2", path = "../std" } sp-std = { version = "2.0.0-alpha.2", path = "../std" }
environmental = { version = "1.1.1" } environmental = { version = "1.1.1" }
@@ -573,7 +573,6 @@ mod tests {
const CHILD_UUID_1: &[u8] = b"unique_id_1"; const CHILD_UUID_1: &[u8] = b"unique_id_1";
const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(CHILD_UUID_1); const CHILD_INFO_1: ChildInfo<'static> = ChildInfo::new_default(CHILD_UUID_1);
fn prepare_overlay_with_changes() -> OverlayedChanges { fn prepare_overlay_with_changes() -> OverlayedChanges {
OverlayedChanges { OverlayedChanges {
prospective: vec![ prospective: vec![
@@ -74,6 +74,7 @@ pub use trie_backend::TrieBackend;
pub use error::{Error, ExecutionError}; pub use error::{Error, ExecutionError};
pub use in_memory_backend::InMemory as InMemoryBackend; pub use in_memory_backend::InMemory as InMemoryBackend;
pub use stats::{UsageInfo, UsageUnit}; pub use stats::{UsageInfo, UsageUnit};
pub use sp_core::traits::CloneableSpawn;
type CallResult<R, E> = Result<NativeOrEncoded<R>, E>; type CallResult<R, E> = Result<NativeOrEncoded<R>, E>;
@@ -210,8 +211,10 @@ impl<'a, B, H, N, Exec> StateMachine<'a, B, H, N, Exec> where
call_data: &'a [u8], call_data: &'a [u8],
mut extensions: Extensions, mut extensions: Extensions,
runtime_code: &'a RuntimeCode, runtime_code: &'a RuntimeCode,
spawn_handle: Box<dyn CloneableSpawn>,
) -> Self { ) -> Self {
extensions.register(CallInWasmExt::new(exec.clone())); extensions.register(CallInWasmExt::new(exec.clone()));
extensions.register(sp_core::traits::TaskExecutorExt::new(spawn_handle));
Self { Self {
backend, backend,
@@ -437,6 +440,7 @@ pub fn prove_execution<B, H, N, Exec>(
mut backend: B, mut backend: B,
overlay: &mut OverlayedChanges, overlay: &mut OverlayedChanges,
exec: &Exec, exec: &Exec,
spawn_handle: Box<dyn CloneableSpawn>,
method: &str, method: &str,
call_data: &[u8], call_data: &[u8],
runtime_code: &RuntimeCode, runtime_code: &RuntimeCode,
@@ -454,6 +458,7 @@ where
trie_backend, trie_backend,
overlay, overlay,
exec, exec,
spawn_handle,
method, method,
call_data, call_data,
runtime_code, runtime_code,
@@ -473,6 +478,7 @@ pub fn prove_execution_on_trie_backend<S, H, N, Exec>(
trie_backend: &TrieBackend<S, H>, trie_backend: &TrieBackend<S, H>,
overlay: &mut OverlayedChanges, overlay: &mut OverlayedChanges,
exec: &Exec, exec: &Exec,
spawn_handle: Box<dyn CloneableSpawn>,
method: &str, method: &str,
call_data: &[u8], call_data: &[u8],
runtime_code: &RuntimeCode, runtime_code: &RuntimeCode,
@@ -494,6 +500,7 @@ where
call_data, call_data,
Extensions::default(), Extensions::default(),
runtime_code, runtime_code,
spawn_handle,
); );
let result = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( let result = sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
@@ -510,6 +517,7 @@ pub fn execution_proof_check<H, N, Exec>(
proof: StorageProof, proof: StorageProof,
overlay: &mut OverlayedChanges, overlay: &mut OverlayedChanges,
exec: &Exec, exec: &Exec,
spawn_handle: Box<dyn CloneableSpawn>,
method: &str, method: &str,
call_data: &[u8], call_data: &[u8],
runtime_code: &RuntimeCode, runtime_code: &RuntimeCode,
@@ -525,6 +533,7 @@ where
&trie_backend, &trie_backend,
overlay, overlay,
exec, exec,
spawn_handle,
method, method,
call_data, call_data,
runtime_code, runtime_code,
@@ -536,6 +545,7 @@ pub fn execution_proof_check_on_trie_backend<H, N, Exec>(
trie_backend: &TrieBackend<MemoryDB<H>, H>, trie_backend: &TrieBackend<MemoryDB<H>, H>,
overlay: &mut OverlayedChanges, overlay: &mut OverlayedChanges,
exec: &Exec, exec: &Exec,
spawn_handle: Box<dyn CloneableSpawn>,
method: &str, method: &str,
call_data: &[u8], call_data: &[u8],
runtime_code: &RuntimeCode, runtime_code: &RuntimeCode,
@@ -555,6 +565,7 @@ where
call_data, call_data,
Extensions::default(), Extensions::default(),
runtime_code, runtime_code,
spawn_handle,
); );
sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>( sm.execute_using_consensus_failure_handler::<_, NeverNativeValue, fn() -> _>(
@@ -820,6 +831,7 @@ mod tests {
&[], &[],
Default::default(), Default::default(),
&wasm_code, &wasm_code,
sp_core::tasks::executor(),
); );
assert_eq!( assert_eq!(
@@ -849,6 +861,7 @@ mod tests {
&[], &[],
Default::default(), Default::default(),
&wasm_code, &wasm_code,
sp_core::tasks::executor(),
); );
assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap(), vec![66]); assert_eq!(state_machine.execute(ExecutionStrategy::NativeElseWasm).unwrap(), vec![66]);
@@ -875,6 +888,7 @@ mod tests {
&[], &[],
Default::default(), Default::default(),
&wasm_code, &wasm_code,
sp_core::tasks::executor(),
); );
assert!( assert!(
@@ -905,6 +919,7 @@ mod tests {
remote_backend, remote_backend,
&mut Default::default(), &mut Default::default(),
&executor, &executor,
sp_core::tasks::executor(),
"test", "test",
&[], &[],
&RuntimeCode::empty(), &RuntimeCode::empty(),
@@ -916,6 +931,7 @@ mod tests {
remote_proof, remote_proof,
&mut Default::default(), &mut Default::default(),
&executor, &executor,
sp_core::tasks::executor(),
"test", "test",
&[], &[],
&RuntimeCode::empty(), &RuntimeCode::empty(),
+3 -3
View File
@@ -23,7 +23,7 @@ pub mod client_ext;
pub use sc_client::{blockchain, self}; pub use sc_client::{blockchain, self};
pub use sc_client_api::{ pub use sc_client_api::{
execution_extensions::{ExecutionStrategies, ExecutionExtensions}, execution_extensions::{ExecutionStrategies, ExecutionExtensions},
ForkBlocks, BadBlocks, ForkBlocks, BadBlocks, CloneableSpawn,
}; };
pub use sc_client_db::{Backend, self}; pub use sc_client_db::{Backend, self};
pub use sp_consensus; pub use sp_consensus;
@@ -33,7 +33,7 @@ pub use sp_keyring::{
ed25519::Keyring as Ed25519Keyring, ed25519::Keyring as Ed25519Keyring,
sr25519::Keyring as Sr25519Keyring, 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_runtime::{Storage, StorageChild};
pub use sp_state_machine::ExecutionStrategy; pub use sp_state_machine::ExecutionStrategy;
pub use self::client_ext::{ClientExt, ClientBlockImportExt}; pub use self::client_ext::{ClientExt, ClientBlockImportExt};
@@ -246,7 +246,7 @@ impl<Block: BlockT, E, Backend, G: GenesisInit> TestClientBuilder<
let executor = executor.into().unwrap_or_else(|| let executor = executor.into().unwrap_or_else(||
NativeExecutor::new(WasmExecutionMethod::Interpreted, None, 8) 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) self.build_with_executor(executor)
} }
@@ -349,7 +349,7 @@ pub fn new_light() -> (
let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage)); let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage));
let backend = Arc::new(LightBackend::new(blockchain.clone())); let backend = Arc::new(LightBackend::new(blockchain.clone()));
let executor = new_native_executor(); 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( let call_executor = LightExecutor::new(
backend.clone(), backend.clone(),
local_call_executor, local_call_executor,
@@ -10,6 +10,7 @@ description = "CLI for benchmarking FRAME"
[dependencies] [dependencies]
frame-benchmarking = { version = "2.0.0-alpha.2", path = "../../../frame/benchmarking" } 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-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-cli = { version = "0.8.0-alpha.2", path = "../../../client/cli" }
sc-client = { version = "0.8.0-alpha.2", path = "../../../client" } sc-client = { version = "0.8.0-alpha.2", path = "../../../client" }
@@ -23,6 +23,7 @@ use sc_service::{Configuration, ChainSpec};
use sc_executor::{NativeExecutor, NativeExecutionDispatch}; use sc_executor::{NativeExecutor, NativeExecutionDispatch};
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use frame_benchmarking::BenchmarkResults; use frame_benchmarking::BenchmarkResults;
use sp_core::tasks;
/// The `benchmark` command used to benchmark FRAME Pallets. /// The `benchmark` command used to benchmark FRAME Pallets.
#[derive(Debug, structopt::StructOpt, Clone)] #[derive(Debug, structopt::StructOpt, Clone)]
@@ -121,6 +122,7 @@ impl BenchmarkCmd {
).encode(), ).encode(),
Default::default(), Default::default(),
&sp_state_machine::backend::BackendRuntimeCode::new(&state).runtime_code()?, &sp_state_machine::backend::BackendRuntimeCode::new(&state).runtime_code()?,
tasks::executor(),
) )
.execute(strategy.into()) .execute(strategy.into())
.map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?; .map_err(|e| format!("Error executing runtime benchmark: {:?}", e))?;