;
+ SP: Spawn + Clone + Send + Sync + 'static;
}
/// Parachain context needed for collation.
@@ -209,38 +200,40 @@ pub async fn collate(
Ok(collation)
}
-fn build_collator_service(
- service: (S, polkadot_service::FullNodeHandles),
+
+fn build_collator_service(
+ spawner: SP,
+ handles: polkadot_service::FullNodeHandles,
+ client: Arc,
para_id: ParaId,
key: Arc,
build_parachain_context: P,
-) -> Result
+) -> Result + Send + 'static, polkadot_service::Error>
where
- S: AbstractService,
- sc_client::Client: ProvideRuntimeApi,
- as ProvideRuntimeApi>::Api:
- RuntimeApiCollection<
+ C: ClientProvider<
+ service::Block,
+ service::TFullBackend,
+ service::TFullCallExecutor,
+ R
+ > + 'static,
+ R: ConstructRuntimeApi + Sync + Send,
+ >::RuntimeApi:
+ sp_api::ApiExt<
+ service::Block,
+ StateBackend = as service::Backend>::State,
+ >
+ + RuntimeApiCollection<
Extrinsic,
- Error = sp_blockchain::Error,
- StateBackend = sc_client_api::StateBackendFor
- >,
- // Rust bug: https://github.com/rust-lang/rust/issues/24159
- S::Backend: service::Backend,
- // Rust bug: https://github.com/rust-lang/rust/issues/24159
- >::State:
- sp_api::StateBackend>,
- // Rust bug: https://github.com/rust-lang/rust/issues/24159
- S::CallExecutor: service::CallExecutor,
- // Rust bug: https://github.com/rust-lang/rust/issues/24159
- S::SelectChain: service::SelectChain,
+ StateBackend = as service::Backend>::State,
+ >
+ + Sync + Send,
+ E: sc_executor::NativeExecutionDispatch + 'static,
P: BuildParachainContext,
P::ParachainContext: Send + 'static,
::ProduceCandidate: Send,
Extrinsic: service::Codec + Send + Sync + 'static,
+ SP: Spawn + Clone + Send + Sync + 'static,
{
- let (service, handles) = service;
- let spawner = service.spawn_task_handle();
-
let polkadot_network = handles.polkadot_network
.ok_or_else(|| "Collator cannot run when Polkadot-specific networking has not been started")?;
@@ -250,8 +243,6 @@ fn build_collator_service(
handles.validation_service_handle
.ok_or_else(|| "Collator cannot run when validation networking has not been started")?;
- let client = service.client();
-
let parachain_context = match build_parachain_context.build(
client.clone(),
spawner,
@@ -334,9 +325,7 @@ fn build_collator_service(
}
}.boxed();
- service.spawn_essential_task("collation", work);
-
- Ok(service)
+ Ok(work)
}
/// Async function that will run the collator node with the given `RelayChainContext` and `ParachainContext`
@@ -348,29 +337,55 @@ pub async fn start_collator(
config: Configuration,
) -> Result<(), polkadot_service::Error>
where
- P: BuildParachainContext,
+ P: 'static + BuildParachainContext,
P::ParachainContext: Send + 'static,
::ProduceCandidate: Send,
{
let is_kusama = config.chain_spec.is_kusama();
match (is_kusama, &config.role) {
- (_, Role::Light) => return Err(
+ (_, Role::Light) => Err(
polkadot_service::Error::Other("light nodes are unsupported as collator".into())
).into(),
- (true, _) =>
+ (true, _) => {
+ let (service, client, handlers) = service::kusama_new_full(
+ config,
+ Some((key.public(), para_id)),
+ None,
+ false,
+ 6000,
+ None
+ )?;
+ let spawn_handle = service.spawn_task_handle();
build_collator_service(
- service::kusama_new_full(config, Some((key.public(), para_id)), None, false, 6000, None)?,
+ spawn_handle,
+ handlers,
+ client,
para_id,
key,
- build_parachain_context,
- )?.await,
- (false, _) =>
+ build_parachain_context
+ )?.await;
+ Ok(())
+ },
+ (false, _) => {
+ let (service, client, handles) = service::polkadot_new_full(
+ config,
+ Some((key.public(), para_id)),
+ None,
+ false,
+ 6000,
+ None
+ )?;
+ let spawn_handle = service.spawn_task_handle();
build_collator_service(
- service::polkadot_new_full(config, Some((key.public(), para_id)), None, false, 6000, None)?,
+ spawn_handle,
+ handles,
+ client,
para_id,
key,
build_parachain_context,
- )?.await,
+ )?.await;
+ Ok(())
+ }
}
}
@@ -413,9 +428,9 @@ mod tests {
impl BuildParachainContext for BuildDummyParachainContext {
type ParachainContext = DummyParachainContext;
- fn build(
+ fn build(
self,
- _: Arc>,
+ _: Arc,
_: SP,
_: impl Network + Clone + 'static,
) -> Result {
diff --git a/network/Cargo.toml b/network/Cargo.toml
index 01406bae8b0c..d60f941c4526 100644
--- a/network/Cargo.toml
+++ b/network/Cargo.toml
@@ -23,7 +23,6 @@ futures = "0.3.4"
log = "0.4.8"
exit-future = "0.2.0"
futures-timer = "2.0"
-sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
wasm-timer = "0.2.4"
diff --git a/network/test/Cargo.toml b/network/test/Cargo.toml
index c1a6fc9663d1..3761527a7a40 100644
--- a/network/test/Cargo.toml
+++ b/network/test/Cargo.toml
@@ -10,10 +10,11 @@ log = "0.4.8"
parking_lot = "0.10.0"
futures = "0.3.1"
rand = "0.7.2"
+sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sc-service = { git = "https://github.com/paritytech/substrate", features = ["test-helpers"], branch = "master" }
sc-network-test = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
diff --git a/network/test/src/lib.rs b/network/test/src/lib.rs
index 36bdda0ba4d6..bd824f1441b9 100644
--- a/network/test/src/lib.rs
+++ b/network/test/src/lib.rs
@@ -34,8 +34,8 @@ use sc_client_api::{
client::BlockBackend,
backend::{TransactionFor, AuxStore, Backend, Finalizer},
};
+use sc_consensus::LongestChain;
use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
-use sc_client::LongestChain;
use sp_consensus::block_validation::DefaultBlockAnnounceValidator;
use sp_consensus::import_queue::{
BasicQueue, BoxJustificationImport, Verifier, BoxFinalityProofImport,
@@ -53,14 +53,23 @@ use sp_runtime::generic::BlockId;
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
use sp_runtime::Justification;
pub use sc_network_test::PassThroughVerifier;
+use sc_service::client::Client;
pub use polkadot_test_runtime_client::runtime::{Block, Extrinsic, Hash};
pub use polkadot_test_runtime_client::{TestClient, TestClientBuilder, TestClientBuilderExt};
-pub type PeersFullClient =
- sc_client::Client;
-pub type PeersLightClient =
- sc_client::Client;
+pub type PeersFullClient = Client<
+ polkadot_test_runtime_client::Backend,
+ polkadot_test_runtime_client::Executor,
+ Block,
+ polkadot_test_runtime_client::runtime::RuntimeApi
+>;
+pub type PeersLightClient = Client<
+ polkadot_test_runtime_client::LightBackend,
+ polkadot_test_runtime_client::LightExecutor,
+ Block,
+ polkadot_test_runtime_client::runtime::RuntimeApi
+>;
#[derive(Clone)]
pub enum PeersClient {
diff --git a/parachain/test-parachains/adder/collator/Cargo.toml b/parachain/test-parachains/adder/collator/Cargo.toml
index 1d56b6924128..3363a908a943 100644
--- a/parachain/test-parachains/adder/collator/Cargo.toml
+++ b/parachain/test-parachains/adder/collator/Cargo.toml
@@ -10,7 +10,6 @@ parachain = { package = "polkadot-parachain", path = "../../.." }
collator = { package = "polkadot-collator", path = "../../../../collator" }
primitives = { package = "polkadot-primitives", path = "../../../../primitives" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
-client = { package = "sc-client", git = "https://github.com/paritytech/substrate", branch = "master" }
client-api = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "master" }
parking_lot = "0.10.0"
codec = { package = "parity-scale-codec", version = "1.2.0" }
diff --git a/parachain/test-parachains/adder/collator/src/main.rs b/parachain/test-parachains/adder/collator/src/main.rs
index cc61dc2695e2..5ecf063dda85 100644
--- a/parachain/test-parachains/adder/collator/src/main.rs
+++ b/parachain/test-parachains/adder/collator/src/main.rs
@@ -101,9 +101,9 @@ impl ParachainContext for AdderContext {
impl BuildParachainContext for AdderContext {
type ParachainContext = Self;
- fn build(
+ fn build(
self,
- _: Arc>,
+ _: Arc,
_: SP,
network: impl Network + Clone + 'static,
) -> Result {
diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml
index ab0f302a48bb..9660ce3ec968 100644
--- a/rpc/Cargo.toml
+++ b/rpc/Cargo.toml
@@ -5,9 +5,10 @@ authors = ["Parity Technologies "]
edition = "2018"
[dependencies]
-client = { package = "sc-client", git = "https://github.com/paritytech/substrate", branch = "master" }
jsonrpc-core = "14.0.3"
polkadot-primitives = { path = "../primitives" }
+sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-blockchain = { 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" }
sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs
index 3b27b2543435..cc54917ffafe 100644
--- a/rpc/src/lib.rs
+++ b/rpc/src/lib.rs
@@ -23,6 +23,8 @@ use std::sync::Arc;
use polkadot_primitives::{Block, AccountId, Nonce, Balance};
use sp_api::ProvideRuntimeApi;
use txpool_api::TransactionPool;
+use sp_blockchain::HeaderBackend;
+use sc_client_api::light::{Fetcher, RemoteBlockchain};
/// A type representing all RPC extensions.
pub type RpcExtension = jsonrpc_core::IoHandler;
@@ -30,7 +32,7 @@ pub type RpcExtension = jsonrpc_core::IoHandler;
/// Instantiate all RPC extensions.
pub fn create_full(client: Arc, pool: Arc) -> RpcExtension where
C: ProvideRuntimeApi,
- C: client::blockchain::HeaderBackend,
+ C: HeaderBackend,
C: Send + Sync + 'static,
C::Api: frame_rpc_system::AccountNonceApi,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi,
@@ -53,18 +55,18 @@ pub fn create_full(client: Arc, pool: Arc) -> RpcExtension where
/// Instantiate all RPC extensions for light node.
pub fn create_light(
client: Arc,
- remote_blockchain: Arc>,
+ remote_blockchain: Arc>,
fetcher: Arc,
pool: Arc,
) -> RpcExtension
where
C: ProvideRuntimeApi,
- C: client::blockchain::HeaderBackend,
+ C: HeaderBackend,
C: Send + Sync + 'static,
C::Api: frame_rpc_system::AccountNonceApi,
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi,
P: TransactionPool + Sync + Send + 'static,
- F: client::light::fetcher::Fetcher + 'static,
+ F: Fetcher + 'static,
UE: codec::Codec + Send + Sync + 'static,
{
use frame_rpc_system::{LightSystem, SystemApi};
diff --git a/runtime/test-runtime/client/Cargo.toml b/runtime/test-runtime/client/Cargo.toml
index b540adfb9b49..ff94572b5f8e 100644
--- a/runtime/test-runtime/client/Cargo.toml
+++ b/runtime/test-runtime/client/Cargo.toml
@@ -7,6 +7,8 @@ license = "GPL-3.0"
[dependencies]
sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["test-helpers"], default-features = false }
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
polkadot-test-runtime = { path = ".." }
@@ -17,6 +19,5 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
codec = { package = "parity-scale-codec", version = "1.0.0" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
futures = "0.3.1"
diff --git a/runtime/test-runtime/client/src/lib.rs b/runtime/test-runtime/client/src/lib.rs
index 2d7797557e72..ad767f7ffde5 100644
--- a/runtime/test-runtime/client/src/lib.rs
+++ b/runtime/test-runtime/client/src/lib.rs
@@ -22,16 +22,19 @@ use std::sync::Arc;
use std::collections::BTreeMap;
pub use substrate_test_client::*;
pub use polkadot_test_runtime as runtime;
-pub use sc_client::LongestChain;
use sp_core::{sr25519, ChangesTrieConfiguration, map, twox_128};
use sp_core::storage::{ChildInfo, Storage, StorageChild};
use polkadot_test_runtime::genesismap::GenesisConfig;
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, HashFor};
-use sc_client::{
- light::fetcher::{
- RemoteCallRequest, RemoteBodyRequest,
+use sc_consensus::LongestChain;
+use sc_client_api::light::{RemoteCallRequest, RemoteBodyRequest};
+use sc_service::client::{
+ light::{
+ call_executor::GenesisCallExecutor, backend as light_backend,
+ new_light_blockchain, new_light_backend,
},
+ genesis, Client as SubstrateClient, LocalCallExecutor
};
/// A prelude to import in tests.
@@ -57,7 +60,7 @@ sc_executor::native_executor_instance! {
pub type Backend = substrate_test_client::Backend;
/// Test client executor.
-pub type Executor = sc_client::LocalCallExecutor<
+pub type Executor = LocalCallExecutor<
Backend,
NativeExecutor,
>;
@@ -66,10 +69,10 @@ pub type Executor = sc_client::LocalCallExecutor<
pub type LightBackend = substrate_test_client::LightBackend;
/// Test client light executor.
-pub type LightExecutor = sc_client::light::call_executor::GenesisCallExecutor<
+pub type LightExecutor = GenesisCallExecutor<
LightBackend,
- sc_client::LocalCallExecutor<
- sc_client::light::backend::Backend<
+ LocalCallExecutor<
+ light_backend::Backend<
sc_client_db::light::LightStorage,
HashFor
>,
@@ -120,7 +123,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters {
let state_root = <<::Header as HeaderT>::Hashing as HashT>::trie_root(
storage.top.clone().into_iter().chain(child_roots).collect()
);
- let block: runtime::Block = sc_client::genesis::construct_genesis_block(state_root);
+ let block: runtime::Block = genesis::construct_genesis_block(state_root);
storage.top.extend(additional_storage_with_genesis(&block));
storage
@@ -136,9 +139,9 @@ pub type TestClientBuilder = substrate_test_client::TestClientBuilder<
>;
/// Test client type with `LocalExecutor` and generic Backend.
-pub type Client = sc_client::Client<
+pub type Client = SubstrateClient<
B,
- sc_client::LocalCallExecutor>,
+ LocalCallExecutor>,
polkadot_test_runtime::Block,
polkadot_test_runtime::RuntimeApi,
>;
@@ -212,21 +215,21 @@ pub trait TestClientBuilderExt: Sized {
}
/// Build the test client and longest chain selector.
- fn build_with_longest_chain(self) -> (Client, sc_client::LongestChain);
+ fn build_with_longest_chain(self) -> (Client, LongestChain);
/// Build the test client and the backend.
fn build_with_backend(self) -> (Client, Arc);
}
impl TestClientBuilderExt for TestClientBuilder<
- sc_client::LocalCallExecutor>,
+ LocalCallExecutor>,
Backend
> {
fn genesis_init_mut(&mut self) -> &mut GenesisParameters {
Self::genesis_init_mut(self)
}
- fn build_with_longest_chain(self) -> (Client, sc_client::LongestChain) {
+ fn build_with_longest_chain(self) -> (Client, LongestChain) {
self.build_with_native_executor(None)
}
@@ -277,15 +280,25 @@ pub fn new() -> Client {
/// Creates new light client instance used for tests.
pub fn new_light() -> (
- sc_client::Client,
+ SubstrateClient<
+ LightBackend,
+ LightExecutor,
+ polkadot_test_runtime::Block,
+ polkadot_test_runtime::RuntimeApi
+ >,
Arc,
) {
let storage = sc_client_db::light::LightStorage::new_test();
- let blockchain = Arc::new(sc_client::light::blockchain::Blockchain::new(storage));
- let backend = Arc::new(LightBackend::new(blockchain.clone()));
+ let blockchain =new_light_blockchain(storage);
+ let backend = new_light_backend(blockchain.clone());
let executor = new_native_executor();
- let local_call_executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, sp_core::tasks::executor(), Default::default(),);
+ let local_call_executor = LocalCallExecutor::new(
+ backend.clone(),
+ executor,
+ sp_core::tasks::executor(),
+ Default::default()
+ );
let call_executor = LightExecutor::new(
backend.clone(),
local_call_executor,
diff --git a/service/Cargo.toml b/service/Cargo.toml
index fbad3afd043f..7a0094b6ee93 100644
--- a/service/Cargo.toml
+++ b/service/Cargo.toml
@@ -25,11 +25,11 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sc-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-db = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "master" }
grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -37,6 +37,7 @@ grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.co
inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master" }
service = { package = "sc-service", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
telemetry = { package = "sc-telemetry", git = "https://github.com/paritytech/substrate", branch = "master" }
+sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
diff --git a/service/src/chain_spec.rs b/service/src/chain_spec.rs
index 8d8572e7e7e3..4daf3826c948 100644
--- a/service/src/chain_spec.rs
+++ b/service/src/chain_spec.rs
@@ -48,9 +48,9 @@ const DEFAULT_PROTOCOL_ID: &str = "dot";
#[serde(rename_all = "camelCase")]
pub struct Extensions {
/// Block numbers with known hashes.
- pub fork_blocks: sc_client::ForkBlocks,
+ pub fork_blocks: sc_client_api::ForkBlocks,
/// Known bad block hashes.
- pub bad_blocks: sc_client::BadBlocks,
+ pub bad_blocks: sc_client_api::BadBlocks,
}
/// The `ChainSpec parametrised for polkadot runtime`.
diff --git a/service/src/lib.rs b/service/src/lib.rs
index f27f19e1c721..5a684fae6a67 100644
--- a/service/src/lib.rs
+++ b/service/src/lib.rs
@@ -19,7 +19,6 @@
pub mod chain_spec;
mod grandpa_support;
-use sc_client::LongestChain;
use std::sync::Arc;
use std::time::Duration;
use polkadot_primitives::{parachain, Hash, BlockId, AccountId, Nonce, Balance};
@@ -27,21 +26,20 @@ use polkadot_primitives::{parachain, Hash, BlockId, AccountId, Nonce, Balance};
use polkadot_network::{legacy::gossip::Known, protocol as network_protocol};
use service::{error::Error as ServiceError, ServiceBuilder};
use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider};
-use inherents::InherentDataProviders;
use sc_executor::native_executor_instance;
use log::info;
pub use service::{
AbstractService, Role, PruningMode, TransactionPoolOptions, Error, RuntimeGenesis,
TFullClient, TLightClient, TFullBackend, TLightBackend, TFullCallExecutor, TLightCallExecutor,
- Configuration, ChainSpec, ServiceBuilderCommand,
+ Configuration, ChainSpec, ServiceBuilderCommand, ClientProvider,
};
pub use service::config::{DatabaseConfig, PrometheusConfig};
pub use sc_executor::NativeExecutionDispatch;
-pub use sc_client::{ExecutionStrategy, CallExecutor, Client};
-pub use sc_client_api::backend::Backend;
+pub use sc_client_api::{Backend, ExecutionStrategy, CallExecutor};
+pub use sc_consensus::LongestChain;
pub use sp_api::{Core as CoreApi, ConstructRuntimeApi, ProvideRuntimeApi, StateBackend};
pub use sp_runtime::traits::{HashFor, NumberFor};
-pub use consensus_common::SelectChain;
+pub use consensus_common::{SelectChain, BlockImport, block_validation::Chain};
pub use polkadot_primitives::parachain::{CollatorId, ParachainHost};
pub use polkadot_primitives::Block;
pub use sp_runtime::traits::{Block as BlockT, self as runtime_traits, BlakeTwo256};
@@ -76,7 +74,7 @@ native_executor_instance!(
);
/// A set of APIs that polkadot-like runtimes must implement.
-pub trait RuntimeApiCollection :
+pub trait RuntimeApiCollection:
sp_transaction_pool::runtime_api::TaggedTransactionQueue
+ sp_api::ApiExt
+ babe_primitives::BabeApi
@@ -156,7 +154,7 @@ macro_rules! new_full_start {
Block, $runtime, $executor
>($config)?
.with_select_chain(|_, backend| {
- Ok(sc_client::LongestChain::new(backend.clone()))
+ Ok(sc_consensus::LongestChain::new(backend.clone()))
})?
.with_transaction_pool(|config, client, _fetcher, prometheus_registry| {
let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
@@ -209,6 +207,352 @@ macro_rules! new_full_start {
}}
}
+/// Builds a new service for a full client.
+#[macro_export]
+macro_rules! new_full {
+ (
+ $config:expr,
+ $collating_for:expr,
+ $max_block_data_size:expr,
+ $authority_discovery_enabled:expr,
+ $slot_duration:expr,
+ $grandpa_pause:expr,
+ $runtime:ty,
+ $dispatch:ty
+ ) => {{
+ use sc_network::Event;
+ use sc_client_api::ExecutorProvider;
+ use futures::stream::StreamExt;
+
+ let is_collator = $collating_for.is_some();
+ let role = $config.role.clone();
+ let is_authority = role.is_authority() && !is_collator;
+ let force_authoring = $config.force_authoring;
+ let max_block_data_size = $max_block_data_size;
+ let db_path = match $config.database.path() {
+ Some(path) => std::path::PathBuf::from(path),
+ None => return Err("Starting a Polkadot service with a custom database isn't supported".to_string().into()),
+ };
+ let disable_grandpa = $config.disable_grandpa;
+ let name = $config.network.node_name.clone();
+ let authority_discovery_enabled = $authority_discovery_enabled;
+ let slot_duration = $slot_duration;
+
+ let (builder, mut import_setup, inherent_data_providers) = new_full_start!($config, $runtime, $dispatch);
+
+ let backend = builder.backend().clone();
+
+ let service = builder
+ .with_finality_proof_provider(|client, backend| {
+ let provider = client as Arc>;
+ Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
+ })?
+ .build()?;
+
+ let (block_import, link_half, babe_link) = import_setup.take()
+ .expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
+
+ let client = service.client();
+ let known_oracle = client.clone();
+
+ let mut handles = FullNodeHandles::default();
+ let select_chain = if let Some(select_chain) = service.select_chain() {
+ select_chain
+ } else {
+ info!("The node cannot start as an authority because it can't select chain.");
+ return Ok((service, client, handles));
+ };
+ let gossip_validator_select_chain = select_chain.clone();
+
+ let is_known = move |block_hash: &Hash| {
+ use consensus_common::BlockStatus;
+
+ match known_oracle.block_status(&BlockId::hash(*block_hash)) {
+ Err(_) | Ok(BlockStatus::Unknown) | Ok(BlockStatus::Queued) => None,
+ Ok(BlockStatus::KnownBad) => Some(Known::Bad),
+ Ok(BlockStatus::InChainWithState) | Ok(BlockStatus::InChainPruned) => {
+ match gossip_validator_select_chain.leaves() {
+ Err(_) => None,
+ Ok(leaves) => if leaves.contains(block_hash) {
+ Some(Known::Leaf)
+ } else {
+ Some(Known::Old)
+ },
+ }
+ }
+ }
+ };
+
+ let polkadot_network_service = network_protocol::start(
+ service.network(),
+ network_protocol::Config {
+ collating_for: $collating_for,
+ },
+ (is_known, client.clone()),
+ client.clone(),
+ service.spawn_task_handle(),
+ ).map_err(|e| format!("Could not spawn network worker: {:?}", e))?;
+
+ let authority_handles = if is_collator || role.is_authority() {
+ let availability_store = {
+ use std::path::PathBuf;
+
+ let mut path = PathBuf::from(db_path);
+ path.push("availability");
+
+ #[cfg(not(target_os = "unknown"))]
+ {
+ av_store::Store::new(
+ ::av_store::Config {
+ cache_size: None,
+ path,
+ },
+ polkadot_network_service.clone(),
+ )?
+ }
+
+ #[cfg(target_os = "unknown")]
+ av_store::Store::new_in_memory(gossip)
+ };
+
+ polkadot_network_service.register_availability_store(availability_store.clone());
+
+ let (validation_service_handle, validation_service) = consensus::ServiceBuilder {
+ client: client.clone(),
+ network: polkadot_network_service.clone(),
+ collators: polkadot_network_service.clone(),
+ spawner: service.spawn_task_handle(),
+ availability_store: availability_store.clone(),
+ select_chain: select_chain.clone(),
+ keystore: service.keystore(),
+ max_block_data_size,
+ }.build();
+
+ service.spawn_essential_task("validation-service", Box::pin(validation_service));
+
+ handles.validation_service_handle = Some(validation_service_handle.clone());
+
+ Some((validation_service_handle, availability_store))
+ } else {
+ None
+ };
+
+ if role.is_authority() {
+ let (validation_service_handle, availability_store) = authority_handles
+ .clone()
+ .expect("Authority handles are set for authority nodes; qed");
+
+ let proposer = consensus::ProposerFactory::new(
+ client.clone(),
+ service.transaction_pool(),
+ validation_service_handle,
+ slot_duration,
+ backend,
+ );
+
+ let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?;
+ let can_author_with =
+ consensus_common::CanAuthorWithNativeVersion::new(client.executor().clone());
+
+ let block_import = availability_store.block_import(
+ block_import,
+ client.clone(),
+ service.spawn_task_handle(),
+ service.keystore(),
+ )?;
+
+ let babe_config = babe::BabeParams {
+ keystore: service.keystore(),
+ client: client.clone(),
+ select_chain,
+ block_import,
+ env: proposer,
+ sync_oracle: service.network(),
+ inherent_data_providers: inherent_data_providers.clone(),
+ force_authoring,
+ babe_link,
+ can_author_with,
+ };
+
+ let babe = babe::start_babe(babe_config)?;
+ service.spawn_essential_task("babe", babe);
+ }
+
+ if matches!(role, Role::Authority{..} | Role::Sentry{..}) {
+ if authority_discovery_enabled {
+ let (sentries, authority_discovery_role) = match role {
+ Role::Authority { ref sentry_nodes } => (
+ sentry_nodes.clone(),
+ authority_discovery::Role::Authority (
+ service.keystore(),
+ ),
+ ),
+ Role::Sentry {..} => (
+ vec![],
+ authority_discovery::Role::Sentry,
+ ),
+ _ => unreachable!("Due to outer matches! constraint; qed."),
+ };
+
+ let network = service.network();
+ let network_event_stream = network.event_stream("authority-discovery");
+ let dht_event_stream = network_event_stream.filter_map(|e| async move { match e {
+ Event::Dht(e) => Some(e),
+ _ => None,
+ }}).boxed();
+ let authority_discovery = authority_discovery::AuthorityDiscovery::new(
+ service.client(),
+ network,
+ sentries,
+ dht_event_stream,
+ authority_discovery_role,
+ service.prometheus_registry(),
+ );
+
+ service.spawn_task("authority-discovery", authority_discovery);
+ }
+ }
+
+ // if the node isn't actively participating in consensus then it doesn't
+ // need a keystore, regardless of which protocol we use below.
+ let keystore = if is_authority {
+ Some(service.keystore())
+ } else {
+ None
+ };
+
+ let config = grandpa::Config {
+ // FIXME substrate#1578 make this available through chainspec
+ gossip_duration: Duration::from_millis(1000),
+ justification_period: 512,
+ name: Some(name),
+ observer_enabled: false,
+ keystore,
+ is_authority: role.is_network_authority(),
+ };
+
+ let enable_grandpa = !disable_grandpa;
+ if enable_grandpa {
+ // start the full GRANDPA voter
+ // NOTE: unlike in substrate we are currently running the full
+ // GRANDPA voter protocol for all full nodes (regardless of whether
+ // they're validators or not). at this point the full voter should
+ // provide better guarantees of block and vote data availability than
+ // the observer.
+
+ // add a custom voting rule to temporarily stop voting for new blocks
+ // after the given pause block is finalized and restarting after the
+ // given delay.
+ let voting_rule = match $grandpa_pause {
+ Some((block, delay)) => {
+ info!("GRANDPA scheduled voting pause set for block #{} with a duration of {} blocks.",
+ block,
+ delay,
+ );
+
+ grandpa::VotingRulesBuilder::default()
+ .add(grandpa_support::PauseAfterBlockFor(block, delay))
+ .build()
+ },
+ None =>
+ grandpa::VotingRulesBuilder::default()
+ .build(),
+ };
+
+ let grandpa_config = grandpa::GrandpaParams {
+ config,
+ link: link_half,
+ network: service.network(),
+ inherent_data_providers: inherent_data_providers.clone(),
+ telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
+ voting_rule,
+ prometheus_registry: service.prometheus_registry(),
+ };
+
+ service.spawn_essential_task(
+ "grandpa-voter",
+ grandpa::run_grandpa_voter(grandpa_config)?
+ );
+ } else {
+ grandpa::setup_disabled_grandpa(
+ client.clone(),
+ &inherent_data_providers,
+ service.network(),
+ )?;
+ }
+
+ handles.polkadot_network = Some(polkadot_network_service);
+ (service, client, handles)
+ }}
+}
+
+/// Builds a new service for a light client.
+#[macro_export]
+macro_rules! new_light {
+ ($config:expr, $runtime:ty, $dispatch:ty) => {{
+ crate::set_prometheus_registry(&mut $config)?;
+ let inherent_data_providers = inherents::InherentDataProviders::new();
+
+ ServiceBuilder::new_light::($config)?
+ .with_select_chain(|_, backend| {
+ Ok(sc_consensus::LongestChain::new(backend.clone()))
+ })?
+ .with_transaction_pool(|config, client, fetcher, prometheus_registry| {
+ let fetcher = fetcher
+ .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
+ let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone());
+ let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
+ config, Arc::new(pool_api), prometheus_registry, sc_transaction_pool::RevalidationType::Light,
+ );
+ Ok(pool)
+ })?
+ .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _| {
+ let fetch_checker = fetcher
+ .map(|fetcher| fetcher.checker().clone())
+ .ok_or_else(|| "Trying to start light import queue without active fetch checker")?;
+ let grandpa_block_import = grandpa::light_block_import(
+ client.clone(), backend, &(client.clone() as Arc<_>), Arc::new(fetch_checker)
+ )?;
+
+ let finality_proof_import = grandpa_block_import.clone();
+ let finality_proof_request_builder =
+ finality_proof_import.create_finality_proof_request_builder();
+
+ let (babe_block_import, babe_link) = babe::block_import(
+ babe::Config::get_or_compute(&*client)?,
+ grandpa_block_import,
+ client.clone(),
+ )?;
+
+ // FIXME: pruning task isn't started since light client doesn't do `AuthoritySetup`.
+ let import_queue = babe::import_queue(
+ babe_link,
+ babe_block_import,
+ None,
+ Some(Box::new(finality_proof_import)),
+ client,
+ inherent_data_providers.clone(),
+ )?;
+
+ Ok((import_queue, finality_proof_request_builder))
+ })?
+ .with_finality_proof_provider(|client, backend| {
+ let provider = client as Arc>;
+ Ok(Arc::new(grandpa::FinalityProofProvider::new(backend, provider)) as _)
+ })?
+ .with_rpc_extensions(|builder|
+ -> Result {
+ let fetcher = builder.fetcher()
+ .ok_or_else(|| "Trying to start node RPC without active fetcher")?;
+ let remote_blockchain = builder.remote_backend()
+ .ok_or_else(|| "Trying to start node RPC without active remote blockchain")?;
+
+ Ok(polkadot_rpc::create_light(builder.client().clone(), remote_blockchain, fetcher, builder.pool()))
+ })?
+ .build()
+ }}
+}
+
/// Builds a new object suitable for chain operations.
pub fn new_chain_ops(mut config: Configuration)
-> Result, ServiceError>
@@ -227,7 +571,7 @@ where
/// Create a new Polkadot service for a full node.
#[cfg(feature = "full-node")]
pub fn polkadot_new_full(
- config: Configuration,
+ mut config: Configuration,
collating_for: Option<(CollatorId, parachain::Id)>,
max_block_data_size: Option,
authority_discovery_enabled: bool,
@@ -235,61 +579,69 @@ pub fn polkadot_new_full(
grandpa_pause: Option<(u32, u32)>,
)
-> Result<(
- impl AbstractService<
- Block = Block,
- RuntimeApi = polkadot_runtime::RuntimeApi,
- Backend = TFullBackend,
- SelectChain = LongestChain, Block>,
- CallExecutor = TFullCallExecutor,
- >,
+ impl AbstractService,
+ Arc,
+ TFullCallExecutor,
+ polkadot_runtime::RuntimeApi
+ >>,
FullNodeHandles,
), ServiceError>
{
- new_full(
+ let (service, client, handles) = new_full!(
config,
collating_for,
max_block_data_size,
authority_discovery_enabled,
slot_duration,
grandpa_pause,
- )
+ polkadot_runtime::RuntimeApi,
+ PolkadotExecutor
+ );
+
+ Ok((service, client, handles))
}
/// Create a new Kusama service for a full node.
#[cfg(feature = "full-node")]
pub fn kusama_new_full(
- config: Configuration,
+ mut config: Configuration,
collating_for: Option<(CollatorId, parachain::Id)>,
max_block_data_size: Option,
authority_discovery_enabled: bool,
slot_duration: u64,
grandpa_pause: Option<(u32, u32)>,
-)
- -> Result<(
- impl AbstractService<
- Block = Block,
- RuntimeApi = kusama_runtime::RuntimeApi,
- Backend = TFullBackend,
- SelectChain = LongestChain, Block>,
- CallExecutor = TFullCallExecutor,
+) -> Result<(
+ impl AbstractService,
+ Arc,
+ TFullCallExecutor,
+ kusama_runtime::RuntimeApi
+ >
>,
- FullNodeHandles,
+ FullNodeHandles
), ServiceError>
{
- new_full(
+ let (service, client, handles) = new_full!(
config,
collating_for,
max_block_data_size,
authority_discovery_enabled,
slot_duration,
grandpa_pause,
- )
+ kusama_runtime::RuntimeApi,
+ KusamaExecutor
+ );
+
+ Ok((service, client, handles))
}
/// Create a new Kusama service for a full node.
#[cfg(feature = "full-node")]
pub fn westend_new_full(
- config: Configuration,
+ mut config: Configuration,
collating_for: Option<(CollatorId, parachain::Id)>,
max_block_data_size: Option,
authority_discovery_enabled: bool,
@@ -297,24 +649,28 @@ pub fn westend_new_full(
grandpa_pause: Option<(u32, u32)>,
)
-> Result<(
- impl AbstractService<
- Block = Block,
- RuntimeApi = westend_runtime::RuntimeApi,
- Backend = TFullBackend,
- SelectChain = LongestChain, Block>,
- CallExecutor = TFullCallExecutor,
- >,
+ impl AbstractService,
+ Arc,
+ TFullCallExecutor,
+ westend_runtime::RuntimeApi
+ >>,
FullNodeHandles,
), ServiceError>
{
- new_full(
+ let (service, client, handles) = new_full!(
config,
collating_for,
max_block_data_size,
authority_discovery_enabled,
slot_duration,
grandpa_pause,
- )
+ westend_runtime::RuntimeApi,
+ KusamaExecutor
+ );
+
+ Ok((service, client, handles))
}
/// Handles to other sub-services that full nodes instantiate, which consumers
@@ -328,305 +684,9 @@ pub struct FullNodeHandles {
pub validation_service_handle: Option,
}
-/// Builds a new service for a full client.
-#[cfg(feature = "full-node")]
-pub fn new_full(
- mut config: Configuration,
- collating_for: Option<(CollatorId, parachain::Id)>,
- max_block_data_size: Option,
- authority_discovery_enabled: bool,
- slot_duration: u64,
- grandpa_pause: Option<(u32, u32)>,
-)
- -> Result<(
- impl AbstractService<
- Block = Block,
- RuntimeApi = Runtime,
- Backend = TFullBackend,
- SelectChain = LongestChain, Block>,
- CallExecutor = TFullCallExecutor,
- >,
- FullNodeHandles,
- ), ServiceError>
- where
- Runtime: ConstructRuntimeApi> + Send + Sync + 'static,
- Runtime::RuntimeApi:
- RuntimeApiCollection, Block>>,
- Dispatch: NativeExecutionDispatch + 'static,
- Extrinsic: RuntimeExtrinsic,
- // Rust bug: https://github.com/rust-lang/rust/issues/24159
- >::StateBackend: sp_api::StateBackend,
-{
- use sc_network::Event;
- use sc_client_api::ExecutorProvider;
- use futures::stream::StreamExt;
-
- let is_collator = collating_for.is_some();
- let role = config.role.clone();
- let is_authority = role.is_authority() && !is_collator;
- let force_authoring = config.force_authoring;
- let max_block_data_size = max_block_data_size;
- let db_path = match config.database.path() {
- Some(path) => std::path::PathBuf::from(path),
- None => return Err("Starting a Polkadot service with a custom database isn't supported".to_string().into()),
- };
- let disable_grandpa = config.disable_grandpa;
- let name = config.network.node_name.clone();
- let authority_discovery_enabled = authority_discovery_enabled;
- let slot_duration = slot_duration;
-
- let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config, Runtime, Dispatch);
-
- let backend = builder.backend().clone();
-
- let service = builder
- .with_finality_proof_provider(|client, backend| {
- let provider = client as Arc>;
- Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
- })?
- .build()?;
-
- let (block_import, link_half, babe_link) = import_setup.take()
- .expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
-
- let client = service.client();
- let known_oracle = client.clone();
-
- let mut handles = FullNodeHandles::default();
- let select_chain = if let Some(select_chain) = service.select_chain() {
- select_chain
- } else {
- info!("The node cannot start as an authority because it can't select chain.");
- return Ok((service, handles));
- };
- let gossip_validator_select_chain = select_chain.clone();
-
- let is_known = move |block_hash: &Hash| {
- use consensus_common::BlockStatus;
-
- match known_oracle.block_status(&BlockId::hash(*block_hash)) {
- Err(_) | Ok(BlockStatus::Unknown) | Ok(BlockStatus::Queued) => None,
- Ok(BlockStatus::KnownBad) => Some(Known::Bad),
- Ok(BlockStatus::InChainWithState) | Ok(BlockStatus::InChainPruned) => {
- match gossip_validator_select_chain.leaves() {
- Err(_) => None,
- Ok(leaves) => if leaves.contains(block_hash) {
- Some(Known::Leaf)
- } else {
- Some(Known::Old)
- },
- }
- }
- }
- };
-
- let polkadot_network_service = network_protocol::start(
- service.network(),
- network_protocol::Config {
- collating_for,
- },
- (is_known, client.clone()),
- client.clone(),
- service.spawn_task_handle(),
- ).map_err(|e| format!("Could not spawn network worker: {:?}", e))?;
-
- let authority_handles = if is_collator || role.is_authority() {
- let availability_store = {
- use std::path::PathBuf;
-
- let mut path = PathBuf::from(db_path);
- path.push("availability");
-
- #[cfg(not(target_os = "unknown"))]
- {
- av_store::Store::new(
- ::av_store::Config {
- cache_size: None,
- path,
- },
- polkadot_network_service.clone(),
- )?
- }
-
- #[cfg(target_os = "unknown")]
- av_store::Store::new_in_memory(gossip)
- };
-
- polkadot_network_service.register_availability_store(availability_store.clone());
-
- let (validation_service_handle, validation_service) = consensus::ServiceBuilder {
- client: client.clone(),
- network: polkadot_network_service.clone(),
- collators: polkadot_network_service.clone(),
- spawner: service.spawn_task_handle(),
- availability_store: availability_store.clone(),
- select_chain: select_chain.clone(),
- keystore: service.keystore(),
- max_block_data_size,
- }.build();
-
- service.spawn_essential_task("validation-service", Box::pin(validation_service));
-
- handles.validation_service_handle = Some(validation_service_handle.clone());
-
- Some((validation_service_handle, availability_store))
- } else {
- None
- };
-
- if role.is_authority() {
- let (validation_service_handle, availability_store) = authority_handles
- .clone()
- .expect("Authority handles are set for authority nodes; qed");
-
- let proposer = consensus::ProposerFactory::new(
- client.clone(),
- service.transaction_pool(),
- validation_service_handle,
- slot_duration,
- backend,
- );
-
- let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?;
- let can_author_with =
- consensus_common::CanAuthorWithNativeVersion::new(client.executor().clone());
-
- let block_import = availability_store.block_import(
- block_import,
- client.clone(),
- service.spawn_task_handle(),
- service.keystore(),
- )?;
-
- let babe_config = babe::BabeParams {
- keystore: service.keystore(),
- client,
- select_chain,
- block_import,
- env: proposer,
- sync_oracle: service.network(),
- inherent_data_providers: inherent_data_providers.clone(),
- force_authoring,
- babe_link,
- can_author_with,
- };
-
- let babe = babe::start_babe(babe_config)?;
- service.spawn_essential_task("babe", babe);
- }
-
- if matches!(role, Role::Authority{..} | Role::Sentry{..}) {
- if authority_discovery_enabled {
- let (sentries, authority_discovery_role) = match role {
- Role::Authority { ref sentry_nodes } => (
- sentry_nodes.clone(),
- authority_discovery::Role::Authority (
- service.keystore(),
- ),
- ),
- Role::Sentry {..} => (
- vec![],
- authority_discovery::Role::Sentry,
- ),
- _ => unreachable!("Due to outer matches! constraint; qed."),
- };
-
- let network = service.network();
- let network_event_stream = network.event_stream("authority-discovery");
- let dht_event_stream = network_event_stream.filter_map(|e| async move { match e {
- Event::Dht(e) => Some(e),
- _ => None,
- }}).boxed();
- let authority_discovery = authority_discovery::AuthorityDiscovery::new(
- service.client(),
- network,
- sentries,
- dht_event_stream,
- authority_discovery_role,
- service.prometheus_registry(),
- );
-
- service.spawn_task("authority-discovery", authority_discovery);
- }
- }
-
- // if the node isn't actively participating in consensus then it doesn't
- // need a keystore, regardless of which protocol we use below.
- let keystore = if is_authority {
- Some(service.keystore())
- } else {
- None
- };
-
- let config = grandpa::Config {
- // FIXME substrate#1578 make this available through chainspec
- gossip_duration: Duration::from_millis(1000),
- justification_period: 512,
- name: Some(name),
- observer_enabled: false,
- keystore,
- is_authority: role.is_network_authority(),
- };
-
- let enable_grandpa = !disable_grandpa;
- if enable_grandpa {
- // start the full GRANDPA voter
- // NOTE: unlike in substrate we are currently running the full
- // GRANDPA voter protocol for all full nodes (regardless of whether
- // they're validators or not). at this point the full voter should
- // provide better guarantees of block and vote data availability than
- // the observer.
-
- // add a custom voting rule to temporarily stop voting for new blocks
- // after the given pause block is finalized and restarting after the
- // given delay.
- let voting_rule = match grandpa_pause {
- Some((block, delay)) => {
- info!("GRANDPA scheduled voting pause set for block #{} with a duration of {} blocks.",
- block,
- delay,
- );
-
- grandpa::VotingRulesBuilder::default()
- .add(grandpa_support::PauseAfterBlockFor(block, delay))
- .build()
- },
- None =>
- grandpa::VotingRulesBuilder::default()
- .build(),
- };
-
- let grandpa_config = grandpa::GrandpaParams {
- config,
- link: link_half,
- network: service.network(),
- inherent_data_providers: inherent_data_providers.clone(),
- telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
- voting_rule,
- prometheus_registry: service.prometheus_registry(),
- };
-
- service.spawn_essential_task(
- "grandpa-voter",
- grandpa::run_grandpa_voter(grandpa_config)?
- );
- } else {
- grandpa::setup_disabled_grandpa(
- service.client(),
- &inherent_data_providers,
- service.network(),
- )?;
- }
-
- handles.polkadot_network = Some(polkadot_network_service);
- Ok((service, handles))
-}
-
/// Create a new Polkadot service for a light client.
-pub fn polkadot_new_light(
- config: Configuration,
-)
- -> Result Result<
+ impl AbstractService<
Block = Block,
RuntimeApi = polkadot_runtime::RuntimeApi,
Backend = TLightBackend,
@@ -634,14 +694,12 @@ pub fn polkadot_new_light(
CallExecutor = TLightCallExecutor,
>, ServiceError>
{
- new_light(config)
+ new_light!(config, polkadot_runtime::RuntimeApi, PolkadotExecutor)
}
/// Create a new Kusama service for a light client.
-pub fn kusama_new_light(
- config: Configuration,
-)
- -> Result Result<
+ impl AbstractService<
Block = Block,
RuntimeApi = kusama_runtime::RuntimeApi,
Backend = TLightBackend,
@@ -649,125 +707,19 @@ pub fn kusama_new_light(
CallExecutor = TLightCallExecutor,
>, ServiceError>
{
- new_light(config)
+ new_light!(config, kusama_runtime::RuntimeApi, KusamaExecutor)
}
/// Create a new Westend service for a light client.
-pub fn westend_new_light(
- config: Configuration,
-)
- -> Result Result<
+ impl AbstractService<
Block = Block,
RuntimeApi = westend_runtime::RuntimeApi,
Backend = TLightBackend,
SelectChain = LongestChain, Block>,
- CallExecutor = TLightCallExecutor,
- >, ServiceError>
-{
- new_light(config)
-}
-
-// We can't use service::TLightClient due to
-// Rust bug: https://github.com/rust-lang/rust/issues/43580
-type TLocalLightClient = Client<
- sc_client::light::backend::Backend, BlakeTwo256>,
- sc_client::light::call_executor::GenesisCallExecutor<
- sc_client::light::backend::Backend, BlakeTwo256>,
- sc_client::LocalCallExecutor<
- sc_client::light::backend::Backend<
- sc_client_db::light::LightStorage,
- BlakeTwo256
- >,
- sc_executor::NativeExecutor
- >
- >,
- Block,
- Runtime
->;
-
-/// Builds a new service for a light client.
-pub fn new_light(
- mut config: Configuration,
-)
- -> Result,
- SelectChain = LongestChain, Block>,
- CallExecutor = TLightCallExecutor,
- >, ServiceError>
-where
- Runtime: Send + Sync + 'static,
- Runtime::RuntimeApi: RuntimeApiCollection<
- Extrinsic,
- StateBackend = sc_client_api::StateBackendFor, Block>
- >,
- Dispatch: NativeExecutionDispatch + 'static,
- Extrinsic: RuntimeExtrinsic,
- Runtime: sp_api::ConstructRuntimeApi<
- Block,
- TLocalLightClient,
+ CallExecutor = TLightCallExecutor
>,
+ ServiceError>
{
- set_prometheus_registry(&mut config)?;
-
- let inherent_data_providers = InherentDataProviders::new();
-
- ServiceBuilder::new_light::(config)?
- .with_select_chain(|_, backend| {
- Ok(LongestChain::new(backend.clone()))
- })?
- .with_transaction_pool(|config, client, fetcher, prometheus_registry| {
- let fetcher = fetcher
- .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
- let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone());
- let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
- config, Arc::new(pool_api), prometheus_registry, sc_transaction_pool::RevalidationType::Light,
- );
- Ok(pool)
- })?
- .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _| {
- let fetch_checker = fetcher
- .map(|fetcher| fetcher.checker().clone())
- .ok_or_else(|| "Trying to start light import queue without active fetch checker")?;
- let grandpa_block_import = grandpa::light_block_import(
- client.clone(), backend, &(client.clone() as Arc<_>), Arc::new(fetch_checker)
- )?;
-
- let finality_proof_import = grandpa_block_import.clone();
- let finality_proof_request_builder =
- finality_proof_import.create_finality_proof_request_builder();
-
- let (babe_block_import, babe_link) = babe::block_import(
- babe::Config::get_or_compute(&*client)?,
- grandpa_block_import,
- client.clone(),
- )?;
-
- // FIXME: pruning task isn't started since light client doesn't do `AuthoritySetup`.
- let import_queue = babe::import_queue(
- babe_link,
- babe_block_import,
- None,
- Some(Box::new(finality_proof_import)),
- client,
- inherent_data_providers.clone(),
- )?;
-
- Ok((import_queue, finality_proof_request_builder))
- })?
- .with_finality_proof_provider(|client, backend| {
- let provider = client as Arc>;
- Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
- })?
- .with_rpc_extensions(|builder|
- -> Result {
- let fetcher = builder.fetcher()
- .ok_or_else(|| "Trying to start node RPC without active fetcher")?;
- let remote_blockchain = builder.remote_backend()
- .ok_or_else(|| "Trying to start node RPC without active remote blockchain")?;
-
- Ok(polkadot_rpc::create_light(builder.client().clone(), remote_blockchain, fetcher, builder.pool()))
- })?
- .build()
+ new_light!(config, westend_runtime::RuntimeApi, KusamaExecutor)
}