// Copyright 2017-2019 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 .
//! Substrate service components.
use std::{sync::Arc, net::SocketAddr, ops::Deref, ops::DerefMut};
use serde::{Serialize, de::DeserializeOwned};
use tokio::runtime::TaskExecutor;
use crate::chain_spec::ChainSpec;
use client_db;
use client::{self, Client, runtime_api};
use crate::{error, Service, maybe_start_server};
use consensus_common::{import_queue::ImportQueue, SelectChain};
use network::{self, OnDemand, FinalityProofProvider};
use substrate_executor::{NativeExecutor, NativeExecutionDispatch};
use transaction_pool::txpool::{self, Options as TransactionPoolOptions, Pool as TransactionPool};
use runtime_primitives::{
BuildStorage, traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi}, generic::BlockId
};
use crate::config::Configuration;
use primitives::{Blake2Hasher, H256};
use rpc::{self, apis::system::SystemInfo};
use parking_lot::Mutex;
// Type aliases.
// These exist mainly to avoid typing `::Foo` all over the code.
/// Network service type for a factory.
pub type NetworkService =
network::NetworkService<::Block, ::NetworkProtocol>;
/// Code executor type for a factory.
pub type CodeExecutor = NativeExecutor<::RuntimeDispatch>;
/// Full client backend type for a factory.
pub type FullBackend = client_db::Backend<::Block>;
/// Full client executor type for a factory.
pub type FullExecutor = client::LocalCallExecutor<
client_db::Backend<::Block>,
CodeExecutor,
>;
/// Light client backend type for a factory.
pub type LightBackend = client::light::backend::Backend<
client_db::light::LightStorage<::Block>,
network::OnDemand<::Block>,
Blake2Hasher,
>;
/// Light client executor type for a factory.
pub type LightExecutor = client::light::call_executor::RemoteOrLocalCallExecutor<
::Block,
client::light::backend::Backend<
client_db::light::LightStorage<::Block>,
network::OnDemand<::Block>,
Blake2Hasher
>,
client::light::call_executor::RemoteCallExecutor<
client::light::blockchain::Blockchain<
client_db::light::LightStorage<::Block>,
network::OnDemand<::Block>
>,
network::OnDemand<::Block>,
>,
client::LocalCallExecutor<
client::light::backend::Backend<
client_db::light::LightStorage<::Block>,
network::OnDemand<::Block>,
Blake2Hasher
>,
CodeExecutor
>
>;
/// Full client type for a factory.
pub type FullClient = Client, FullExecutor, ::Block, ::RuntimeApi>;
/// Light client type for a factory.
pub type LightClient = Client, LightExecutor, ::Block, ::RuntimeApi>;
/// `ChainSpec` specialization for a factory.
pub type FactoryChainSpec = ChainSpec<::Genesis>;
/// `Genesis` specialization for a factory.
pub type FactoryGenesis = ::Genesis;
/// `Block` type for a factory.
pub type FactoryBlock = ::Block;
/// `Extrinsic` type for a factory.
pub type FactoryExtrinsic = <::Block as BlockT>::Extrinsic;
/// `Number` type for a factory.
pub type FactoryBlockNumber = < as BlockT>::Header as HeaderT>::Number;
/// Full `Configuration` type for a factory.
pub type FactoryFullConfiguration = Configuration<::Configuration, FactoryGenesis>;
/// Client type for `Components`.
pub type ComponentClient = Client<
::Backend,
::Executor,
FactoryBlock<::Factory>,
::RuntimeApi,
>;
/// Block type for `Components`
pub type ComponentBlock = <::Factory as ServiceFactory>::Block;
/// Extrinsic hash type for `Components`
pub type ComponentExHash = <::TransactionPoolApi as txpool::ChainApi>::Hash;
/// Extrinsic type.
pub type ComponentExtrinsic = as BlockT>::Extrinsic;
/// Extrinsic pool API type for `Components`.
pub type PoolApi = ::TransactionPoolApi;
/// A set of traits for the runtime genesis config.
pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {}
impl RuntimeGenesis for T {}
/// Something that can start the RPC service.
pub trait StartRPC {
type ServersHandle: Send + Sync;
fn start_rpc(
client: Arc>,
network: Arc>>,
should_have_peers: bool,
system_info: SystemInfo,
rpc_http: Option,
rpc_ws: Option,
rpc_ws_max_connections: Option,
rpc_cors: Option>,
task_executor: TaskExecutor,
transaction_pool: Arc>,
) -> error::Result;
}
impl StartRPC for C where
ComponentClient: ProvideRuntimeApi,
as ProvideRuntimeApi>::Api: runtime_api::Metadata>,
{
type ServersHandle = (Option, Option>);
fn start_rpc(
client: Arc>,
network: Arc>>,
should_have_peers: bool,
rpc_system_info: SystemInfo,
rpc_http: Option,
rpc_ws: Option,
rpc_ws_max_connections: Option,
rpc_cors: Option>,
task_executor: TaskExecutor,
transaction_pool: Arc>,
) -> error::Result {
let handler = || {
let client = client.clone();
let subscriptions = rpc::apis::Subscriptions::new(task_executor.clone());
let chain = rpc::apis::chain::Chain::new(client.clone(), subscriptions.clone());
let state = rpc::apis::state::State::new(client.clone(), subscriptions.clone());
let author = rpc::apis::author::Author::new(
client.clone(), transaction_pool.clone(), subscriptions
);
let system = rpc::apis::system::System::new(
rpc_system_info.clone(), network.clone(), should_have_peers
);
rpc::rpc_handler::, ComponentExHash, _, _, _, _>(
state,
chain,
author,
system,
)
};
Ok((
maybe_start_server(
rpc_http,
|address| rpc::start_http(address, rpc_cors.as_ref(), handler()),
)?,
maybe_start_server(
rpc_ws,
|address| rpc::start_ws(
address,
rpc_ws_max_connections,
rpc_cors.as_ref(),
handler(),
),
)?.map(Mutex::new),
))
}
}
/// Something that can maintain transaction pool on every imported block.
pub trait MaintainTransactionPool {
fn maintain_transaction_pool(
id: &BlockId>,
client: &ComponentClient,
transaction_pool: &TransactionPool,
) -> error::Result<()>;
}
fn maintain_transaction_pool(
id: &BlockId,
client: &Client,
transaction_pool: &TransactionPool,
) -> error::Result<()> where
Block: BlockT::Out>,
Backend: client::backend::Backend,
Client: ProvideRuntimeApi,
as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue,
Executor: client::CallExecutor,
PoolApi: txpool::ChainApi,
{
// Avoid calling into runtime if there is nothing to prune from the pool anyway.
if transaction_pool.status().is_empty() {
return Ok(())
}
if let Some(block) = client.block(id)? {
let parent_id = BlockId::hash(*block.block.header().parent_hash());
let extrinsics = block.block.extrinsics();
transaction_pool.prune(id, &parent_id, extrinsics).map_err(|e| format!("{:?}", e))?;
}
Ok(())
}
impl MaintainTransactionPool for C where
ComponentClient: ProvideRuntimeApi,
as ProvideRuntimeApi>::Api: runtime_api::TaggedTransactionQueue>,
{
fn maintain_transaction_pool(
id: &BlockId>,
client: &ComponentClient,
transaction_pool: &TransactionPool,
) -> error::Result<()> {
maintain_transaction_pool(id, client, transaction_pool)
}
}
pub trait OffchainWorker {
fn offchain_workers(
number: &FactoryBlockNumber,
offchain: &offchain::OffchainWorkers, ComponentBlock>,
pool: &Arc>,
) -> error::Result<()>;
}
impl OffchainWorker for C where
ComponentClient: ProvideRuntimeApi,
as ProvideRuntimeApi>::Api: offchain::OffchainWorkerApi>,
{
fn offchain_workers(
number: &FactoryBlockNumber,
offchain: &offchain::OffchainWorkers, ComponentBlock>,
pool: &Arc>,
) -> error::Result<()> {
Ok(offchain.on_block_imported(number, pool))
}
}
/// The super trait that combines all required traits a `Service` needs to implement.
pub trait ServiceTrait:
Deref>
+ Send
+ Sync
+ 'static
+ StartRPC
+ MaintainTransactionPool
+ OffchainWorker
{}
impl ServiceTrait for T where
T: Deref>
+ Send
+ Sync
+ 'static
+ StartRPC
+ MaintainTransactionPool
+ OffchainWorker
{}
/// A collection of types and methods to build a service on top of the substrate service.
pub trait ServiceFactory: 'static + Sized {
/// Block type.
type Block: BlockT;
/// The type that implements the runtime API.
type RuntimeApi: Send + Sync;
/// Network protocol extensions.
type NetworkProtocol: network::specialization::NetworkSpecialization;
/// Chain runtime.
type RuntimeDispatch: NativeExecutionDispatch + Send + Sync + 'static;
/// Extrinsic pool backend type for the full client.
type FullTransactionPoolApi: txpool::ChainApi::Hash, Block = Self::Block> + Send + 'static;
/// Extrinsic pool backend type for the light client.
type LightTransactionPoolApi: txpool::ChainApi::Hash, Block = Self::Block> + 'static;
/// Genesis configuration for the runtime.
type Genesis: RuntimeGenesis;
/// Other configuration for service members.
type Configuration: Default;
/// Extended full service type.
type FullService: ServiceTrait>;
/// Extended light service type.
type LightService: ServiceTrait>;
/// ImportQueue for full client
type FullImportQueue: ImportQueue + 'static;
/// ImportQueue for light clients
type LightImportQueue: ImportQueue + 'static;
/// The Fork Choice Strategy for the chain
type SelectChain: SelectChain + 'static;
//TODO: replace these with a constructor trait. that TransactionPool implements. (#1242)
/// Extrinsic pool constructor for the full client.
fn build_full_transaction_pool(config: TransactionPoolOptions, client: Arc>)
-> Result, error::Error>;
/// Extrinsic pool constructor for the light client.
fn build_light_transaction_pool(config: TransactionPoolOptions, client: Arc>)
-> Result, error::Error>;
/// Build network protocol.
fn build_network_protocol(config: &FactoryFullConfiguration)
-> Result;
/// Build finality proof provider for serving network requests on full node.
fn build_finality_proof_provider(
client: Arc>
) -> Result