Unverified Commit f5971628 authored by Bastian Köcher's avatar Bastian Köcher Committed by GitHub
Browse files

polkadot-service: Make native runtime configurable (#3189)

* polkadot-service: Make native runtime configurable

This pull requests adds support for configuring the native runtimes used
by polkadot-service. While this whole pr doesn't change that much for
polkadot, besides not having the light-node enabled for the default
polkadot binary. However, downstream projects (parachains) will have a
much better compile time. In cumulus for example the `cargo test --all
--release` is about 4m faster to compile.

* Fixes

* Fix

* Enable rococo-native

* Fix light client

* 🤦

* Fixes
parent a4dfdf16
Pipeline #141344 passed with stages
in 37 minutes and 16 seconds
This diff is collapsed.
......@@ -12,11 +12,8 @@ edition = "2018"
readme = "README.md"
[dependencies]
cli = { package = "polkadot-cli", path = "cli" }
polkadot-cli = { path = "cli", features = [ "kusama-native", "westend-native", "rococo-native" ] }
color-eyre = "0.5.10"
thiserror = "1.0.23"
futures = "0.3.12"
service = { package = "polkadot-service", path = "node/service" }
parity-util-mem = { version = "*", default-features = false, features = ["jemalloc-global"] }
[dev-dependencies]
......@@ -43,6 +40,7 @@ members = [
"xcm/xcm-builder",
"xcm/xcm-executor",
"xcm/pallet-xcm",
"node/client",
"node/collation-generation",
"node/core/approval-voting",
"node/core/av-store",
......@@ -96,8 +94,8 @@ opt-level = 3
panic = "unwind"
[features]
runtime-benchmarks=["cli/runtime-benchmarks"]
try-runtime = ["cli/try-runtime"]
runtime-benchmarks= [ "polkadot-cli/runtime-benchmarks" ]
try-runtime = [ "polkadot-cli/try-runtime" ]
# Configuration for building a .deb package - for use with `cargo-deb`
[package.metadata.deb]
......
......@@ -54,9 +54,16 @@ browser = [
"wasm-bindgen",
"wasm-bindgen-futures",
"browser-utils",
"service",
"service/light-node",
]
runtime-benchmarks = [ "service/runtime-benchmarks" ]
trie-memory-tracker = [ "sp-trie/memory-tracker" ]
full-node = [ "service/full-node" ]
try-runtime = [ "service/try-runtime" ]
# Configure the native runtimes to use. Polkadot is always enabled by default.
#
# Validators require the native runtime currently
kusama-native = [ "service/kusama-native" ]
westend-native = [ "service/westend-native" ]
rococo-native = [ "service/rococo-native" ]
......@@ -75,23 +75,44 @@ impl SubstrateCli for Cli {
} else { id };
Ok(match id {
"kusama" => Box::new(service::chain_spec::kusama_config()?),
#[cfg(feature = "kusama-native")]
"kusama-dev" => Box::new(service::chain_spec::kusama_development_config()?),
#[cfg(feature = "kusama-native")]
"kusama-local" => Box::new(service::chain_spec::kusama_local_testnet_config()?),
#[cfg(feature = "kusama-native")]
"kusama-staging" => Box::new(service::chain_spec::kusama_staging_testnet_config()?),
#[cfg(not(feature = "kusama-native"))]
name if name.starts_with("kusama-") =>
Err(format!("`{}` only supported with `kusama-native` feature enabled.", name))?,
"polkadot" => Box::new(service::chain_spec::polkadot_config()?),
"polkadot-dev" | "dev" => Box::new(service::chain_spec::polkadot_development_config()?),
"polkadot-local" => Box::new(service::chain_spec::polkadot_local_testnet_config()?),
"polkadot-staging" => Box::new(service::chain_spec::polkadot_staging_testnet_config()?),
"rococo" => Box::new(service::chain_spec::rococo_config()?),
#[cfg(feature = "rococo-native")]
"rococo-dev" => Box::new(service::chain_spec::rococo_development_config()?),
#[cfg(feature = "rococo-native")]
"rococo-local" => Box::new(service::chain_spec::rococo_local_testnet_config()?),
#[cfg(feature = "rococo-native")]
"rococo-staging" => Box::new(service::chain_spec::rococo_staging_testnet_config()?),
name if name.starts_with("rococo-") =>
Err(format!("`{}` only supported with `rococo-native` feature enabled.", name))?,
"westend" => Box::new(service::chain_spec::westend_config()?),
#[cfg(feature = "westend-native")]
"westend-dev" => Box::new(service::chain_spec::westend_development_config()?),
#[cfg(feature = "westend-native")]
"westend-local" => Box::new(service::chain_spec::westend_local_testnet_config()?),
#[cfg(feature = "westend-native")]
"westend-staging" => Box::new(service::chain_spec::westend_staging_testnet_config()?),
#[cfg(not(feature = "westend-native"))]
name if name.starts_with("westend-") =>
Err(format!("`{}` only supported with `westend-native` feature enabled.", name))?,
"wococo" => Box::new(service::chain_spec::wococo_config()?),
#[cfg(feature = "rococo-native")]
"wococo-dev" => Box::new(service::chain_spec::wococo_development_config()?),
#[cfg(not(feature = "rococo-native"))]
name if name.starts_with("wococo-") =>
Err(format!("`{}` only supported with `rococo-native` feature enabled.", name))?,
path => {
let path = std::path::PathBuf::from(path);
......@@ -113,15 +134,25 @@ impl SubstrateCli for Cli {
}
fn native_runtime_version(spec: &Box<dyn service::ChainSpec>) -> &'static RuntimeVersion {
#[cfg(feature = "kusama-native")]
if spec.is_kusama() {
&service::kusama_runtime::VERSION
} else if spec.is_westend() {
&service::westend_runtime::VERSION
} else if spec.is_rococo() || spec.is_wococo() {
&service::rococo_runtime::VERSION
} else {
&service::polkadot_runtime::VERSION
return &service::kusama_runtime::VERSION
}
#[cfg(feature = "westend-native")]
if spec.is_westend() {
return &service::westend_runtime::VERSION
}
#[cfg(feature = "rococo-native")]
if spec.is_rococo() || spec.is_wococo() {
return &service::rococo_runtime::VERSION
}
#[cfg(not(all(feature = "rococo-native", feature = "westend-native", feature = "kusama-native")))]
let _ = spec;
&service::polkadot_runtime::VERSION
}
}
......@@ -181,8 +212,11 @@ pub fn run() -> Result<()> {
runner.run_node_until_exit(move |config| async move {
let role = config.role.clone();
let task_manager = match role {
Role::Light => service::build_light(config).map(|(task_manager, _)| task_manager),
match role {
#[cfg(feature = "browser")]
Role::Light => service::build_light(config).map(|(task_manager, _)| task_manager).map_err(Into::into),
#[cfg(not(feature = "browser"))]
Role::Light => Err(Error::Other("Light client not enabled".into())),
_ => service::build_full(
config,
service::IsCollator::No,
......@@ -190,9 +224,8 @@ pub fn run() -> Result<()> {
cli.run.no_beefy,
jaeger_agent,
None,
).map(|full| full.task_manager)
}?;
Ok::<_, Error>(task_manager)
).map(|full| full.task_manager).map_err(Into::into)
}
})
},
Some(Subcommand::BuildSpec(cmd)) => {
......@@ -304,23 +337,28 @@ pub fn run() -> Result<()> {
set_default_ss58_version(chain_spec);
ensure_dev(chain_spec).map_err(Error::Other)?;
#[cfg(feature = "kusama-native")]
if chain_spec.is_kusama() {
Ok(runner.sync_run(|config| {
return Ok(runner.sync_run(|config| {
cmd.run::<service::kusama_runtime::Block, service::KusamaExecutor>(config)
.map_err(|e| Error::SubstrateCli(e))
})?)
} else if chain_spec.is_westend() {
Ok(runner.sync_run(|config| {
}
#[cfg(feature = "westend-native")]
if chain_spec.is_westend() {
return Ok(runner.sync_run(|config| {
cmd.run::<service::westend_runtime::Block, service::WestendExecutor>(config)
.map_err(|e| Error::SubstrateCli(e))
})?)
} else {
// else we assume it is polkadot.
Ok(runner.sync_run(|config| {
cmd.run::<service::polkadot_runtime::Block, service::PolkadotExecutor>(config)
.map_err(|e| Error::SubstrateCli(e))
})?)
}
// else we assume it is polkadot.
Ok(runner.sync_run(|config| {
cmd.run::<service::polkadot_runtime::Block, service::PolkadotExecutor>(config)
.map_err(|e| Error::SubstrateCli(e))
})?)
},
Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
#[cfg(feature = "try-runtime")]
......@@ -337,29 +375,34 @@ pub fn run() -> Result<()> {
).map_err(|e| Error::SubstrateService(sc_service::Error::Prometheus(e)))?;
ensure_dev(chain_spec).map_err(Error::Other)?;
#[cfg(feature = "kusama-native")]
if chain_spec.is_kusama() {
runner.async_run(|config| {
return runner.async_run(|config| {
Ok((cmd.run::<
service::kusama_runtime::Block,
service::KusamaExecutor,
>(config).map_err(Error::SubstrateCli), task_manager))
})
} else if chain_spec.is_westend() {
runner.async_run(|config| {
}
#[cfg(feature = "westend-native")]
if chain_spec.is_westend() {
return runner.async_run(|config| {
Ok((cmd.run::<
service::westend_runtime::Block,
service::WestendExecutor,
>(config).map_err(Error::SubstrateCli), task_manager))
})
} else {
// else we assume it is polkadot.
runner.async_run(|config| {
Ok((cmd.run::<
service::polkadot_runtime::Block,
service::PolkadotExecutor,
>(config).map_err(Error::SubstrateCli), task_manager))
})
}
// else we assume it is polkadot.
runner.async_run(|config| {
Ok((cmd.run::<
service::polkadot_runtime::Block,
service::PolkadotExecutor,
>(config).map_err(Error::SubstrateCli), task_manager))
})
}
}?;
Ok(())
......
[package]
name = "polkadot-client"
version = "0.9.3"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-storage = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-offchain = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", branch = "master" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" }
beefy-primitives = { git = "https://github.com/paritytech/grandpa-bridge-gadget", branch = "master" }
# Polkadot Runtimes
polkadot-runtime = { path = "../../runtime/polkadot" }
kusama-runtime = { path = "../../runtime/kusama", optional = true }
westend-runtime = { path = "../../runtime/westend", optional = true }
rococo-runtime = { path = "../../runtime/rococo", optional = true }
polkadot-primitives = { path = "../../primitives" }
[features]
kusama = [ "kusama-runtime" ]
rococo = [ "rococo-runtime" ]
westend = [ "westend-runtime" ]
......@@ -14,7 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Polkadot Client meta trait
//! Polkadot Client
//!
//! Provides the [`AbstractClient`] trait that is a super trait that combines all the traits the client implements.
//! There is also the [`Client`] enum that combines all the different clients into one common structure.
use std::sync::Arc;
use beefy_primitives::ecdsa::AuthorityId as BeefyId;
......@@ -26,14 +29,50 @@ use sp_runtime::{
use sc_client_api::{Backend as BackendT, BlockchainEvents, KeyIterator, AuxStore, UsageProvider};
use sp_storage::{StorageData, StorageKey, ChildInfo, PrefixedStorageKey};
use polkadot_primitives::v1::{Block, ParachainHost, AccountId, Nonce, Balance, Header, BlockNumber, Hash};
use consensus_common::BlockStatus;
use sp_consensus::BlockStatus;
use sc_executor::native_executor_instance;
pub type FullBackend = sc_service::TFullBackend<Block>;
pub type FullClient<RuntimeApi, Executor> = sc_service::TFullClient<Block, RuntimeApi, Executor>;
native_executor_instance!(
pub PolkadotExecutor,
polkadot_runtime::api::dispatch,
polkadot_runtime::native_version,
frame_benchmarking::benchmarking::HostFunctions,
);
#[cfg(feature = "kusama")]
native_executor_instance!(
pub KusamaExecutor,
kusama_runtime::api::dispatch,
kusama_runtime::native_version,
frame_benchmarking::benchmarking::HostFunctions,
);
#[cfg(feature = "westend")]
native_executor_instance!(
pub WestendExecutor,
westend_runtime::api::dispatch,
westend_runtime::native_version,
frame_benchmarking::benchmarking::HostFunctions,
);
#[cfg(feature = "rococo")]
native_executor_instance!(
pub RococoExecutor,
rococo_runtime::api::dispatch,
rococo_runtime::native_version,
frame_benchmarking::benchmarking::HostFunctions,
);
/// A set of APIs that polkadot-like runtimes must implement.
pub trait RuntimeApiCollection:
sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::ApiExt<Block>
+ sp_consensus_babe::BabeApi<Block>
+ grandpa_primitives::GrandpaApi<Block>
+ sp_finality_grandpa::GrandpaApi<Block>
+ ParachainHost<Block>
+ sp_block_builder::BlockBuilder<Block>
+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
......@@ -53,7 +92,7 @@ where
Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
+ sp_api::ApiExt<Block>
+ sp_consensus_babe::BabeApi<Block>
+ grandpa_primitives::GrandpaApi<Block>
+ sp_finality_grandpa::GrandpaApi<Block>
+ ParachainHost<Block>
+ sp_block_builder::BlockBuilder<Block>
+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
......@@ -145,31 +184,47 @@ pub trait ClientHandle {
fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output;
}
macro_rules! with_client {
{
$self:ident,
$client:ident,
{
$( $code:tt )*
}
} => {
match $self {
Self::Polkadot($client) => { $( $code )* },
#[cfg(feature = "westend")]
Self::Westend($client) => { $( $code )* },
#[cfg(feature = "kusama")]
Self::Kusama($client) => { $( $code )* },
#[cfg(feature = "rococo")]
Self::Rococo($client) => { $( $code )* },
}
}
}
/// A client instance of Polkadot.
///
/// See [`ExecuteWithClient`] for more information.
#[derive(Clone)]
pub enum Client {
Polkadot(Arc<crate::FullClient<polkadot_runtime::RuntimeApi, crate::PolkadotExecutor>>),
Westend(Arc<crate::FullClient<westend_runtime::RuntimeApi, crate::WestendExecutor>>),
Kusama(Arc<crate::FullClient<kusama_runtime::RuntimeApi, crate::KusamaExecutor>>),
Rococo(Arc<crate::FullClient<rococo_runtime::RuntimeApi, crate::RococoExecutor>>),
Polkadot(Arc<FullClient<polkadot_runtime::RuntimeApi, PolkadotExecutor>>),
#[cfg(feature = "westend")]
Westend(Arc<FullClient<westend_runtime::RuntimeApi, WestendExecutor>>),
#[cfg(feature = "kusama")]
Kusama(Arc<FullClient<kusama_runtime::RuntimeApi, KusamaExecutor>>),
#[cfg(feature = "rococo")]
Rococo(Arc<FullClient<rococo_runtime::RuntimeApi, RococoExecutor>>),
}
impl ClientHandle for Client {
fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output {
match self {
Self::Polkadot(client) => {
T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone())
},
Self::Westend(client) => {
T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone())
},
Self::Kusama(client) => {
T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone())
},
Self::Rococo(client) => {
T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone())
with_client! {
self,
client,
{
T::execute_with_client::<_, _, FullBackend>(t, client.clone())
}
}
}
......@@ -177,11 +232,12 @@ impl ClientHandle for Client {
impl UsageProvider<Block> for Client {
fn usage_info(&self) -> sc_client_api::ClientInfo<Block> {
match self {
Self::Polkadot(client) => client.usage_info(),
Self::Westend(client) => client.usage_info(),
Self::Kusama(client) => client.usage_info(),
Self::Rococo(client) => client.usage_info(),
with_client! {
self,
client,
{
client.usage_info()
}
}
}
}
......@@ -191,29 +247,32 @@ impl sc_client_api::BlockBackend<Block> for Client {
&self,
id: &BlockId<Block>
) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
match self {
Self::Polkadot(client) => client.block_body(id),
Self::Westend(client) => client.block_body(id),
Self::Kusama(client) => client.block_body(id),
Self::Rococo(client) => client.block_body(id),
with_client! {
self,
client,
{
client.block_body(id)
}
}
}
fn block(&self, id: &BlockId<Block>) -> sp_blockchain::Result<Option<SignedBlock<Block>>> {
match self {
Self::Polkadot(client) => client.block(id),
Self::Westend(client) => client.block(id),
Self::Kusama(client) => client.block(id),
Self::Rococo(client) => client.block(id),
with_client! {
self,
client,
{
client.block(id)
}
}
}
fn block_status(&self, id: &BlockId<Block>) -> sp_blockchain::Result<BlockStatus> {
match self {
Self::Polkadot(client) => client.block_status(id),
Self::Westend(client) => client.block_status(id),
Self::Kusama(client) => client.block_status(id),
Self::Rococo(client) => client.block_status(id),
with_client! {
self,
client,
{
client.block_status(id)
}
}
}
......@@ -221,11 +280,12 @@ impl sc_client_api::BlockBackend<Block> for Client {
&self,
id: &BlockId<Block>
) -> sp_blockchain::Result<Option<Justifications>> {
match self {
Self::Polkadot(client) => client.justifications(id),
Self::Westend(client) => client.justifications(id),
Self::Kusama(client) => client.justifications(id),
Self::Rococo(client) => client.justifications(id),
with_client! {
self,
client,
{
client.justifications(id)
}
}
}
......@@ -233,11 +293,12 @@ impl sc_client_api::BlockBackend<Block> for Client {
&self,
number: NumberFor<Block>
) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
match self {
Self::Polkadot(client) => client.block_hash(number),
Self::Westend(client) => client.block_hash(number),
Self::Kusama(client) => client.block_hash(number),
Self::Rococo(client) => client.block_hash(number),
with_client! {
self,
client,
{
client.block_hash(number)
}
}
}
......@@ -245,11 +306,12 @@ impl sc_client_api::BlockBackend<Block> for Client {
&self,
id: &<Block as BlockT>::Hash
) -> sp_blockchain::Result<Option<Vec<u8>>> {
match self {
Self::Polkadot(client) => client.indexed_transaction(id),
Self::Westend(client) => client.indexed_transaction(id),
Self::Kusama(client) => client.indexed_transaction(id),
Self::Rococo(client) => client.indexed_transaction(id),
with_client! {
self,
client,
{
client.indexed_transaction(id)
}
}
}
......@@ -257,11 +319,12 @@ impl sc_client_api::BlockBackend<Block> for Client {
&self,
id: &BlockId<Block>
) -> sp_blockchain::Result<Option<Vec<Vec<u8>>>> {
match self {
Self::Polkadot(client) => client.block_indexed_body(id),
Self::Westend(client) => client.block_indexed_body(id),
Self::Kusama(client) => client.block_indexed_body(id),
Self::Rococo(client) => client.block_indexed_body(id),
with_client! {
self,
client,
{
client.block_indexed_body(id)
}
}
}
}
......@@ -272,11 +335,12 @@ impl sc_client_api::StorageProvider<Block, crate::FullBackend> for Client {
id: &BlockId<Block>,
key: &StorageKey,
) -> sp_blockchain::Result<Option<StorageData>> {
match self {
Self::Polkadot(client) => client.storage(id, key),
Self::Westend(client) => client.storage(id, key),
Self::Kusama(client) => client.storage(id, key),
Self::Rococo(client) => client.storage(id, key),
with_client! {
self,
client,
{
client.storage(id, key)
}
}
}
......@@ -285,11 +349,12 @@ impl sc_client_api::StorageProvider<Block, crate::FullBackend> for Client {
id: &BlockId<Block>,
key_prefix: &StorageKey,
) -> sp_blockchain::Result<Vec<StorageKey>> {
match self {
Self::Polkadot(client) => client.storage_keys(id, key_prefix),
Self::Westend(client) => client.storage_keys(id, key_prefix),
Self::Kusama(client) => client.storage_keys(id, key_prefix),
Self::Rococo(client) => client.storage_keys(id, key_prefix),
with_client! {
self,
client,
{
client.storage_keys(id, key_prefix)
}
}
}
......@@ -298,11 +363,12 @@ impl sc_client_api::StorageProvider<Block, crate::FullBackend> for Client {
id: &BlockId<Block>,
key: &StorageKey,
) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
match self {
Self::Polkadot(client) => client.storage_hash(id, key),
Self::Westend(client) => client.storage_hash(id, key),
Self::Kusama(client) => client.storage_hash(id, key),
Self::Rococo(client) => client.storage_hash(id, key),
with_client! {
self,
client,
{
client.storage_hash(id, key)
}
}
}