diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock index e86e42238c..8b8f0ce91d 100644 --- a/polkadot/Cargo.lock +++ b/polkadot/Cargo.lock @@ -8713,8 +8713,11 @@ dependencies = [ "polkadot-collator", "polkadot-parachain", "polkadot-primitives", + "polkadot-service", "sc-client-api", + "sp-api", "sp-core", + "sp-runtime", "test-parachain-adder", ] diff --git a/polkadot/collator/src/lib.rs b/polkadot/collator/src/lib.rs index 070740bf7f..8e0cabb0eb 100644 --- a/polkadot/collator/src/lib.rs +++ b/polkadot/collator/src/lib.rs @@ -67,7 +67,7 @@ pub use sc_network::PeerId; pub use service::{RuntimeApiCollection, Client}; pub use sc_cli::SubstrateCli; #[cfg(not(feature = "service-rewr"))] -use polkadot_service::{FullNodeHandles, AbstractClient}; +use polkadot_service::{FullNodeHandles, AbstractClient, ClientHandle}; #[cfg(feature = "service-rewr")] use polkadot_service_new::{ self as polkadot_service, @@ -77,6 +77,7 @@ use sc_service::SpawnTaskHandle; use sp_core::traits::SpawnNamed; use sp_runtime::traits::BlakeTwo256; use consensus_common::SyncOracle; +use sc_client_api::Backend as BackendT; const COLLATION_TIMEOUT: Duration = Duration::from_secs(30); @@ -117,14 +118,19 @@ pub trait BuildParachainContext { type ParachainContext: self::ParachainContext; /// Build the `ParachainContext`. - fn build( + fn build( self, - client: polkadot_service::Client, + client: Arc, spawner: SP, network: impl Network + SyncOracle + Clone + 'static, ) -> Result where - SP: SpawnNamed + Clone + Send + Sync + 'static; + SP: SpawnNamed + Clone + Send + Sync + 'static, + Backend: BackendT, + Backend::State: sp_api::StateBackend, + Client: polkadot_service::AbstractClient + 'static, + Client::Api: RuntimeApiCollection, + ; } /// Parachain context needed for collation. @@ -194,11 +200,12 @@ pub async fn collate

( Some(collation) } +/// Build a collator service based on the `ClientHandle`. #[cfg(feature = "service-rewr")] -fn build_collator_service

( +pub fn build_collator_service

( spawner: SpawnTaskHandle, handles: FullNodeHandles, - client: polkadot_service::Client, + client: impl ClientHandle, para_id: ParaId, key: Arc, build_parachain_context: P, @@ -217,7 +224,6 @@ struct BuildCollationWork

{ key: Arc, build_parachain_context: P, spawner: SpawnTaskHandle, - client: polkadot_service::Client, } impl

polkadot_service::ExecuteWithClient for BuildCollationWork

@@ -233,7 +239,7 @@ impl

polkadot_service::ExecuteWithClient for BuildCollationWork

Backend: sc_client_api::Backend, Backend::State: sp_api::StateBackend, Api: RuntimeApiCollection, - Client: AbstractClient + 'static + Client: AbstractClient + 'static, { let polkadot_network = self.handles .polkadot_network @@ -246,7 +252,7 @@ impl

polkadot_service::ExecuteWithClient for BuildCollationWork

.ok_or_else(|| "Collator cannot run when validation networking has not been started")?; let parachain_context = match self.build_parachain_context.build( - self.client, + client.clone(), self.spawner.clone(), polkadot_network.clone(), ) { @@ -346,11 +352,12 @@ impl

polkadot_service::ExecuteWithClient for BuildCollationWork

} } +/// Build a collator service based on the `ClientHandle`. #[cfg(not(feature = "service-rewr"))] -fn build_collator_service

( +pub fn build_collator_service

( spawner: SpawnTaskHandle, handles: FullNodeHandles, - client: polkadot_service::Client, + client: impl ClientHandle, para_id: ParaId, key: Arc, build_parachain_context: P, @@ -366,7 +373,6 @@ fn build_collator_service

( key, build_parachain_context, spawner, - client: client.clone(), }) } @@ -454,12 +460,19 @@ mod tests { impl BuildParachainContext for BuildDummyParachainContext { type ParachainContext = DummyParachainContext; - fn build( + fn build( self, - _: polkadot_service::Client, + _: Arc, _: SP, _: impl Network + Clone + 'static, - ) -> Result { + ) -> Result + where + SP: SpawnNamed + Clone + Send + Sync + 'static, + Backend: BackendT, + Backend::State: sp_api::StateBackend, + Client: polkadot_service::AbstractClient + 'static, + Client::Api: RuntimeApiCollection, + { Ok(DummyParachainContext) } } diff --git a/polkadot/node/test-service/src/lib.rs b/polkadot/node/test-service/src/lib.rs index 03b8dd6aa6..f82c4b7ad3 100644 --- a/polkadot/node/test-service/src/lib.rs +++ b/polkadot/node/test-service/src/lib.rs @@ -26,7 +26,7 @@ use polkadot_primitives::v0::{ Block, Hash, CollatorId, Id as ParaId, }; use polkadot_runtime_common::{parachains, registrar, BlockHashCount}; -use polkadot_service::{new_full, FullNodeHandles, AbstractClient}; +use polkadot_service::{new_full, FullNodeHandles, AbstractClient, ClientHandle, ExecuteWithClient}; use polkadot_test_runtime::{RestrictFunctionality, Runtime, SignedExtra, SignedPayload, VERSION}; use sc_chain_spec::ChainSpec; use sc_client_api::{execution_extensions::ExecutionStrategies, BlockchainEvents}; @@ -67,7 +67,7 @@ pub fn polkadot_test_new_full( ) -> Result< ( TaskManager, - Arc>>, + Arc>, FullNodeHandles, Arc>, Arc, @@ -88,6 +88,15 @@ pub fn polkadot_test_new_full( Ok((task_manager, client, handles, network, rpc_handlers)) } +/// A wrapper for the test client that implements `ClientHandle`. +pub struct TestClient(pub Arc>); + +impl ClientHandle for TestClient { + fn execute_with(&self, t: T) -> T::Output { + T::execute_with_client::<_, _, polkadot_service::FullBackend>(t, self.0.clone()) + } +} + /// Create a Polkadot `Configuration`. By default an in-memory socket will be used, therefore you need to provide boot /// nodes if you want the future node to be connected to other nodes. The `storage_update_func` can be used to make /// adjustements to the runtime before the node starts. diff --git a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml index dc686fe24e..cab8bbf98b 100644 --- a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml +++ b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml @@ -9,8 +9,11 @@ adder = { package = "test-parachain-adder", path = ".." } parachain = { package = "polkadot-parachain", path = "../../.." } collator = { package = "polkadot-collator", path = "../../../../collator" } primitives = { package = "polkadot-primitives", path = "../../../../primitives" } +service = { package = "polkadot-service", path = "../../../../service" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } client-api = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } parking_lot = "0.10.0" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.4" diff --git a/polkadot/parachain/test-parachains/adder/collator/src/main.rs b/polkadot/parachain/test-parachains/adder/collator/src/main.rs index 2bddff6f86..318bc6142c 100644 --- a/polkadot/parachain/test-parachains/adder/collator/src/main.rs +++ b/polkadot/parachain/test-parachains/adder/collator/src/main.rs @@ -20,15 +20,17 @@ use std::collections::HashMap; use std::sync::Arc; use adder::{HeadData as AdderHead, BlockData as AdderBody}; -use sp_core::Pair; +use sp_core::{traits::SpawnNamed, Pair}; use codec::{Encode, Decode}; use primitives::v0::{ - Hash, DownwardMessage, + Block, Hash, DownwardMessage, HeadData, BlockData, Id as ParaId, LocalValidationData, GlobalValidationData, }; use collator::{ParachainContext, Network, BuildParachainContext, Cli, SubstrateCli}; use parking_lot::Mutex; use futures::future::{Ready, ready, FutureExt}; +use sp_runtime::traits::BlakeTwo256; +use client_api::Backend as BackendT; const GENESIS: AdderHead = AdderHead { number: 0, @@ -103,12 +105,19 @@ impl ParachainContext for AdderContext { impl BuildParachainContext for AdderContext { type ParachainContext = Self; - fn build( + fn build( self, - _: collator::Client, + _: Arc, _: SP, network: impl Network + Clone + 'static, - ) -> Result { + ) -> Result + where + SP: SpawnNamed + Clone + Send + Sync + 'static, + Backend: BackendT, + Backend::State: sp_api::StateBackend, + Client: service::AbstractClient + 'static, + Client::Api: service::RuntimeApiCollection, + { Ok(Self { _network: Some(Arc::new(network)), ..self }) } } diff --git a/polkadot/service/src/client.rs b/polkadot/service/src/client.rs index e7743e8530..dad038cf96 100644 --- a/polkadot/service/src/client.rs +++ b/polkadot/service/src/client.rs @@ -118,6 +118,19 @@ pub trait ExecuteWithClient { Client: AbstractClient + 'static; } +/// A handle to a Polkadot client instance. +/// +/// The Polkadot service supports multiple different runtimes (Westend, Polkadot itself, etc). As each runtime has a +/// specialized client, we need to hide them behind a trait. This is this trait. +/// +/// When wanting to work with the inner client, you need to use `execute_with`. +/// +/// See [`ExecuteWithClient`](trait.ExecuteWithClient.html) for more information. +pub trait ClientHandle { + /// Execute the given something with the client. + fn execute_with(&self, t: T) -> T::Output; +} + /// A client instance of Polkadot. /// /// See [`ExecuteWithClient`] for more information. @@ -129,9 +142,8 @@ pub enum Client { Rococo(Arc>), } -impl Client { - /// Execute the given something with the client. - pub fn execute_with(&self, t: T) -> T::Output { +impl ClientHandle for Client { + fn execute_with(&self, t: T) -> T::Output { match self { Self::Polkadot(client) => { T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()) diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index b311117dd2..6bb78a18ce 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -109,16 +109,25 @@ impl IdentifyVariant for Box { } } -type FullBackend = service::TFullBackend; -type FullSelectChain = sc_consensus::LongestChain; -type FullClient = service::TFullClient; -type FullGrandpaBlockImport = grandpa::GrandpaBlockImport< +/// Polkadot's full backend. +pub type FullBackend = service::TFullBackend; + +/// Polkadot's select chain. +pub type FullSelectChain = sc_consensus::LongestChain; + +/// Polkadot's full client. +pub type FullClient = service::TFullClient; + +/// Polkadot's full Grandpa block import. +pub type FullGrandpaBlockImport = grandpa::GrandpaBlockImport< FullBackend, Block, FullClient, FullSelectChain >; -type LightBackend = service::TLightBackendWithHash; +/// Polkadot's light backend. +pub type LightBackend = service::TLightBackendWithHash; -type LightClient = +/// Polkadot's light client. +pub type LightClient = service::TLightClientWithBackend; #[cfg(feature = "full-node")]