From 436c4a88aa908fc94e3947d0af8d6d11e73ee3ca Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 28 Jun 2024 23:37:59 +0300 Subject: [PATCH 01/10] Simplifications and fixes --- cumulus/polkadot-parachain/src/command.rs | 133 +++++++--------------- cumulus/polkadot-parachain/src/service.rs | 2 +- substrate/client/cli/src/lib.rs | 4 +- substrate/client/service/src/lib.rs | 2 +- 4 files changed, 42 insertions(+), 99 deletions(-) diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index aa75b6b6ae3f..fbba4a777e69 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -23,6 +23,7 @@ use crate::{ }, service::{new_partial, Block, Hash}, }; +#[cfg(feature = "runtime-benchmarks")] use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; @@ -34,6 +35,8 @@ use sc_cli::{ }; use sc_service::config::{BasePath, PrometheusConfig}; use sp_runtime::traits::AccountIdConversion; +#[cfg(feature = "runtime-benchmarks")] +use sp_runtime::traits::HashingFor; use std::{net::SocketAddr, path::PathBuf}; /// The choice of consensus for the parachain omni-node. @@ -110,6 +113,7 @@ fn runtime(id: &str) -> Runtime { } else if id.starts_with("asset-hub-kusama") | id.starts_with("statemine") | id.starts_with("asset-hub-rococo") | + id.starts_with("rockmine") | id.starts_with("asset-hub-westend") | id.starts_with("westmint") { @@ -584,25 +588,15 @@ pub fn run() -> Result<()> { // Switch on the concrete benchmark sub-command- match cmd { - BenchmarkCmd::Pallet(cmd) => - if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run_with_spec::, ReclaimHostFunctions>(Some(config.chain_spec))) - } else { - Err("Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - .into()) - }, + #[cfg(feature = "runtime-benchmarks")] + BenchmarkCmd::Pallet(cmd) => runner.sync_run(|config| { + cmd.run_with_spec::, ReclaimHostFunctions>(Some( + config.chain_spec, + )) + }), BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { construct_partials!(config, |partials| cmd.run(partials.client)) }), - #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => - return Err(sc_cli::Error::Input( - "Compile with --features=runtime-benchmarks \ - to enable storage benchmarks." - .into(), - ) - .into()), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { construct_partials!(config, |partials| { @@ -617,7 +611,10 @@ pub fn run() -> Result<()> { // NOTE: this allows the Client to leniently implement // new benchmark commands without requiring a companion MR. #[allow(unreachable_patterns)] - _ => Err("Benchmarking sub-command unsupported".into()), + _ => Err("Benchmarking sub-command unsupported or compilation feature missing. \ + Make sure to compile with --features=runtime-benchmarks \ + to enable all supported benchmarks." + .into()), } }, Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?), @@ -645,25 +642,33 @@ pub fn run() -> Result<()> { if old_path.exists() && new_path.exists() { return Err(format!( - "Found legacy {} path {} and new asset-hub path {}. Delete one path such that only one exists.", - old_name, old_path.display(), new_path.display() - ).into()) + "Found legacy {} path {} and new Asset Hub path {}. \ + Delete one path such that only one exists.", + old_name, + old_path.display(), + new_path.display() + ) + .into()) } if old_path.exists() { std::fs::rename(old_path.clone(), new_path.clone())?; info!( - "Statemint renamed to Asset Hub. The filepath with associated data on disk has been renamed from {} to {}.", - old_path.display(), new_path.display() + "{} was renamed to Asset Hub. The filepath with associated data on disk \ + has been renamed from {} to {}.", + old_name, + old_path.display(), + new_path.display() ); } } - let hwbench = (!cli.no_hardware_benchmarks).then_some( - config.database.path().map(|database_path| { + let hwbench = (!cli.no_hardware_benchmarks) + .then_some(config.database.path().map(|database_path| { let _ = std::fs::create_dir_all(database_path); sc_sysinfo::gather_hwbench(Some(database_path)) - })).flatten(); + })) + .flatten(); let para_id = chain_spec::Extensions::try_get(&*config.chain_spec) .map(|e| e.para_id) @@ -672,7 +677,9 @@ pub fn run() -> Result<()> { let id = ParaId::from(para_id); let parachain_account = - AccountIdConversion::::into_account_truncating(&id); + AccountIdConversion::::into_account_truncating( + &id, + ); let tokio_handle = config.tokio_handle.clone(); let polkadot_config = @@ -734,7 +741,10 @@ async fn start_node>( .map(|r| r.0) .map_err(Into::into), - Runtime::Collectives => crate::service::start_generic_aura_lookahead_node::( + Runtime::BridgeHub(_) | + Runtime::Collectives | + Runtime::Coretime(_) | + Runtime::People(_) => crate::service::start_generic_aura_lookahead_node::( config, polkadot_config, collator_options, @@ -767,52 +777,6 @@ async fn start_node>( .map(|r| r.0) .map_err(Into::into), - Runtime::BridgeHub(bridge_hub_runtime_type) => match bridge_hub_runtime_type { - chain_spec::bridge_hubs::BridgeHubRuntimeType::Polkadot | - chain_spec::bridge_hubs::BridgeHubRuntimeType::PolkadotLocal | - chain_spec::bridge_hubs::BridgeHubRuntimeType::Kusama | - chain_spec::bridge_hubs::BridgeHubRuntimeType::KusamaLocal | - chain_spec::bridge_hubs::BridgeHubRuntimeType::Westend | - chain_spec::bridge_hubs::BridgeHubRuntimeType::WestendLocal | - chain_spec::bridge_hubs::BridgeHubRuntimeType::WestendDevelopment | - chain_spec::bridge_hubs::BridgeHubRuntimeType::Rococo | - chain_spec::bridge_hubs::BridgeHubRuntimeType::RococoLocal | - chain_spec::bridge_hubs::BridgeHubRuntimeType::RococoDevelopment => - crate::service::start_generic_aura_lookahead_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map(|r| r.0), - } - .map_err(Into::into), - - Runtime::Coretime(coretime_runtime_type) => match coretime_runtime_type { - chain_spec::coretime::CoretimeRuntimeType::Kusama | - chain_spec::coretime::CoretimeRuntimeType::KusamaLocal | - chain_spec::coretime::CoretimeRuntimeType::Polkadot | - chain_spec::coretime::CoretimeRuntimeType::PolkadotLocal | - chain_spec::coretime::CoretimeRuntimeType::Rococo | - chain_spec::coretime::CoretimeRuntimeType::RococoLocal | - chain_spec::coretime::CoretimeRuntimeType::RococoDevelopment | - chain_spec::coretime::CoretimeRuntimeType::Westend | - chain_spec::coretime::CoretimeRuntimeType::WestendLocal | - chain_spec::coretime::CoretimeRuntimeType::WestendDevelopment => - crate::service::start_generic_aura_lookahead_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map(|r| r.0), - } - .map_err(Into::into), - Runtime::Penpal(_) => crate::service::start_rococo_parachain_node::( config, polkadot_config, @@ -835,28 +799,6 @@ async fn start_node>( .map(|r| r.0) .map_err(Into::into), - Runtime::People(people_runtime_type) => match people_runtime_type { - chain_spec::people::PeopleRuntimeType::Kusama | - chain_spec::people::PeopleRuntimeType::KusamaLocal | - chain_spec::people::PeopleRuntimeType::Polkadot | - chain_spec::people::PeopleRuntimeType::PolkadotLocal | - chain_spec::people::PeopleRuntimeType::Rococo | - chain_spec::people::PeopleRuntimeType::RococoLocal | - chain_spec::people::PeopleRuntimeType::RococoDevelopment | - chain_spec::people::PeopleRuntimeType::Westend | - chain_spec::people::PeopleRuntimeType::WestendLocal | - chain_spec::people::PeopleRuntimeType::WestendDevelopment => - crate::service::start_generic_aura_lookahead_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map(|r| r.0), - } - .map_err(Into::into), Runtime::Omni(consensus) => match consensus { // rococo actually uses aura import and consensus, unlike most system chains that use // relay to aura. @@ -870,6 +812,7 @@ async fn start_node>( .await .map(|r| r.0) .map_err(Into::into), + Consensus::Relay => crate::service::start_shell_node::( config, polkadot_config, diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index a22ae77a7759..c0aa96b3cde8 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -567,7 +567,7 @@ where }); let relay_chain_verifier = - Box::new(RelayChainVerifier::new(client.clone(), |_, _| async { Ok(()) })) as Box<_>; + Box::new(RelayChainVerifier::new(client.clone(), |_, _| async { Ok(()) })); let verifier = Verifier { client, diff --git a/substrate/client/cli/src/lib.rs b/substrate/client/cli/src/lib.rs index 104e8ec8b798..363d79cf2430 100644 --- a/substrate/client/cli/src/lib.rs +++ b/substrate/client/cli/src/lib.rs @@ -58,11 +58,11 @@ pub trait SubstrateCli: Sized { /// Implementation version. /// - /// By default this will look like this: + /// By default, it will look like this: /// /// `2.0.0-b950f731c` /// - /// Where the hash is the short commit hash of the commit of in the Git repository. + /// Where the hash is the short hash of the commit in the Git repository. fn impl_version() -> String; /// Executable file name. diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs index a51bb4012d5d..63be296d1b21 100644 --- a/substrate/client/service/src/lib.rs +++ b/substrate/client/service/src/lib.rs @@ -137,7 +137,7 @@ pub struct PartialComponents, /// The chain task manager. pub task_manager: TaskManager, - /// A keystore container instance.. + /// A keystore container instance. pub keystore_container: KeystoreContainer, /// A chain selection algorithm instance. pub select_chain: SelectChain, From 283d474d497170aa5ea44f1fad30f506a88c2ecd Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Sun, 30 Jun 2024 11:00:11 +0300 Subject: [PATCH 02/10] Simplify start_node_impl() return type --- cumulus/polkadot-parachain/src/command.rs | 9 --------- cumulus/polkadot-parachain/src/service.rs | 16 ++++++++-------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index fbba4a777e69..d7c4a14c1de0 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -729,7 +729,6 @@ async fn start_node>( Network, >(config, polkadot_config, collator_options, id, hwbench) .await - .map(|r| r.0) .map_err(Into::into), Runtime::AssetHub => crate::service::start_asset_hub_lookahead_node::< @@ -738,7 +737,6 @@ async fn start_node>( Network, >(config, polkadot_config, collator_options, id, hwbench) .await - .map(|r| r.0) .map_err(Into::into), Runtime::BridgeHub(_) | @@ -752,7 +750,6 @@ async fn start_node>( hwbench, ) .await - .map(|r| r.0) .map_err(Into::into), Runtime::Seedling | Runtime::Shell => crate::service::start_shell_node::( @@ -763,7 +760,6 @@ async fn start_node>( hwbench, ) .await - .map(|r| r.0) .map_err(Into::into), Runtime::ContractsRococo => crate::service::start_contracts_rococo_node::( @@ -774,7 +770,6 @@ async fn start_node>( hwbench, ) .await - .map(|r| r.0) .map_err(Into::into), Runtime::Penpal(_) => crate::service::start_rococo_parachain_node::( @@ -785,7 +780,6 @@ async fn start_node>( hwbench, ) .await - .map(|r| r.0) .map_err(Into::into), Runtime::Glutton => crate::service::start_basic_lookahead_node::( @@ -796,7 +790,6 @@ async fn start_node>( hwbench, ) .await - .map(|r| r.0) .map_err(Into::into), Runtime::Omni(consensus) => match consensus { @@ -810,7 +803,6 @@ async fn start_node>( hwbench, ) .await - .map(|r| r.0) .map_err(Into::into), Consensus::Relay => crate::service::start_shell_node::( @@ -821,7 +813,6 @@ async fn start_node>( hwbench, ) .await - .map(|r| r.0) .map_err(Into::into), }, } diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index c0aa96b3cde8..d5cdadcf6ed7 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -194,7 +194,7 @@ async fn start_node_impl( build_import_queue: BIQ, start_consensus: SC, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> +) -> sc_service::error::Result where RuntimeApi: ConstructNodeRuntimeApi>, RB: Fn( @@ -366,7 +366,7 @@ where start_network.start_network(); - Ok((task_manager, client)) + Ok(task_manager) } /// Build the import queue for Aura-based runtimes. @@ -414,7 +414,7 @@ pub async fn start_rococo_parachain_node>( collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> { +) -> sc_service::error::Result { start_node_impl::( parachain_config, polkadot_config, @@ -483,7 +483,7 @@ pub async fn start_shell_node>( collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> { +) -> sc_service::error::Result { start_node_impl::( parachain_config, polkadot_config, @@ -591,7 +591,7 @@ pub async fn start_generic_aura_lookahead_node> collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> { +) -> sc_service::error::Result { start_node_impl::( parachain_config, polkadot_config, @@ -618,7 +618,7 @@ pub async fn start_asset_hub_lookahead_node( collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> +) -> sc_service::error::Result where RuntimeApi: ConstructNodeRuntimeApi>, RuntimeApi::RuntimeApi: AuraRuntimeApi @@ -888,7 +888,7 @@ pub async fn start_basic_lookahead_node>( collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> { +) -> sc_service::error::Result { start_node_impl::( parachain_config, polkadot_config, @@ -910,7 +910,7 @@ pub async fn start_contracts_rococo_node>( collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc>)> { +) -> sc_service::error::Result { start_node_impl::( parachain_config, polkadot_config, From 270060b80e7df7710842308c9c83d8be982080a3 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Sun, 30 Jun 2024 01:05:31 +0300 Subject: [PATCH 03/10] Deduplicate create_runner() logic --- polkadot/cli/src/command.rs | 2 +- substrate/client/cli/src/lib.rs | 21 ++++++++------------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/polkadot/cli/src/command.rs b/polkadot/cli/src/command.rs index b89054b4dc32..62d99122c301 100644 --- a/polkadot/cli/src/command.rs +++ b/polkadot/cli/src/command.rs @@ -192,7 +192,7 @@ where F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), { let runner = cli - .create_runner_with_logger_hook::(&cli.run.base, logger_hook) + .create_runner_with_logger_hook::<_, _, F>(&cli.run.base, logger_hook) .map_err(Error::from)?; let chain_spec = &runner.config().chain_spec; diff --git a/substrate/client/cli/src/lib.rs b/substrate/client/cli/src/lib.rs index 363d79cf2430..1bb9fec0e276 100644 --- a/substrate/client/cli/src/lib.rs +++ b/substrate/client/cli/src/lib.rs @@ -199,17 +199,8 @@ pub trait SubstrateCli: Sized { fn create_runner, DVC: DefaultConfigurationValues>( &self, command: &T, - ) -> error::Result> { - let tokio_runtime = build_runtime()?; - - // `capture` needs to be called in a tokio context. - // Also capture them as early as possible. - let signals = tokio_runtime.block_on(async { Signals::capture() })?; - - let config = command.create_configuration(self, tokio_runtime.handle().clone())?; - - command.init(&Self::support_url(), &Self::impl_version(), |_, _| {}, &config)?; - Runner::new(config, tokio_runtime, signals) + ) -> Result> { + self.create_runner_with_logger_hook(command, |_, _| {}) } /// Create a runner for the command provided in argument. The `logger_hook` can be used to setup @@ -231,11 +222,15 @@ pub trait SubstrateCli: Sized { /// } /// } /// ``` - fn create_runner_with_logger_hook( + fn create_runner_with_logger_hook< + T: CliConfiguration, + DVC: DefaultConfigurationValues, + F, + >( &self, command: &T, logger_hook: F, - ) -> error::Result> + ) -> Result> where F: FnOnce(&mut LoggerBuilder, &Configuration), { From 0121d3ceeaf5f2f3959de1a50a379b6b4ad12049 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 26 Jun 2024 17:31:46 +0300 Subject: [PATCH 04/10] Deduplicate construct_partials!() and construct_async_run!() --- Cargo.lock | 2 + cumulus/polkadot-parachain/Cargo.toml | 3 + cumulus/polkadot-parachain/src/command.rs | 233 ++++++------------ .../polkadot-parachain/src/common/command.rs | 136 ++++++++++ cumulus/polkadot-parachain/src/common/mod.rs | 1 + 5 files changed, 215 insertions(+), 160 deletions(-) create mode 100644 cumulus/polkadot-parachain/src/common/command.rs diff --git a/Cargo.lock b/Cargo.lock index 91d604d6fa3c..bb0174630812 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13952,9 +13952,11 @@ dependencies = [ "polkadot-service", "rococo-parachain-runtime", "sc-basic-authorship", + "sc-block-builder", "sc-chain-spec", "sc-cli", "sc-client-api", + "sc-client-db", "sc-consensus", "sc-executor", "sc-network", diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index ae5abdcfab6a..63e1dfd6950f 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -56,11 +56,13 @@ sp-io = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } sp-session = { workspace = true, default-features = true } frame-try-runtime = { optional = true, workspace = true, default-features = true } +sc-block-builder = { workspace = true, default-features = true } sc-consensus = { workspace = true, default-features = true } sp-tracing = { workspace = true, default-features = true } frame-support = { workspace = true, default-features = true } sc-cli = { workspace = true, default-features = true } sc-client-api = { workspace = true, default-features = true } +sc-client-db = { workspace = true, default-features = true } sc-executor = { workspace = true, default-features = true } sc-service = { workspace = true, default-features = true } sc-telemetry = { workspace = true, default-features = true } @@ -147,6 +149,7 @@ runtime-benchmarks = [ "polkadot-primitives/runtime-benchmarks", "polkadot-service/runtime-benchmarks", "rococo-parachain-runtime/runtime-benchmarks", + "sc-client-db/runtime-benchmarks", "sc-service/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index d7c4a14c1de0..a06f12550090 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -18,6 +18,7 @@ use crate::{ chain_spec, chain_spec::GenericChainSpec, cli::{Cli, RelayChainCli, Subcommand}, + common::command::CmdRunner, fake_runtime_api::{ asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, aura::RuntimeApi, }, @@ -382,146 +383,47 @@ impl SubstrateCli for RelayChainCli { } } -/// Creates partial components for the runtimes that are supported by the benchmarks. -macro_rules! construct_partials { - ($config:expr, |$partials:ident| $code:expr) => { - match $config.chain_spec.runtime()? { - Runtime::AssetHubPolkadot => { - let $partials = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, - )?; - $code - }, - Runtime::AssetHub | - Runtime::BridgeHub(_) | - Runtime::Collectives | - Runtime::Coretime(_) | - Runtime::People(_) => { - let $partials = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AuraId>, - )?; - $code - }, - Runtime::Glutton | Runtime::Shell | Runtime::Seedling => { - let $partials = new_partial::( - &$config, - crate::service::build_shell_import_queue, - )?; - $code - }, - Runtime::ContractsRococo | Runtime::Penpal(_) => { - let $partials = new_partial::( - &$config, - crate::service::build_aura_import_queue, - )?; - $code - }, - Runtime::Omni(consensus) => match consensus { - Consensus::Aura => { - let $partials = new_partial::( - &$config, - crate::service::build_aura_import_queue, - )?; - $code - }, - Consensus::Relay => { - let $partials = new_partial::( - &$config, - crate::service::build_shell_import_queue, - )?; - $code - }, - }, - } - }; -} - -macro_rules! construct_async_run { - (|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{ - let runner = $cli.create_runner($cmd)?; - match runner.config().chain_spec.runtime()? { - Runtime::AssetHubPolkadot => { - runner.async_run(|$config| { - let $components = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Runtime::AssetHub | - Runtime::BridgeHub(_) | - Runtime::Collectives | - Runtime::Coretime(_) | - Runtime::People(_) => { - runner.async_run(|$config| { - let $components = new_partial::( - &$config, - crate::service::build_relay_to_aura_import_queue::<_, AuraId>, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Runtime::Shell | - Runtime::Seedling | - Runtime::Glutton => { - runner.async_run(|$config| { - let $components = new_partial::( - &$config, - crate::service::build_shell_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - } - Runtime::ContractsRococo | Runtime::Penpal(_) => { - runner.async_run(|$config| { - let $components = new_partial::< - RuntimeApi, - _, - >( - &$config, - crate::service::build_aura_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Runtime::Omni(consensus) => match consensus { - Consensus::Aura => { - runner.async_run(|$config| { - let $components = new_partial::< - RuntimeApi, - _, - >( - &$config, - crate::service::build_aura_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - Consensus::Relay - => { - runner.async_run(|$config| { - let $components = new_partial::< - RuntimeApi, - _, - >( - &$config, - crate::service::build_shell_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }, - } - } - }} +fn new_partial_from_config( + config: &sc_service::Configuration, +) -> std::result::Result>, sc_cli::Error> { + Ok(match config.chain_spec.runtime()? { + Runtime::AssetHubPolkadot => Box::new( + new_partial::( + config, + crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, + ) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::AssetHub | + Runtime::BridgeHub(_) | + Runtime::Collectives | + Runtime::Coretime(_) | + Runtime::People(_) => Box::new( + new_partial::( + config, + crate::service::build_relay_to_aura_import_queue::<_, AuraId>, + ) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::Glutton | Runtime::Shell | Runtime::Seedling => Box::new( + new_partial::(config, crate::service::build_shell_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::ContractsRococo | Runtime::Penpal(_) => Box::new( + new_partial::(config, crate::service::build_aura_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + Runtime::Omni(consensus) => match consensus { + Consensus::Aura => Box::new( + new_partial::(config, crate::service::build_aura_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + Consensus::Relay => Box::new( + new_partial::(config, crate::service::build_shell_import_queue) + .map_err(sc_cli::Error::Service)?, + ), + }, + }) } /// Parse command line arguments into service configuration. @@ -534,28 +436,40 @@ pub fn run() -> Result<()> { runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) }, Some(Subcommand::CheckBlock(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.import_queue)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_check_block_cmd(cmd)) }) }, Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, config.database)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_export_blocks_cmd(cmd, config)) }) }, Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, config.chain_spec)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_export_state_cmd(cmd, config)) }) }, Some(Subcommand::ImportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.import_queue)) + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_import_blocks_cmd(cmd)) + }) + }, + Some(Subcommand::Revert(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let partials = new_partial_from_config(&config)?; + Ok(partials.prepare_revert_cmd(cmd)) }) }, - Some(Subcommand::Revert(cmd)) => construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.backend, None)) - }), Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; let polkadot_cli = RelayChainCli::new(runner.config(), cli.relay_chain_args.iter()); @@ -573,8 +487,10 @@ pub fn run() -> Result<()> { }, Some(Subcommand::ExportGenesisHead(cmd)) => { let runner = cli.create_runner(cmd)?; - runner - .sync_run(|config| construct_partials!(config, |partials| cmd.run(partials.client))) + runner.sync_run(|config| { + let partials = new_partial_from_config(&config)?; + partials.run_export_genesis_head_cmd(cmd) + }) }, Some(Subcommand::ExportGenesisWasm(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -595,16 +511,13 @@ pub fn run() -> Result<()> { )) }), BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { - construct_partials!(config, |partials| cmd.run(partials.client)) + let partials = new_partial_from_config(&config)?; + partials.run_benchmark_block_cmd(cmd) }), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { - construct_partials!(config, |partials| { - let db = partials.backend.expose_db(); - let storage = partials.backend.expose_storage(); - - cmd.run(config, partials.client.clone(), db, storage) - }) + let partials = new_partial_from_config(&config)?; + partials.run_benchmark_storage_cmd(cmd, config) }), BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), diff --git a/cumulus/polkadot-parachain/src/common/command.rs b/cumulus/polkadot-parachain/src/common/command.rs new file mode 100644 index 000000000000..57587fd8697f --- /dev/null +++ b/cumulus/polkadot-parachain/src/common/command.rs @@ -0,0 +1,136 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . + +//! Helper trait used to dynamically run parachain node commands. + +use cumulus_client_cli::ExportGenesisHeadCommand; +use cumulus_primitives_core::BlockT; +use frame_benchmarking_cli::BlockCmd; +#[cfg(any(feature = "runtime-benchmarks"))] +use frame_benchmarking_cli::StorageCmd; +use sc_block_builder::BlockBuilderApi; +use sc_cli::{CheckBlockCmd, ExportBlocksCmd, ExportStateCmd, ImportBlocksCmd, RevertCmd}; +use sc_client_api::{BlockBackend, StorageProvider, UsageProvider}; +use sc_client_db::{Backend, DbHash}; +use sc_service::{Configuration, PartialComponents, TaskManager}; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_runtime::{traits::Header as HeaderT, OpaqueExtrinsic}; +use std::{fmt::Debug, future::Future, pin::Pin, str::FromStr}; + +type SyncCmdResult = sc_cli::Result<()>; +type AsyncCmdResult<'a> = (Pin + 'a>>, TaskManager); + +pub trait CmdRunner { + fn prepare_check_block_cmd(self: Box, cmd: &CheckBlockCmd) -> AsyncCmdResult<'_>; + + fn prepare_export_blocks_cmd( + self: Box, + cmd: &ExportBlocksCmd, + config: Configuration, + ) -> AsyncCmdResult<'_>; + + fn prepare_export_state_cmd( + self: Box, + cmd: &ExportStateCmd, + config: Configuration, + ) -> AsyncCmdResult<'_>; + + fn prepare_import_blocks_cmd(self: Box, cmd: &ImportBlocksCmd) -> AsyncCmdResult<'_>; + + fn prepare_revert_cmd(self: Box, cmd: &RevertCmd) -> AsyncCmdResult<'_>; + + fn run_export_genesis_head_cmd( + self: Box, + cmd: &ExportGenesisHeadCommand, + ) -> SyncCmdResult; + + fn run_benchmark_block_cmd(self: Box, cmd: &BlockCmd) -> SyncCmdResult; + + #[cfg(any(feature = "runtime-benchmarks"))] + fn run_benchmark_storage_cmd( + self: Box, + cmd: &StorageCmd, + config: Configuration, + ) -> SyncCmdResult; +} + +impl CmdRunner + for PartialComponents, SelectChain, ImportQueue, TransactionPool, Other> +where + Self: Send, + Block: BlockT + for<'de> serde::Deserialize<'de>, + <::Number as FromStr>::Err: Debug, + Client: HeaderBackend + + BlockBackend + + ProvideRuntimeApi + + StorageProvider> + + UsageProvider + + 'static, + Client::Api: BlockBuilderApi, + ImportQueue: sc_service::ImportQueue + 'static, +{ + fn prepare_check_block_cmd(self: Box, cmd: &CheckBlockCmd) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, self.import_queue)), self.task_manager) + } + + fn prepare_export_blocks_cmd( + self: Box, + cmd: &ExportBlocksCmd, + config: Configuration, + ) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, config.database)), self.task_manager) + } + + fn prepare_export_state_cmd( + self: Box, + cmd: &ExportStateCmd, + config: Configuration, + ) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, config.chain_spec)), self.task_manager) + } + + fn prepare_import_blocks_cmd(self: Box, cmd: &ImportBlocksCmd) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, self.import_queue)), self.task_manager) + } + + fn prepare_revert_cmd(self: Box, cmd: &RevertCmd) -> AsyncCmdResult<'_> { + (Box::pin(cmd.run(self.client, self.backend, None)), self.task_manager) + } + + fn run_export_genesis_head_cmd( + self: Box, + cmd: &ExportGenesisHeadCommand, + ) -> SyncCmdResult { + cmd.run(self.client) + } + + fn run_benchmark_block_cmd(self: Box, cmd: &BlockCmd) -> SyncCmdResult { + cmd.run(self.client) + } + + #[cfg(any(feature = "runtime-benchmarks"))] + fn run_benchmark_storage_cmd( + self: Box, + cmd: &StorageCmd, + config: Configuration, + ) -> SyncCmdResult { + let db = self.backend.expose_db(); + let storage = self.backend.expose_storage(); + + cmd.run(config, self.client, db, storage) + } +} diff --git a/cumulus/polkadot-parachain/src/common/mod.rs b/cumulus/polkadot-parachain/src/common/mod.rs index 5adbb4137cd3..860980ae9be8 100644 --- a/cumulus/polkadot-parachain/src/common/mod.rs +++ b/cumulus/polkadot-parachain/src/common/mod.rs @@ -19,6 +19,7 @@ #![warn(missing_docs)] pub mod aura; +pub mod command; use cumulus_primitives_core::CollectCollationInfo; use sp_api::{ApiExt, CallApiAt, ConstructRuntimeApi, Metadata}; From 40c39675eff2b0af80bb4b1cbc302a362850d88d Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 1 Jul 2024 21:46:31 +0300 Subject: [PATCH 05/10] Implement a more structured way to define a node spec - use traits instead of bounds for `rpc_ext_builder()`, `build_import_queue()`, `start_consensus()` - add a `NodeSpec` trait for defining the specifications of a node - deduplicate the code related to building a node's components / starting a node --- Cargo.lock | 2 - cumulus/polkadot-parachain/Cargo.toml | 3 - cumulus/polkadot-parachain/src/command.rs | 190 +- .../polkadot-parachain/src/common/command.rs | 136 -- cumulus/polkadot-parachain/src/common/mod.rs | 1 - cumulus/polkadot-parachain/src/rpc.rs | 9 + cumulus/polkadot-parachain/src/service.rs | 1624 +++++++++-------- 7 files changed, 953 insertions(+), 1012 deletions(-) delete mode 100644 cumulus/polkadot-parachain/src/common/command.rs diff --git a/Cargo.lock b/Cargo.lock index bb0174630812..91d604d6fa3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13952,11 +13952,9 @@ dependencies = [ "polkadot-service", "rococo-parachain-runtime", "sc-basic-authorship", - "sc-block-builder", "sc-chain-spec", "sc-cli", "sc-client-api", - "sc-client-db", "sc-consensus", "sc-executor", "sc-network", diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 63e1dfd6950f..ae5abdcfab6a 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -56,13 +56,11 @@ sp-io = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } sp-session = { workspace = true, default-features = true } frame-try-runtime = { optional = true, workspace = true, default-features = true } -sc-block-builder = { workspace = true, default-features = true } sc-consensus = { workspace = true, default-features = true } sp-tracing = { workspace = true, default-features = true } frame-support = { workspace = true, default-features = true } sc-cli = { workspace = true, default-features = true } sc-client-api = { workspace = true, default-features = true } -sc-client-db = { workspace = true, default-features = true } sc-executor = { workspace = true, default-features = true } sc-service = { workspace = true, default-features = true } sc-telemetry = { workspace = true, default-features = true } @@ -149,7 +147,6 @@ runtime-benchmarks = [ "polkadot-primitives/runtime-benchmarks", "polkadot-service/runtime-benchmarks", "rococo-parachain-runtime/runtime-benchmarks", - "sc-client-db/runtime-benchmarks", "sc-service/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index a06f12550090..2a5b691af2e9 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -18,11 +18,13 @@ use crate::{ chain_spec, chain_spec::GenericChainSpec, cli::{Cli, RelayChainCli, Subcommand}, - common::command::CmdRunner, fake_runtime_api::{ asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, aura::RuntimeApi, }, - service::{new_partial, Block, Hash}, + service::{ + AssetHubLookaheadNode, BasicLookaheadNode, Block, ContractsRococoNode, DynNodeSpec, + GenericAuraLookaheadNode, Hash, RococoParachainNode, ShellNode, + }, }; #[cfg(feature = "runtime-benchmarks")] use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; @@ -383,49 +385,37 @@ impl SubstrateCli for RelayChainCli { } } -fn new_partial_from_config( +fn new_node_spec_with_network>( config: &sc_service::Configuration, -) -> std::result::Result>, sc_cli::Error> { +) -> std::result::Result>, sc_cli::Error> { Ok(match config.chain_spec.runtime()? { - Runtime::AssetHubPolkadot => Box::new( - new_partial::( - config, - crate::service::build_relay_to_aura_import_queue::<_, AssetHubPolkadotAuraId>, - ) - .map_err(sc_cli::Error::Service)?, - ), - Runtime::AssetHub | + Runtime::AssetHubPolkadot => Box::new(AssetHubLookaheadNode::< + AssetHubPolkadotRuntimeApi, + AssetHubPolkadotAuraId, + >(Default::default())), + Runtime::AssetHub => + Box::new(AssetHubLookaheadNode::(Default::default())), Runtime::BridgeHub(_) | Runtime::Collectives | Runtime::Coretime(_) | - Runtime::People(_) => Box::new( - new_partial::( - config, - crate::service::build_relay_to_aura_import_queue::<_, AuraId>, - ) - .map_err(sc_cli::Error::Service)?, - ), - Runtime::Glutton | Runtime::Shell | Runtime::Seedling => Box::new( - new_partial::(config, crate::service::build_shell_import_queue) - .map_err(sc_cli::Error::Service)?, - ), - Runtime::ContractsRococo | Runtime::Penpal(_) => Box::new( - new_partial::(config, crate::service::build_aura_import_queue) - .map_err(sc_cli::Error::Service)?, - ), + Runtime::People(_) => Box::new(GenericAuraLookaheadNode), + Runtime::Shell | Runtime::Seedling => Box::new(ShellNode), + Runtime::ContractsRococo => Box::new(ContractsRococoNode), + Runtime::Penpal(_) => Box::new(RococoParachainNode), + Runtime::Glutton => Box::new(BasicLookaheadNode), Runtime::Omni(consensus) => match consensus { - Consensus::Aura => Box::new( - new_partial::(config, crate::service::build_aura_import_queue) - .map_err(sc_cli::Error::Service)?, - ), - Consensus::Relay => Box::new( - new_partial::(config, crate::service::build_shell_import_queue) - .map_err(sc_cli::Error::Service)?, - ), + Consensus::Aura => Box::new(RococoParachainNode), + Consensus::Relay => Box::new(ShellNode), }, }) } +fn new_node_spec( + config: &sc_service::Configuration, +) -> std::result::Result>, sc_cli::Error> { + new_node_spec_with_network(config) +} + /// Parse command line arguments into service configuration. pub fn run() -> Result<()> { let cli = Cli::from_args(); @@ -438,36 +428,36 @@ pub fn run() -> Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let partials = new_partial_from_config(&config)?; - Ok(partials.prepare_check_block_cmd(cmd)) + let node = new_node_spec(&config)?; + node.prepare_check_block_cmd(config, cmd) }) }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let partials = new_partial_from_config(&config)?; - Ok(partials.prepare_export_blocks_cmd(cmd, config)) + let node = new_node_spec(&config)?; + node.prepare_export_blocks_cmd(config, cmd) }) }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let partials = new_partial_from_config(&config)?; - Ok(partials.prepare_export_state_cmd(cmd, config)) + let node = new_node_spec(&config)?; + node.prepare_export_state_cmd(config, cmd) }) }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let partials = new_partial_from_config(&config)?; - Ok(partials.prepare_import_blocks_cmd(cmd)) + let node = new_node_spec(&config)?; + node.prepare_import_blocks_cmd(config, cmd) }) }, Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let partials = new_partial_from_config(&config)?; - Ok(partials.prepare_revert_cmd(cmd)) + let node = new_node_spec(&config)?; + node.prepare_revert_cmd(config, cmd) }) }, Some(Subcommand::PurgeChain(cmd)) => { @@ -488,8 +478,8 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisHead(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { - let partials = new_partial_from_config(&config)?; - partials.run_export_genesis_head_cmd(cmd) + let node = new_node_spec(&config)?; + node.run_export_genesis_head_cmd(config, cmd) }) }, Some(Subcommand::ExportGenesisWasm(cmd)) => { @@ -511,13 +501,13 @@ pub fn run() -> Result<()> { )) }), BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { - let partials = new_partial_from_config(&config)?; - partials.run_benchmark_block_cmd(cmd) + let node = new_node_spec(&config)?; + node.run_benchmark_block_cmd(config, cmd) }), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { - let partials = new_partial_from_config(&config)?; - partials.run_benchmark_storage_cmd(cmd, config) + let node = new_node_spec(&config)?; + node.run_benchmark_storage_cmd(config, cmd) }), BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), @@ -628,6 +618,7 @@ pub fn run() -> Result<()> { } } +#[sc_tracing::logging::prefix_logs_with("Parachain")] async fn start_node>( config: sc_service::Configuration, polkadot_config: sc_service::Configuration, @@ -635,100 +626,11 @@ async fn start_node>( id: ParaId, hwbench: Option, ) -> Result { - match config.chain_spec.runtime()? { - Runtime::AssetHubPolkadot => crate::service::start_asset_hub_lookahead_node::< - AssetHubPolkadotRuntimeApi, - AssetHubPolkadotAuraId, - Network, - >(config, polkadot_config, collator_options, id, hwbench) - .await - .map_err(Into::into), - - Runtime::AssetHub => crate::service::start_asset_hub_lookahead_node::< - RuntimeApi, - AuraId, - Network, - >(config, polkadot_config, collator_options, id, hwbench) - .await - .map_err(Into::into), - - Runtime::BridgeHub(_) | - Runtime::Collectives | - Runtime::Coretime(_) | - Runtime::People(_) => crate::service::start_generic_aura_lookahead_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map_err(Into::into), - - Runtime::Seedling | Runtime::Shell => crate::service::start_shell_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map_err(Into::into), - - Runtime::ContractsRococo => crate::service::start_contracts_rococo_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map_err(Into::into), - - Runtime::Penpal(_) => crate::service::start_rococo_parachain_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map_err(Into::into), - - Runtime::Glutton => crate::service::start_basic_lookahead_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) + let node_spec = new_node_spec_with_network::(&config)?; + node_spec + .start_node(config, polkadot_config, collator_options, id, hwbench) .await - .map_err(Into::into), - - Runtime::Omni(consensus) => match consensus { - // rococo actually uses aura import and consensus, unlike most system chains that use - // relay to aura. - Consensus::Aura => crate::service::start_rococo_parachain_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map_err(Into::into), - - Consensus::Relay => crate::service::start_shell_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map_err(Into::into), - }, - } + .map_err(Into::into) } impl DefaultConfigurationValues for RelayChainCli { diff --git a/cumulus/polkadot-parachain/src/common/command.rs b/cumulus/polkadot-parachain/src/common/command.rs deleted file mode 100644 index 57587fd8697f..000000000000 --- a/cumulus/polkadot-parachain/src/common/command.rs +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Cumulus. - -// Cumulus 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. - -// Cumulus 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 Cumulus. If not, see . - -//! Helper trait used to dynamically run parachain node commands. - -use cumulus_client_cli::ExportGenesisHeadCommand; -use cumulus_primitives_core::BlockT; -use frame_benchmarking_cli::BlockCmd; -#[cfg(any(feature = "runtime-benchmarks"))] -use frame_benchmarking_cli::StorageCmd; -use sc_block_builder::BlockBuilderApi; -use sc_cli::{CheckBlockCmd, ExportBlocksCmd, ExportStateCmd, ImportBlocksCmd, RevertCmd}; -use sc_client_api::{BlockBackend, StorageProvider, UsageProvider}; -use sc_client_db::{Backend, DbHash}; -use sc_service::{Configuration, PartialComponents, TaskManager}; -use sp_api::ProvideRuntimeApi; -use sp_blockchain::HeaderBackend; -use sp_runtime::{traits::Header as HeaderT, OpaqueExtrinsic}; -use std::{fmt::Debug, future::Future, pin::Pin, str::FromStr}; - -type SyncCmdResult = sc_cli::Result<()>; -type AsyncCmdResult<'a> = (Pin + 'a>>, TaskManager); - -pub trait CmdRunner { - fn prepare_check_block_cmd(self: Box, cmd: &CheckBlockCmd) -> AsyncCmdResult<'_>; - - fn prepare_export_blocks_cmd( - self: Box, - cmd: &ExportBlocksCmd, - config: Configuration, - ) -> AsyncCmdResult<'_>; - - fn prepare_export_state_cmd( - self: Box, - cmd: &ExportStateCmd, - config: Configuration, - ) -> AsyncCmdResult<'_>; - - fn prepare_import_blocks_cmd(self: Box, cmd: &ImportBlocksCmd) -> AsyncCmdResult<'_>; - - fn prepare_revert_cmd(self: Box, cmd: &RevertCmd) -> AsyncCmdResult<'_>; - - fn run_export_genesis_head_cmd( - self: Box, - cmd: &ExportGenesisHeadCommand, - ) -> SyncCmdResult; - - fn run_benchmark_block_cmd(self: Box, cmd: &BlockCmd) -> SyncCmdResult; - - #[cfg(any(feature = "runtime-benchmarks"))] - fn run_benchmark_storage_cmd( - self: Box, - cmd: &StorageCmd, - config: Configuration, - ) -> SyncCmdResult; -} - -impl CmdRunner - for PartialComponents, SelectChain, ImportQueue, TransactionPool, Other> -where - Self: Send, - Block: BlockT + for<'de> serde::Deserialize<'de>, - <::Number as FromStr>::Err: Debug, - Client: HeaderBackend - + BlockBackend - + ProvideRuntimeApi - + StorageProvider> - + UsageProvider - + 'static, - Client::Api: BlockBuilderApi, - ImportQueue: sc_service::ImportQueue + 'static, -{ - fn prepare_check_block_cmd(self: Box, cmd: &CheckBlockCmd) -> AsyncCmdResult<'_> { - (Box::pin(cmd.run(self.client, self.import_queue)), self.task_manager) - } - - fn prepare_export_blocks_cmd( - self: Box, - cmd: &ExportBlocksCmd, - config: Configuration, - ) -> AsyncCmdResult<'_> { - (Box::pin(cmd.run(self.client, config.database)), self.task_manager) - } - - fn prepare_export_state_cmd( - self: Box, - cmd: &ExportStateCmd, - config: Configuration, - ) -> AsyncCmdResult<'_> { - (Box::pin(cmd.run(self.client, config.chain_spec)), self.task_manager) - } - - fn prepare_import_blocks_cmd(self: Box, cmd: &ImportBlocksCmd) -> AsyncCmdResult<'_> { - (Box::pin(cmd.run(self.client, self.import_queue)), self.task_manager) - } - - fn prepare_revert_cmd(self: Box, cmd: &RevertCmd) -> AsyncCmdResult<'_> { - (Box::pin(cmd.run(self.client, self.backend, None)), self.task_manager) - } - - fn run_export_genesis_head_cmd( - self: Box, - cmd: &ExportGenesisHeadCommand, - ) -> SyncCmdResult { - cmd.run(self.client) - } - - fn run_benchmark_block_cmd(self: Box, cmd: &BlockCmd) -> SyncCmdResult { - cmd.run(self.client) - } - - #[cfg(any(feature = "runtime-benchmarks"))] - fn run_benchmark_storage_cmd( - self: Box, - cmd: &StorageCmd, - config: Configuration, - ) -> SyncCmdResult { - let db = self.backend.expose_db(); - let storage = self.backend.expose_storage(); - - cmd.run(config, self.client, db, storage) - } -} diff --git a/cumulus/polkadot-parachain/src/common/mod.rs b/cumulus/polkadot-parachain/src/common/mod.rs index 860980ae9be8..5adbb4137cd3 100644 --- a/cumulus/polkadot-parachain/src/common/mod.rs +++ b/cumulus/polkadot-parachain/src/common/mod.rs @@ -19,7 +19,6 @@ #![warn(missing_docs)] pub mod aura; -pub mod command; use cumulus_primitives_core::CollectCollationInfo; use sp_api::{ApiExt, CallApiAt, ConstructRuntimeApi, Metadata}; diff --git a/cumulus/polkadot-parachain/src/rpc.rs b/cumulus/polkadot-parachain/src/rpc.rs index 7437bb1f4b93..a42498e7ffe8 100644 --- a/cumulus/polkadot-parachain/src/rpc.rs +++ b/cumulus/polkadot-parachain/src/rpc.rs @@ -31,6 +31,15 @@ use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; /// A type representing all RPC extensions. pub type RpcExtension = jsonrpsee::RpcModule<()>; +pub trait BuildRpcExtensions { + fn build_rpc_extensions( + deny_unsafe: DenyUnsafe, + client: Arc, + backend: Arc, + pool: Arc, + ) -> sc_service::error::Result>; +} + /// Full client dependencies pub struct FullDeps { /// The client instance to use. diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index d5cdadcf6ed7..c1d0b859df6d 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -15,11 +15,12 @@ // along with Cumulus. If not, see . use codec::Decode; -use cumulus_client_cli::CollatorOptions; +use cumulus_client_cli::{CollatorOptions, ExportGenesisHeadCommand}; use cumulus_client_collator::service::CollatorService; use cumulus_client_consensus_aura::collators::lookahead::{self as aura, Params as AuraParams}; use cumulus_client_consensus_common::ParachainBlockImport as TParachainBlockImport; use cumulus_client_consensus_proposer::Proposer; +use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier; #[allow(deprecated)] use cumulus_client_service::old_consensus; use cumulus_client_service::{ @@ -39,23 +40,30 @@ use crate::{ }, fake_runtime_api::aura::RuntimeApi as FakeRuntimeApi, rpc, + rpc::BuildRpcExtensions, }; pub use parachains_common::{AccountId, AuraId, Balance, Block, Hash, Nonce}; -use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier; +use frame_benchmarking_cli::BlockCmd; +#[cfg(any(feature = "runtime-benchmarks"))] +use frame_benchmarking_cli::StorageCmd; use futures::prelude::*; +use polkadot_primitives::CollatorPair; use prometheus_endpoint::Registry; +use sc_cli::{CheckBlockCmd, ExportBlocksCmd, ExportStateCmd, ImportBlocksCmd, RevertCmd}; use sc_client_api::Backend as ClientApiBackend; use sc_consensus::{ import_queue::{BasicQueue, Verifier as VerifierT}, - BlockImportParams, ImportQueue, + BlockImportParams, DefaultImportQueue, ImportQueue, }; use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; use sc_network::{config::FullNetworkConfiguration, service::traits::NetworkBackend, NetworkBlock}; use sc_network_sync::SyncingService; -use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; +use sc_service::{Configuration, Error, PartialComponents, TFullBackend, TFullClient, TaskManager}; +use sc_sysinfo::HwBench; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; -use sp_api::{ConstructRuntimeApi, ProvideRuntimeApi}; +use sc_transaction_pool::FullPool; +use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_core::traits::SpawnEssentialNamed; use sp_keystore::KeystorePtr; @@ -63,9 +71,7 @@ use sp_runtime::{ app_crypto::AppCrypto, traits::{Block as BlockT, Header as HeaderT}, }; -use std::{marker::PhantomData, sync::Arc, time::Duration}; - -use polkadot_primitives::CollatorPair; +use std::{marker::PhantomData, pin::Pin, sync::Arc, time::Duration}; #[cfg(not(feature = "runtime-benchmarks"))] type HostFunctions = cumulus_client_service::ParachainHostFunctions; @@ -76,7 +82,7 @@ type HostFunctions = ( frame_benchmarking::benchmarking::HostFunctions, ); -type ParachainClient = TFullClient>; +pub type ParachainClient = TFullClient>; type ParachainBackend = TFullBackend; @@ -93,409 +99,434 @@ pub type Service = PartialComponents< (ParachainBlockImport, Option, Option), >; -/// Starts a `ServiceBuilder` for a full service. -/// -/// Use this macro if you don't actually need the full service, but just the builder in order to -/// be able to perform chain operations. -pub fn new_partial( - config: &Configuration, - build_import_queue: BIQ, -) -> Result, sc_service::Error> -where - RuntimeApi: ConstructNodeRuntimeApi>, - BIQ: FnOnce( - Arc>, - ParachainBlockImport, - &Configuration, - Option, - &TaskManager, - ) -> Result, sc_service::Error>, -{ - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let heap_pages = config - .default_heap_pages - .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); - - let executor = sc_executor::WasmExecutor::::builder() - .with_execution_method(config.wasm_method) - .with_max_runtime_instances(config.max_runtime_instances) - .with_runtime_cache_size(config.runtime_cache_size) - .with_onchain_heap_alloc_strategy(heap_pages) - .with_offchain_heap_alloc_strategy(heap_pages) - .build(); - - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts_record_import::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - true, - )?; - let client = Arc::new(client); - - let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); - - let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", None, worker.run()); - telemetry - }); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - - let block_import = ParachainBlockImport::new(client.clone(), backend.clone()); - - let import_queue = build_import_queue( - client.clone(), - block_import.clone(), - config, - telemetry.as_ref().map(|telemetry| telemetry.handle()), - &task_manager, - )?; - - Ok(PartialComponents { - backend, - client, - import_queue, - keystore_container, - task_manager, - transaction_pool, - select_chain: (), - other: (block_import, telemetry, telemetry_worker_handle), - }) +pub trait BuildImportQueue { + fn build_import_queue( + client: Arc>, + block_import: ParachainBlockImport, + config: &Configuration, + telemetry_handle: Option, + task_manager: &TaskManager, + ) -> sc_service::error::Result>; } -/// Start a node with the given parachain `Configuration` and relay chain `Configuration`. -/// -/// This is the actual implementation that is abstract over the executor and the runtime api. -#[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_node_impl( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - sybil_resistance_level: CollatorSybilResistance, - para_id: ParaId, - rpc_ext_builder: RB, - build_import_queue: BIQ, - start_consensus: SC, - hwbench: Option, -) -> sc_service::error::Result +pub trait StartConsensus where RuntimeApi: ConstructNodeRuntimeApi>, - RB: Fn( - DenyUnsafe, - Arc>, - Arc, - Arc>>, - ) -> Result, sc_service::Error> - + 'static, - BIQ: FnOnce( - Arc>, - ParachainBlockImport, - &Configuration, - Option, - &TaskManager, - ) -> Result, sc_service::Error>, - SC: FnOnce( - Arc>, - ParachainBlockImport, - Option<&Registry>, - Option, - &TaskManager, - Arc, - Arc>>, - Arc>, - KeystorePtr, - Duration, - ParaId, - CollatorPair, - OverseerHandle, - Arc>) + Send + Sync>, - Arc, - ) -> Result<(), sc_service::Error>, - Net: NetworkBackend, { - let parachain_config = prepare_node_config(parachain_config); - - let params = new_partial::(¶chain_config, build_import_queue)?; - let (block_import, mut telemetry, telemetry_worker_handle) = params.other; - - let client = params.client.clone(); - let backend = params.backend.clone(); - - let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = build_relay_chain_interface( - polkadot_config, - ¶chain_config, - telemetry_worker_handle, - &mut task_manager, - collator_options.clone(), - hwbench.clone(), - ) - .await - .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; - - let validator = parachain_config.role.is_authority(); - let prometheus_registry = parachain_config.prometheus_registry().cloned(); - let transaction_pool = params.transaction_pool.clone(); - let import_queue_service = params.import_queue.service(); - let net_config = FullNetworkConfiguration::<_, _, Net>::new(¶chain_config.network); - - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = - build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - para_id, - spawn_handle: task_manager.spawn_handle(), - relay_chain_interface: relay_chain_interface.clone(), - import_queue: params.import_queue, - sybil_resistance_level, - }) - .await?; - - let rpc_builder = { - let client = client.clone(); - let transaction_pool = transaction_pool.clone(); - let backend_for_rpc = backend.clone(); - - Box::new(move |deny_unsafe, _| { - rpc_ext_builder( - deny_unsafe, - client.clone(), - backend_for_rpc.clone(), - transaction_pool.clone(), - ) - }) - }; - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - rpc_builder, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - config: parachain_config, - keystore: params.keystore_container.keystore(), - backend: backend.clone(), - network: network.clone(), - sync_service: sync_service.clone(), - system_rpc_tx, - tx_handler_controller, - telemetry: telemetry.as_mut(), - })?; - - if let Some(hwbench) = hwbench { - sc_sysinfo::print_hwbench(&hwbench); - if validator { - warn_if_slow_hardware(&hwbench); - } + fn start_consensus( + client: Arc>, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, + relay_chain_interface: Arc, + transaction_pool: Arc>>, + sync_oracle: Arc>, + keystore: KeystorePtr, + relay_chain_slot_duration: Duration, + para_id: ParaId, + collator_key: CollatorPair, + overseer_handle: OverseerHandle, + announce_block: Arc>) + Send + Sync>, + backend: Arc, + ) -> Result<(), sc_service::Error>; +} - if let Some(ref mut telemetry) = telemetry { - let telemetry_handle = telemetry.handle(); - task_manager.spawn_handle().spawn( - "telemetry_hwbench", - None, - sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench), - ); - } - } +pub trait NodeSpec { + type RuntimeApi: ConstructNodeRuntimeApi>; + + type BuildImportQueue: BuildImportQueue + 'static; + + type BuildRpcExtensions: BuildRpcExtensions< + ParachainClient, + ParachainBackend, + sc_transaction_pool::FullPool>, + > + 'static; + + type StartConsensus: StartConsensus + 'static; + + const SYBIL_RESISTANCE: CollatorSybilResistance; + + /// Starts a `ServiceBuilder` for a full service. + /// + /// Use this macro if you don't actually need the full service, but just the builder in order to + /// be able to perform chain operations. + fn new_partial(config: &Configuration) -> sc_service::error::Result> { + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + + let heap_pages = config.default_heap_pages.map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| { + HeapAllocStrategy::Static { extra_pages: h as _ } + }); + + let executor = sc_executor::WasmExecutor::::builder() + .with_execution_method(config.wasm_method) + .with_max_runtime_instances(config.max_runtime_instances) + .with_runtime_cache_size(config.runtime_cache_size) + .with_onchain_heap_alloc_strategy(heap_pages) + .with_offchain_heap_alloc_strategy(heap_pages) + .build(); + + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts_record_import::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + true, + )?; + let client = Arc::new(client); + + let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); + + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", None, worker.run()); + telemetry + }); + + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.role.is_authority().into(), + config.prometheus_registry(), + task_manager.spawn_essential_handle(), + client.clone(), + ); - let announce_block = { - let sync_service = sync_service.clone(); - Arc::new(move |hash, data| sync_service.announce_block(hash, data)) - }; - - let relay_chain_slot_duration = Duration::from_secs(6); - - let overseer_handle = relay_chain_interface - .overseer_handle() - .map_err(|e| sc_service::Error::Application(Box::new(e)))?; - - start_relay_chain_tasks(StartRelayChainTasksParams { - client: client.clone(), - announce_block: announce_block.clone(), - para_id, - relay_chain_interface: relay_chain_interface.clone(), - task_manager: &mut task_manager, - da_recovery_profile: if validator { - DARecoveryProfile::Collator - } else { - DARecoveryProfile::FullNode - }, - import_queue: import_queue_service, - relay_chain_slot_duration, - recovery_handle: Box::new(overseer_handle.clone()), - sync_service: sync_service.clone(), - })?; - - if validator { - start_consensus( + let block_import = ParachainBlockImport::new(client.clone(), backend.clone()); + + let import_queue = Self::BuildImportQueue::build_import_queue( client.clone(), - block_import, - prometheus_registry.as_ref(), - telemetry.as_ref().map(|t| t.handle()), + block_import.clone(), + config, + telemetry.as_ref().map(|telemetry| telemetry.handle()), &task_manager, - relay_chain_interface.clone(), - transaction_pool, - sync_service.clone(), - params.keystore_container.keystore(), - relay_chain_slot_duration, - para_id, - collator_key.expect("Command line arguments do not allow this. qed"), - overseer_handle, - announce_block, - backend.clone(), )?; + + Ok(PartialComponents { + backend, + client, + import_queue, + keystore_container, + task_manager, + transaction_pool, + select_chain: (), + other: (block_import, telemetry, telemetry_worker_handle), + }) } - start_network.start_network(); + /// Start a node with the given parachain spec. + /// + /// This is the actual implementation that is abstract over the executor and the runtime api. + fn start_node( + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, + ) -> Pin>>> + where + Net: NetworkBackend, + { + Box::pin(async move { + let parachain_config = prepare_node_config(parachain_config); + + let params = Self::new_partial(¶chain_config)?; + let (block_import, mut telemetry, telemetry_worker_handle) = params.other; + + let client = params.client.clone(); + let backend = params.backend.clone(); + + let mut task_manager = params.task_manager; + let (relay_chain_interface, collator_key) = build_relay_chain_interface( + polkadot_config, + ¶chain_config, + telemetry_worker_handle, + &mut task_manager, + collator_options.clone(), + hwbench.clone(), + ) + .await + .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; + + let validator = parachain_config.role.is_authority(); + let prometheus_registry = parachain_config.prometheus_registry().cloned(); + let transaction_pool = params.transaction_pool.clone(); + let import_queue_service = params.import_queue.service(); + let net_config = FullNetworkConfiguration::<_, _, Net>::new(¶chain_config.network); + + let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = + build_network(BuildNetworkParams { + parachain_config: ¶chain_config, + net_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + para_id, + spawn_handle: task_manager.spawn_handle(), + relay_chain_interface: relay_chain_interface.clone(), + import_queue: params.import_queue, + sybil_resistance_level: Self::SYBIL_RESISTANCE, + }) + .await?; + + let rpc_builder = { + let client = client.clone(); + let transaction_pool = transaction_pool.clone(); + let backend_for_rpc = backend.clone(); + + Box::new(move |deny_unsafe, _| { + Self::BuildRpcExtensions::build_rpc_extensions( + deny_unsafe, + client.clone(), + backend_for_rpc.clone(), + transaction_pool.clone(), + ) + }) + }; + + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + rpc_builder, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + task_manager: &mut task_manager, + config: parachain_config, + keystore: params.keystore_container.keystore(), + backend: backend.clone(), + network: network.clone(), + sync_service: sync_service.clone(), + system_rpc_tx, + tx_handler_controller, + telemetry: telemetry.as_mut(), + })?; + + if let Some(hwbench) = hwbench { + sc_sysinfo::print_hwbench(&hwbench); + if validator { + warn_if_slow_hardware(&hwbench); + } + + if let Some(ref mut telemetry) = telemetry { + let telemetry_handle = telemetry.handle(); + task_manager.spawn_handle().spawn( + "telemetry_hwbench", + None, + sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench), + ); + } + } + + let announce_block = { + let sync_service = sync_service.clone(); + Arc::new(move |hash, data| sync_service.announce_block(hash, data)) + }; + + let relay_chain_slot_duration = Duration::from_secs(6); + + let overseer_handle = relay_chain_interface + .overseer_handle() + .map_err(|e| sc_service::Error::Application(Box::new(e)))?; + + start_relay_chain_tasks(StartRelayChainTasksParams { + client: client.clone(), + announce_block: announce_block.clone(), + para_id, + relay_chain_interface: relay_chain_interface.clone(), + task_manager: &mut task_manager, + da_recovery_profile: if validator { + DARecoveryProfile::Collator + } else { + DARecoveryProfile::FullNode + }, + import_queue: import_queue_service, + relay_chain_slot_duration, + recovery_handle: Box::new(overseer_handle.clone()), + sync_service: sync_service.clone(), + })?; + + if validator { + Self::StartConsensus::start_consensus( + client.clone(), + block_import, + prometheus_registry.as_ref(), + telemetry.as_ref().map(|t| t.handle()), + &task_manager, + relay_chain_interface.clone(), + transaction_pool, + sync_service.clone(), + params.keystore_container.keystore(), + relay_chain_slot_duration, + para_id, + collator_key.expect("Command line arguments do not allow this. qed"), + overseer_handle, + announce_block, + backend.clone(), + )?; + } - Ok(task_manager) + start_network.start_network(); + + Ok(task_manager) + }) + } } /// Build the import queue for Aura-based runtimes. -pub fn build_aura_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - - cumulus_client_consensus_aura::import_queue::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - >(cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, - }) - .map_err(Into::into) +pub struct BuildAuraImportQueue(PhantomData); + +impl BuildImportQueue for BuildAuraImportQueue { + fn build_import_queue( + client: Arc>, + block_import: ParachainBlockImport, + config: &Configuration, + telemetry_handle: Option, + task_manager: &TaskManager, + ) -> sc_service::error::Result> { + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + + cumulus_client_consensus_aura::import_queue::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + >(cumulus_client_consensus_aura::ImportQueueParams { + block_import, + client, + create_inherent_data_providers: move |_, _| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + registry: config.prometheus_registry(), + spawner: &task_manager.spawn_essential_handle(), + telemetry: telemetry_handle, + }) + .map_err(Into::into) + } } -/// Start a rococo parachain node. -pub async fn start_rococo_parachain_node>( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - build_parachain_rpc_extensions::, - build_aura_import_queue, - start_lookahead_aura_consensus, - hwbench, - ) - .await +pub struct RococoParachainNode; + +impl NodeSpec for RococoParachainNode { + type RuntimeApi = FakeRuntimeApi; + type BuildImportQueue = BuildAuraImportQueue; + type BuildRpcExtensions = BuildParachainRpcExtensions; + type StartConsensus = StartLookaheadAuraConsensus; + + const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } /// Build the import queue for the shell runtime. -pub fn build_shell_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - _: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> { - cumulus_client_consensus_relay_chain::import_queue( - client, - block_import, - |_, _| async { Ok(()) }, - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - ) - .map_err(Into::into) +pub struct BuildShellImportQueue(PhantomData); + +impl BuildImportQueue for BuildShellImportQueue { + fn build_import_queue( + client: Arc>, + block_import: ParachainBlockImport, + config: &Configuration, + _telemetry_handle: Option, + task_manager: &TaskManager, + ) -> sc_service::error::Result> { + cumulus_client_consensus_relay_chain::import_queue( + client, + block_import, + |_, _| async { Ok(()) }, + &task_manager.spawn_essential_handle(), + config.prometheus_registry(), + ) + .map_err(Into::into) + } } -fn build_parachain_rpc_extensions( - deny_unsafe: sc_rpc::DenyUnsafe, - client: Arc>, - backend: Arc, - pool: Arc>>, -) -> Result, sc_service::Error> +pub struct BuildParachainRpcExtensions(PhantomData); + +impl + BuildRpcExtensions< + ParachainClient, + ParachainBackend, + sc_transaction_pool::FullPool>, + > for BuildParachainRpcExtensions where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_block_builder::BlockBuilder - + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + RuntimeApi: ConstructNodeRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + substrate_frame_rpc_system::AccountNonceApi, { - let deps = rpc::FullDeps { client, pool, deny_unsafe }; + fn build_rpc_extensions( + deny_unsafe: DenyUnsafe, + client: Arc>, + backend: Arc, + pool: Arc>>, + ) -> sc_service::error::Result> { + let deps = rpc::FullDeps { client, pool, deny_unsafe }; + + rpc::create_full(deps, backend).map_err(Into::into) + } +} + +pub struct BuildContractsRpcExtensions; - rpc::create_full(deps, backend).map_err(Into::into) +impl + BuildRpcExtensions< + ParachainClient, + ParachainBackend, + sc_transaction_pool::FullPool>, + > for BuildContractsRpcExtensions +{ + fn build_rpc_extensions( + deny_unsafe: DenyUnsafe, + client: Arc>, + _backend: Arc, + pool: Arc>>, + ) -> sc_service::error::Result> { + let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; + + crate::rpc::create_contracts_rococo(deps).map_err(Into::into) + } } -fn build_contracts_rpc_extensions( - deny_unsafe: sc_rpc::DenyUnsafe, - client: Arc>, - _backend: Arc, - pool: Arc>>, -) -> Result, sc_service::Error> { - let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; +pub struct BuildEmptyRpcExtensions(PhantomData); - crate::rpc::create_contracts_rococo(deps).map_err(Into::into) +impl + BuildRpcExtensions< + ParachainClient, + ParachainBackend, + sc_transaction_pool::FullPool>, + > for BuildEmptyRpcExtensions +where + RuntimeApi: ConstructNodeRuntimeApi> + Send + Sync + 'static, +{ + fn build_rpc_extensions( + _deny_unsafe: DenyUnsafe, + _client: Arc>, + _backend: Arc, + _pool: Arc>>, + ) -> sc_service::error::Result> { + Ok(RpcModule::new(())) + } } -/// Start a polkadot-shell parachain node. -pub async fn start_shell_node>( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Unresistant, // free-for-all consensus - para_id, - |_, _, _, _| Ok(RpcModule::new(())), - build_shell_import_queue, - start_relay_chain_consensus, - hwbench, - ) - .await +pub struct ShellNode; + +impl NodeSpec for ShellNode { + type RuntimeApi = FakeRuntimeApi; + type BuildImportQueue = BuildShellImportQueue; + type BuildRpcExtensions = BuildEmptyRpcExtensions; + type StartConsensus = StartRelayChainConsensus; + + const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Unresistant; } struct Verifier { @@ -526,403 +557,379 @@ where /// Build the import queue for parachain runtimes that started with relay chain consensus and /// switched to aura. -pub fn build_relay_to_aura_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry_handle: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> +pub struct BuildRelayToAuraImportQueue(PhantomData<(RuntimeApi, AuraId)>); + +impl BuildImportQueue + for BuildRelayToAuraImportQueue where RuntimeApi: ConstructNodeRuntimeApi>, RuntimeApi::RuntimeApi: AuraRuntimeApi, AuraId: AuraIdT + Sync, { - let verifier_client = client.clone(); - - let aura_verifier = cumulus_client_consensus_aura::build_verifier::< - ::Pair, - _, - _, - _, - >(cumulus_client_consensus_aura::BuildVerifierParams { - client: verifier_client.clone(), - create_inherent_data_providers: move |parent_hash, _| { - let cidp_client = verifier_client.clone(); - async move { - let slot_duration = - cumulus_client_consensus_aura::slot_duration_at(&*cidp_client, parent_hash)?; - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - } - }, - telemetry: telemetry_handle, - }); + fn build_import_queue( + client: Arc>, + block_import: ParachainBlockImport, + config: &Configuration, + telemetry_handle: Option, + task_manager: &TaskManager, + ) -> sc_service::error::Result> { + let verifier_client = client.clone(); + + let aura_verifier = + cumulus_client_consensus_aura::build_verifier::<::Pair, _, _, _>( + cumulus_client_consensus_aura::BuildVerifierParams { + client: verifier_client.clone(), + create_inherent_data_providers: move |parent_hash, _| { + let cidp_client = verifier_client.clone(); + async move { + let slot_duration = cumulus_client_consensus_aura::slot_duration_at( + &*cidp_client, + parent_hash, + )?; + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + } + }, + telemetry: telemetry_handle, + }, + ); - let relay_chain_verifier = - Box::new(RelayChainVerifier::new(client.clone(), |_, _| async { Ok(()) })); + let relay_chain_verifier = + Box::new(RelayChainVerifier::new(client.clone(), |_, _| async { Ok(()) })); - let verifier = Verifier { - client, - relay_chain_verifier, - aura_verifier: Box::new(aura_verifier), - _phantom: PhantomData, - }; + let verifier = Verifier { + client, + relay_chain_verifier, + aura_verifier: Box::new(aura_verifier), + _phantom: PhantomData, + }; - let registry = config.prometheus_registry(); - let spawner = task_manager.spawn_essential_handle(); + let registry = config.prometheus_registry(); + let spawner = task_manager.spawn_essential_handle(); - Ok(BasicQueue::new(verifier, Box::new(block_import), None, &spawner, registry)) + Ok(BasicQueue::new(verifier, Box::new(block_import), None, &spawner, registry)) + } } /// Uses the lookahead collator to support async backing. /// /// Start an aura powered parachain node. Some system chains use this. -pub async fn start_generic_aura_lookahead_node>( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - build_parachain_rpc_extensions::, - build_relay_to_aura_import_queue::<_, AuraId>, - start_lookahead_aura_consensus, - hwbench, - ) - .await +pub struct GenericAuraLookaheadNode; + +impl NodeSpec for GenericAuraLookaheadNode { + type RuntimeApi = FakeRuntimeApi; + type BuildImportQueue = BuildRelayToAuraImportQueue; + type BuildRpcExtensions = BuildParachainRpcExtensions; + type StartConsensus = StartLookaheadAuraConsensus; + const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } -/// Start a shell node which should later transition into an Aura powered parachain node. Asset Hub -/// uses this because at genesis, Asset Hub was on the `shell` runtime which didn't have Aura and -/// needs to sync and upgrade before it can run `AuraApi` functions. -/// -/// Uses the lookahead collator to support async backing. -#[sc_tracing::logging::prefix_logs_with("Parachain")] -pub async fn start_asset_hub_lookahead_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result +pub struct AssetHubLookaheadNode(pub PhantomData<(RuntimeApi, AuraId)>); + +impl NodeSpec for AssetHubLookaheadNode where RuntimeApi: ConstructNodeRuntimeApi>, RuntimeApi::RuntimeApi: AuraRuntimeApi + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + substrate_frame_rpc_system::AccountNonceApi, AuraId: AuraIdT + Sync, - Net: NetworkBackend, { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - build_parachain_rpc_extensions::, - build_relay_to_aura_import_queue::<_, AuraId>, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - sync_oracle, - keystore, - relay_chain_slot_duration, - para_id, - collator_key, - overseer_handle, - announce_block, - backend| { - let relay_chain_interface2 = relay_chain_interface.clone(); - - let collator_service = CollatorService::new( - client.clone(), - Arc::new(task_manager.spawn_handle()), - announce_block, - client.clone(), - ); - - let spawner = task_manager.spawn_handle(); - - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - spawner, - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - - let collation_future = Box::pin(async move { - // Start collating with the `shell` runtime while waiting for an upgrade to an Aura - // compatible runtime. - let mut request_stream = cumulus_client_collator::relay_chain_driven::init( - collator_key.clone(), - para_id, - overseer_handle.clone(), - ) - .await; - while let Some(request) = request_stream.next().await { - let pvd = request.persisted_validation_data().clone(); - let last_head_hash = - match ::Header::decode(&mut &pvd.parent_head.0[..]) { - Ok(header) => header.hash(), - Err(e) => { - log::error!("Could not decode the head data: {e}"); - request.complete(None); - continue - }, - }; - - // Check if we have upgraded to an Aura compatible runtime and transition if - // necessary. - if client.runtime_api().has_aura_api(last_head_hash) { - // Respond to this request before transitioning to Aura. - request.complete(None); - break - } - } - - // Move to Aura consensus. - let proposer = Proposer::new(proposer_factory); - - let params = AuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client.clone(), - para_backend: backend, - relay_client: relay_chain_interface2, - code_hash_provider: move |block_hash| { - client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) - }, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - relay_chain_slot_duration, - proposer, - collator_service, - authoring_duration: Duration::from_millis(1500), - reinitialize: true, /* we need to always re-initialize for asset-hub moving - * to aura */ - }; - - aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params) - .await - }); - - let spawner = task_manager.spawn_essential_handle(); - spawner.spawn_essential("cumulus-asset-hub-collator", None, collation_future); - - Ok(()) - }, - hwbench, - ) - .await + type RuntimeApi = RuntimeApi; + type BuildImportQueue = BuildRelayToAuraImportQueue; + type BuildRpcExtensions = BuildParachainRpcExtensions; + type StartConsensus = StartRelayToAuraConsensus; + const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } /// Start relay-chain consensus that is free for all. Everyone can submit a block, the relay-chain /// decides what is backed and included. -fn start_relay_chain_consensus( - client: Arc>, - block_import: ParachainBlockImport, - prometheus_registry: Option<&Registry>, - telemetry: Option, - task_manager: &TaskManager, - relay_chain_interface: Arc, - transaction_pool: Arc>>, - _sync_oracle: Arc>, - _keystore: KeystorePtr, - _relay_chain_slot_duration: Duration, - para_id: ParaId, - collator_key: CollatorPair, - overseer_handle: OverseerHandle, - announce_block: Arc>) + Send + Sync>, - _backend: Arc, -) -> Result<(), sc_service::Error> { - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry, - telemetry, - ); - - let free_for_all = cumulus_client_consensus_relay_chain::build_relay_chain_consensus( - cumulus_client_consensus_relay_chain::BuildRelayChainConsensusParams { - para_id, - proposer_factory, - block_import, - relay_chain_interface: relay_chain_interface.clone(), - create_inherent_data_providers: move |_, (relay_parent, validation_data)| { - let relay_chain_interface = relay_chain_interface.clone(); - async move { - let parachain_inherent = +pub struct StartRelayChainConsensus; + +impl StartConsensus for StartRelayChainConsensus { + fn start_consensus( + client: Arc>, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, + relay_chain_interface: Arc, + transaction_pool: Arc>>, + _sync_oracle: Arc>, + _keystore: KeystorePtr, + _relay_chain_slot_duration: Duration, + para_id: ParaId, + collator_key: CollatorPair, + overseer_handle: OverseerHandle, + announce_block: Arc>) + Send + Sync>, + _backend: Arc, + ) -> Result<(), Error> { + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry, + telemetry, + ); + + let free_for_all = cumulus_client_consensus_relay_chain::build_relay_chain_consensus( + cumulus_client_consensus_relay_chain::BuildRelayChainConsensusParams { + para_id, + proposer_factory, + block_import, + relay_chain_interface: relay_chain_interface.clone(), + create_inherent_data_providers: move |_, (relay_parent, validation_data)| { + let relay_chain_interface = relay_chain_interface.clone(); + async move { + let parachain_inherent = cumulus_client_parachain_inherent::ParachainInherentDataProvider::create_at( relay_parent, &relay_chain_interface, &validation_data, para_id, ).await; - let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from( - "Failed to create parachain inherent", - ) - })?; - Ok(parachain_inherent) - } + let parachain_inherent = parachain_inherent.ok_or_else(|| { + Box::::from( + "Failed to create parachain inherent", + ) + })?; + Ok(parachain_inherent) + } + }, }, - }, - ); - - let spawner = task_manager.spawn_handle(); - - // Required for free-for-all consensus - #[allow(deprecated)] - old_consensus::start_collator_sync(old_consensus::StartCollatorParams { - para_id, - block_status: client.clone(), - announce_block, - overseer_handle, - spawner, - key: collator_key, - parachain_consensus: free_for_all, - runtime_api: client.clone(), - }); - - Ok(()) + ); + + let spawner = task_manager.spawn_handle(); + + // Required for free-for-all consensus + #[allow(deprecated)] + old_consensus::start_collator_sync(old_consensus::StartCollatorParams { + para_id, + block_status: client.clone(), + announce_block, + overseer_handle, + spawner, + key: collator_key, + parachain_consensus: free_for_all, + runtime_api: client.clone(), + }); + + Ok(()) + } } /// Start consensus using the lookahead aura collator. -fn start_lookahead_aura_consensus( - client: Arc>, - block_import: ParachainBlockImport, - prometheus_registry: Option<&Registry>, - telemetry: Option, - task_manager: &TaskManager, - relay_chain_interface: Arc, - transaction_pool: Arc>>, - sync_oracle: Arc>, - keystore: KeystorePtr, - relay_chain_slot_duration: Duration, - para_id: ParaId, - collator_key: CollatorPair, - overseer_handle: OverseerHandle, - announce_block: Arc>) + Send + Sync>, - backend: Arc, -) -> Result<(), sc_service::Error> +pub struct StartLookaheadAuraConsensus(PhantomData); + +impl StartConsensus for StartLookaheadAuraConsensus where RuntimeApi: ConstructNodeRuntimeApi>, RuntimeApi::RuntimeApi: AuraRuntimeApi, { - let info = backend.blockchain().info(); - if !client.runtime_api().has_aura_api(info.finalized_hash) { - return Err(sc_service::error::Error::Other("Missing aura runtime APIs".to_string())); + fn start_consensus( + client: Arc>, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, + relay_chain_interface: Arc, + transaction_pool: Arc>>, + sync_oracle: Arc>, + keystore: KeystorePtr, + relay_chain_slot_duration: Duration, + para_id: ParaId, + collator_key: CollatorPair, + overseer_handle: OverseerHandle, + announce_block: Arc>) + Send + Sync>, + backend: Arc, + ) -> Result<(), Error> { + let info = backend.blockchain().info(); + if !client.runtime_api().has_aura_api(info.finalized_hash) { + return Err(sc_service::error::Error::Other("Missing aura runtime APIs".to_string())); + } + + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry, + telemetry.clone(), + ); + + let collator_service = CollatorService::new( + client.clone(), + Arc::new(task_manager.spawn_handle()), + announce_block, + client.clone(), + ); + + let params = AuraParams { + create_inherent_data_providers: move |_, ()| async move { Ok(()) }, + block_import, + para_client: client.clone(), + para_backend: backend, + relay_client: relay_chain_interface, + code_hash_provider: move |block_hash| { + client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) + }, + sync_oracle, + keystore, + collator_key, + para_id, + overseer_handle, + relay_chain_slot_duration, + proposer: Proposer::new(proposer_factory), + collator_service, + authoring_duration: Duration::from_millis(1500), + reinitialize: false, + }; + + let fut = + aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params); + task_manager.spawn_essential_handle().spawn("aura", None, fut); + + Ok(()) } +} + +pub struct StartRelayToAuraConsensus(PhantomData<(RuntimeApi, AuraId)>); + +impl StartConsensus + for StartRelayToAuraConsensus +where + RuntimeApi: ConstructNodeRuntimeApi>, + RuntimeApi::RuntimeApi: AuraRuntimeApi, + AuraId: AuraIdT + Sync, +{ + fn start_consensus( + client: Arc>, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, + relay_chain_interface: Arc, + transaction_pool: Arc>>, + sync_oracle: Arc>, + keystore: KeystorePtr, + relay_chain_slot_duration: Duration, + para_id: ParaId, + collator_key: CollatorPair, + overseer_handle: OverseerHandle, + announce_block: Arc>) + Send + Sync>, + backend: Arc, + ) -> Result<(), Error> { + let relay_chain_interface2 = relay_chain_interface.clone(); + + let collator_service = CollatorService::new( + client.clone(), + Arc::new(task_manager.spawn_handle()), + announce_block, + client.clone(), + ); - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - - let collator_service = CollatorService::new( - client.clone(), - Arc::new(task_manager.spawn_handle()), - announce_block, - client.clone(), - ); - - let params = AuraParams { - create_inherent_data_providers: move |_, ()| async move { Ok(()) }, - block_import, - para_client: client.clone(), - para_backend: backend, - relay_client: relay_chain_interface, - code_hash_provider: move |block_hash| { - client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) - }, - sync_oracle, - keystore, - collator_key, - para_id, - overseer_handle, - relay_chain_slot_duration, - proposer: Proposer::new(proposer_factory), - collator_service, - authoring_duration: Duration::from_millis(1500), - reinitialize: false, - }; - - let fut = aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params); - task_manager.spawn_essential_handle().spawn("aura", None, fut); - - Ok(()) + let spawner = task_manager.spawn_handle(); + + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + spawner, + client.clone(), + transaction_pool, + prometheus_registry, + telemetry.clone(), + ); + + let collation_future = Box::pin(async move { + // Start collating with the `shell` runtime while waiting for an upgrade to an Aura + // compatible runtime. + let mut request_stream = cumulus_client_collator::relay_chain_driven::init( + collator_key.clone(), + para_id, + overseer_handle.clone(), + ) + .await; + while let Some(request) = request_stream.next().await { + let pvd = request.persisted_validation_data().clone(); + let last_head_hash = + match ::Header::decode(&mut &pvd.parent_head.0[..]) { + Ok(header) => header.hash(), + Err(e) => { + log::error!("Could not decode the head data: {e}"); + request.complete(None); + continue + }, + }; + + // Check if we have upgraded to an Aura compatible runtime and transition if + // necessary. + if client.runtime_api().has_aura_api(last_head_hash) { + // Respond to this request before transitioning to Aura. + request.complete(None); + break + } + } + + // Move to Aura consensus. + let proposer = Proposer::new(proposer_factory); + + let params = AuraParams { + create_inherent_data_providers: move |_, ()| async move { Ok(()) }, + block_import, + para_client: client.clone(), + para_backend: backend, + relay_client: relay_chain_interface2, + code_hash_provider: move |block_hash| { + client.code_at(block_hash).ok().map(|c| ValidationCode::from(c).hash()) + }, + sync_oracle, + keystore, + collator_key, + para_id, + overseer_handle, + relay_chain_slot_duration, + proposer, + collator_service, + authoring_duration: Duration::from_millis(1500), + reinitialize: true, /* we need to always re-initialize for asset-hub moving + * to aura */ + }; + + aura::run::::Pair, _, _, _, _, _, _, _, _, _>(params).await + }); + + let spawner = task_manager.spawn_essential_handle(); + spawner.spawn_essential("cumulus-asset-hub-collator", None, collation_future); + + Ok(()) + } } /// Start an aura powered parachain node which uses the lookahead collator to support async backing. /// This node is basic in the sense that its runtime api doesn't include common contents such as /// transaction payment. Used for aura glutton. -pub async fn start_basic_lookahead_node>( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - |_, _, _, _| Ok(RpcModule::new(())), - build_relay_to_aura_import_queue::<_, AuraId>, - start_lookahead_aura_consensus, - hwbench, - ) - .await +pub struct BasicLookaheadNode; + +impl NodeSpec for BasicLookaheadNode { + type RuntimeApi = FakeRuntimeApi; + type BuildImportQueue = BuildRelayToAuraImportQueue; + type BuildRpcExtensions = BuildEmptyRpcExtensions; + type StartConsensus = StartLookaheadAuraConsensus; + const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } /// Start a parachain node for Rococo Contracts. -pub async fn start_contracts_rococo_node>( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, -) -> sc_service::error::Result { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - CollatorSybilResistance::Resistant, // Aura - para_id, - build_contracts_rpc_extensions, - build_aura_import_queue, - start_lookahead_aura_consensus, - hwbench, - ) - .await +pub struct ContractsRococoNode; + +impl NodeSpec for ContractsRococoNode { + type RuntimeApi = FakeRuntimeApi; + type BuildImportQueue = BuildAuraImportQueue; + type BuildRpcExtensions = BuildContractsRpcExtensions; + type StartConsensus = StartLookaheadAuraConsensus; + const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } /// Checks that the hardware meets the requirements and print a warning otherwise. @@ -937,3 +944,168 @@ fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) { ); } } + +type SyncCmdResult = sc_cli::Result<()>; + +type AsyncCmdResult<'a> = + sc_cli::Result<(Pin + 'a>>, TaskManager)>; + +pub trait DynNodeSpec> { + fn prepare_check_block_cmd( + self: Box, + config: Configuration, + cmd: &CheckBlockCmd, + ) -> AsyncCmdResult<'_>; + + fn prepare_export_blocks_cmd( + self: Box, + config: Configuration, + cmd: &ExportBlocksCmd, + ) -> AsyncCmdResult<'_>; + + fn prepare_export_state_cmd( + self: Box, + config: Configuration, + cmd: &ExportStateCmd, + ) -> AsyncCmdResult<'_>; + + fn prepare_import_blocks_cmd( + self: Box, + config: Configuration, + cmd: &ImportBlocksCmd, + ) -> AsyncCmdResult<'_>; + + fn prepare_revert_cmd( + self: Box, + config: Configuration, + cmd: &RevertCmd, + ) -> AsyncCmdResult<'_>; + + fn run_export_genesis_head_cmd( + self: Box, + config: Configuration, + cmd: &ExportGenesisHeadCommand, + ) -> SyncCmdResult; + + fn run_benchmark_block_cmd( + self: Box, + config: Configuration, + cmd: &BlockCmd, + ) -> SyncCmdResult; + + #[cfg(any(feature = "runtime-benchmarks"))] + fn run_benchmark_storage_cmd( + self: Box, + config: Configuration, + cmd: &StorageCmd, + ) -> SyncCmdResult; + + fn start_node( + self: Box, + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, + ) -> Pin>>>; +} + +#[async_trait::async_trait] +impl DynNodeSpec for T +where + T: NodeSpec, + Net: NetworkBackend, +{ + fn prepare_check_block_cmd( + self: Box, + config: Configuration, + cmd: &CheckBlockCmd, + ) -> AsyncCmdResult<'_> { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + Ok((Box::pin(cmd.run(partial.client, partial.import_queue)), partial.task_manager)) + } + + fn prepare_export_blocks_cmd( + self: Box, + config: Configuration, + cmd: &ExportBlocksCmd, + ) -> AsyncCmdResult<'_> { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + Ok((Box::pin(cmd.run(partial.client, config.database)), partial.task_manager)) + } + + fn prepare_export_state_cmd( + self: Box, + config: Configuration, + cmd: &ExportStateCmd, + ) -> AsyncCmdResult<'_> { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + Ok((Box::pin(cmd.run(partial.client, config.chain_spec)), partial.task_manager)) + } + + fn prepare_import_blocks_cmd( + self: Box, + config: Configuration, + cmd: &ImportBlocksCmd, + ) -> AsyncCmdResult<'_> { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + Ok((Box::pin(cmd.run(partial.client, partial.import_queue)), partial.task_manager)) + } + + fn prepare_revert_cmd( + self: Box, + config: Configuration, + cmd: &RevertCmd, + ) -> AsyncCmdResult<'_> { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + Ok((Box::pin(cmd.run(partial.client, partial.backend, None)), partial.task_manager)) + } + + fn run_export_genesis_head_cmd( + self: Box, + config: Configuration, + cmd: &ExportGenesisHeadCommand, + ) -> SyncCmdResult { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + cmd.run(partial.client) + } + + fn run_benchmark_block_cmd( + self: Box, + config: Configuration, + cmd: &BlockCmd, + ) -> SyncCmdResult { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + cmd.run(partial.client) + } + + #[cfg(any(feature = "runtime-benchmarks"))] + fn run_benchmark_storage_cmd( + self: Box, + config: Configuration, + cmd: &StorageCmd, + ) -> SyncCmdResult { + let partial = Self::new_partial(&config).map_err(sc_cli::Error::Service)?; + let db = partial.backend.expose_db(); + let storage = partial.backend.expose_storage(); + + cmd.run(config, partial.client, db, storage) + } + + fn start_node( + self: Box, + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, + ) -> Pin>>> { + ::start_node::( + parachain_config, + polkadot_config, + collator_options, + para_id, + hwbench, + ) + } +} From 9aa78184e8db27bbd9f64039311104b8023ee94c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 3 Jul 2024 20:39:02 +0300 Subject: [PATCH 06/10] Remove unneeded Net generic for DynNodeSpec --- cumulus/polkadot-parachain/src/command.rs | 37 ++++------------------- cumulus/polkadot-parachain/src/service.rs | 31 ++++++++++++------- 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index 2a5b691af2e9..b3a1d6af1ba1 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -23,7 +23,7 @@ use crate::{ }, service::{ AssetHubLookaheadNode, BasicLookaheadNode, Block, ContractsRococoNode, DynNodeSpec, - GenericAuraLookaheadNode, Hash, RococoParachainNode, ShellNode, + GenericAuraLookaheadNode, RococoParachainNode, ShellNode, }, }; #[cfg(feature = "runtime-benchmarks")] @@ -385,9 +385,9 @@ impl SubstrateCli for RelayChainCli { } } -fn new_node_spec_with_network>( +fn new_node_spec( config: &sc_service::Configuration, -) -> std::result::Result>, sc_cli::Error> { +) -> std::result::Result, sc_cli::Error> { Ok(match config.chain_spec.runtime()? { Runtime::AssetHubPolkadot => Box::new(AssetHubLookaheadNode::< AssetHubPolkadotRuntimeApi, @@ -410,12 +410,6 @@ fn new_node_spec_with_network>( }) } -fn new_node_spec( - config: &sc_service::Configuration, -) -> std::result::Result>, sc_cli::Error> { - new_node_spec_with_network(config) -} - /// Parse command line arguments into service configuration. pub fn run() -> Result<()> { let cli = Cli::from_args(); @@ -593,40 +587,21 @@ pub fn run() -> Result<()> { info!("🧾 Parachain Account: {}", parachain_account); info!("✍️ Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); - match config.network.network_backend { - sc_network::config::NetworkBackendType::Libp2p => - start_node::>( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await, - sc_network::config::NetworkBackendType::Litep2p => - start_node::( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await, - } + start_node(config, polkadot_config, collator_options, id, hwbench).await }) }, } } #[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_node>( +async fn start_node( config: sc_service::Configuration, polkadot_config: sc_service::Configuration, collator_options: cumulus_client_cli::CollatorOptions, id: ParaId, hwbench: Option, ) -> Result { - let node_spec = new_node_spec_with_network::(&config)?; + let node_spec = new_node_spec(&config)?; node_spec .start_node(config, polkadot_config, collator_options, id, hwbench) .await diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index c1d0b859df6d..bb78d4462d25 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -950,7 +950,7 @@ type SyncCmdResult = sc_cli::Result<()>; type AsyncCmdResult<'a> = sc_cli::Result<(Pin + 'a>>, TaskManager)>; -pub trait DynNodeSpec> { +pub trait DynNodeSpec { fn prepare_check_block_cmd( self: Box, config: Configuration, @@ -1010,11 +1010,9 @@ pub trait DynNodeSpec> { ) -> Pin>>>; } -#[async_trait::async_trait] -impl DynNodeSpec for T +impl DynNodeSpec for T where T: NodeSpec, - Net: NetworkBackend, { fn prepare_check_block_cmd( self: Box, @@ -1100,12 +1098,23 @@ where para_id: ParaId, hwbench: Option, ) -> Pin>>> { - ::start_node::( - parachain_config, - polkadot_config, - collator_options, - para_id, - hwbench, - ) + match parachain_config.network.network_backend { + sc_network::config::NetworkBackendType::Libp2p => + ::start_node::>( + parachain_config, + polkadot_config, + collator_options, + para_id, + hwbench, + ), + sc_network::config::NetworkBackendType::Litep2p => + ::start_node::( + parachain_config, + polkadot_config, + collator_options, + para_id, + hwbench, + ), + } } } From df41f671b88fa0e7a9ed33285b8582a492bb6211 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 4 Jul 2024 11:26:49 +0300 Subject: [PATCH 07/10] Address code review comments --- cumulus/polkadot-parachain/src/command.rs | 27 +-- cumulus/polkadot-parachain/src/rpc.rs | 136 ++++++------- cumulus/polkadot-parachain/src/service.rs | 224 +++++----------------- 3 files changed, 119 insertions(+), 268 deletions(-) diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index dd15e04ead68..1db95516ec34 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -14,22 +14,24 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . +#[cfg(feature = "runtime-benchmarks")] +use crate::service::Block; use crate::{ chain_spec, chain_spec::GenericChainSpec, cli::{Cli, RelayChainCli, Subcommand}, - fake_runtime_api::asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, - service::{ - AssetHubLookaheadNode, BasicLookaheadNode, Block, ContractsRococoNode, DynNodeSpec, - GenericAuraLookaheadNode, RococoParachainNode, ShellNode, + fake_runtime_api::{ + asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, + aura::RuntimeApi as AuraRuntimeApi, }, + service::{BasicLookaheadNode, DynNodeSpec, GenericAuraLookaheadNode, ShellNode}, }; #[cfg(feature = "runtime-benchmarks")] use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; use log::info; -use parachains_common::AssetHubPolkadotAuraId; +use parachains_common::{AssetHubPolkadotAuraId, AuraId}; use sc_cli::{ ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, SharedParams, SubstrateCli, @@ -387,21 +389,22 @@ fn new_node_spec( config: &sc_service::Configuration, ) -> std::result::Result, sc_cli::Error> { Ok(match config.chain_spec.runtime()? { - Runtime::AssetHubPolkadot => Box::new(AssetHubLookaheadNode::< + Runtime::AssetHubPolkadot => Box::new(GenericAuraLookaheadNode::< AssetHubPolkadotRuntimeApi, AssetHubPolkadotAuraId, - >(Default::default())), + >::default()), Runtime::AssetHub | Runtime::BridgeHub(_) | Runtime::Collectives | Runtime::Coretime(_) | - Runtime::People(_) => Box::new(GenericAuraLookaheadNode), + Runtime::People(_) | + Runtime::ContractsRococo | + Runtime::Penpal(_) => Box::new(GenericAuraLookaheadNode::::default()), Runtime::Shell | Runtime::Seedling => Box::new(ShellNode), - Runtime::ContractsRococo => Box::new(ContractsRococoNode), - Runtime::Penpal(_) => Box::new(RococoParachainNode), Runtime::Glutton => Box::new(BasicLookaheadNode), Runtime::Omni(consensus) => match consensus { - Consensus::Aura => Box::new(RococoParachainNode), + Consensus::Aura => + Box::new(GenericAuraLookaheadNode::::default()), Consensus::Relay => Box::new(ShellNode), }, }) @@ -502,8 +505,6 @@ pub fn run() -> Result<()> { }), BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), - // NOTE: this allows the Client to leniently implement - // new benchmark commands without requiring a companion MR. #[allow(unreachable_patterns)] _ => Err("Benchmarking sub-command unsupported or compilation feature missing. \ Make sure to compile with --features=runtime-benchmarks \ diff --git a/cumulus/polkadot-parachain/src/rpc.rs b/cumulus/polkadot-parachain/src/rpc.rs index a42498e7ffe8..283a73d931d7 100644 --- a/cumulus/polkadot-parachain/src/rpc.rs +++ b/cumulus/polkadot-parachain/src/rpc.rs @@ -18,100 +18,82 @@ #![warn(missing_docs)] -use std::sync::Arc; - +use crate::{ + common::ConstructNodeRuntimeApi, + service::{ParachainBackend, ParachainClient}, +}; +use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; use parachains_common::{AccountId, Balance, Block, Nonce}; -use sc_client_api::AuxStore; -pub use sc_rpc::DenyUnsafe; -use sc_transaction_pool_api::TransactionPool; -use sp_api::ProvideRuntimeApi; -use sp_block_builder::BlockBuilder; -use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; +use sc_rpc::{ + dev::{Dev, DevApiServer}, + DenyUnsafe, +}; +use std::{marker::PhantomData, sync::Arc}; +use substrate_frame_rpc_system::{System, SystemApiServer}; +use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer}; /// A type representing all RPC extensions. pub type RpcExtension = jsonrpsee::RpcModule<()>; -pub trait BuildRpcExtensions { +pub(crate) trait BuildRpcExtensions { fn build_rpc_extensions( deny_unsafe: DenyUnsafe, client: Arc, backend: Arc, pool: Arc, - ) -> sc_service::error::Result>; + ) -> sc_service::error::Result; } -/// Full client dependencies -pub struct FullDeps { - /// The client instance to use. - pub client: Arc, - /// Transaction pool instance. - pub pool: Arc

, - /// Whether to deny unsafe calls - pub deny_unsafe: DenyUnsafe, -} +pub(crate) struct BuildEmptyRpcExtensions(PhantomData); -/// Instantiate all RPC extensions. -pub fn create_full( - deps: FullDeps, - backend: Arc, -) -> Result> +impl + BuildRpcExtensions< + ParachainClient, + ParachainBackend, + sc_transaction_pool::FullPool>, + > for BuildEmptyRpcExtensions where - C: ProvideRuntimeApi - + HeaderBackend - + AuxStore - + HeaderMetadata - + Send - + Sync - + 'static, - C::Api: substrate_frame_rpc_system::AccountNonceApi, - C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, - C::Api: BlockBuilder, - P: TransactionPool + Sync + Send + 'static, - B: sc_client_api::Backend + Send + Sync + 'static, - B::State: sc_client_api::backend::StateBackend>, + RuntimeApi: ConstructNodeRuntimeApi> + Send + Sync + 'static, { - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use substrate_frame_rpc_system::{System, SystemApiServer}; - use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer}; - - let mut module = RpcExtension::new(()); - let FullDeps { client, pool, deny_unsafe } = deps; - - module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; - module.merge(TransactionPayment::new(client.clone()).into_rpc())?; - module.merge(StateMigration::new(client, backend, deny_unsafe).into_rpc())?; - - Ok(module) + fn build_rpc_extensions( + _deny_unsafe: DenyUnsafe, + _client: Arc>, + _backend: Arc, + _pool: Arc>>, + ) -> sc_service::error::Result { + Ok(RpcExtension::new(())) + } } -/// Instantiate all RPCs we want at the contracts-rococo chain. -pub fn create_contracts_rococo( - deps: FullDeps, -) -> Result> +pub(crate) struct BuildParachainRpcExtensions(PhantomData); + +impl + BuildRpcExtensions< + ParachainClient, + ParachainBackend, + sc_transaction_pool::FullPool>, + > for BuildParachainRpcExtensions where - C: ProvideRuntimeApi - + sc_client_api::BlockBackend - + HeaderBackend - + AuxStore - + HeaderMetadata - + Send - + Sync - + 'static, - C::Api: substrate_frame_rpc_system::AccountNonceApi, - C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, - C::Api: BlockBuilder, - P: TransactionPool + Sync + Send + 'static, + RuntimeApi: ConstructNodeRuntimeApi> + Send + Sync + 'static, + RuntimeApi::RuntimeApi: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + substrate_frame_rpc_system::AccountNonceApi, { - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use sc_rpc::dev::{Dev, DevApiServer}; - use substrate_frame_rpc_system::{System, SystemApiServer}; - - let mut module = RpcExtension::new(()); - let FullDeps { client, pool, deny_unsafe } = deps; - - module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; - module.merge(TransactionPayment::new(client.clone()).into_rpc())?; - module.merge(Dev::new(client, deny_unsafe).into_rpc())?; - - Ok(module) + fn build_rpc_extensions( + deny_unsafe: DenyUnsafe, + client: Arc>, + backend: Arc, + pool: Arc>>, + ) -> sc_service::error::Result { + let build = || -> Result> { + let mut module = RpcExtension::new(()); + + module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; + module.merge(TransactionPayment::new(client.clone()).into_rpc())?; + module.merge(StateMigration::new(client.clone(), backend, deny_unsafe).into_rpc())?; + module.merge(Dev::new(client, deny_unsafe).into_rpc())?; + + Ok(module) + }; + build().map_err(Into::into) + } } diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index 836e1636ebca..9b4400e668a5 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -28,9 +28,6 @@ use cumulus_client_service::{ }; use cumulus_primitives_core::{relay_chain::ValidationCode, ParaId}; use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; -use sc_rpc::DenyUnsafe; - -use jsonrpsee::RpcModule; use crate::{ common::{ @@ -38,11 +35,11 @@ use crate::{ ConstructNodeRuntimeApi, }, fake_runtime_api::aura::RuntimeApi as FakeRuntimeApi, - rpc, rpc::BuildRpcExtensions, }; pub use parachains_common::{AccountId, AuraId, Balance, Block, Hash, Nonce}; +use crate::rpc::{BuildEmptyRpcExtensions, BuildParachainRpcExtensions}; use frame_benchmarking_cli::BlockCmd; #[cfg(any(feature = "runtime-benchmarks"))] use frame_benchmarking_cli::StorageCmd; @@ -78,7 +75,7 @@ type HostFunctions = ( pub type ParachainClient = TFullClient>; -type ParachainBackend = TFullBackend; +pub type ParachainBackend = TFullBackend; type ParachainBlockImport = TParachainBlockImport>, ParachainBackend>; @@ -93,7 +90,7 @@ pub type Service = PartialComponents< (ParachainBlockImport, Option, Option), >; -pub trait BuildImportQueue { +pub(crate) trait BuildImportQueue { fn build_import_queue( client: Arc>, block_import: ParachainBlockImport, @@ -103,7 +100,7 @@ pub trait BuildImportQueue { ) -> sc_service::error::Result>; } -pub trait StartConsensus +pub(crate) trait StartConsensus where RuntimeApi: ConstructNodeRuntimeApi>, { @@ -126,7 +123,7 @@ where ) -> Result<(), sc_service::Error>; } -pub trait NodeSpec { +pub(crate) trait NodeSpec { type RuntimeApi: ConstructNodeRuntimeApi>; type BuildImportQueue: BuildImportQueue + 'static; @@ -370,61 +367,8 @@ pub trait NodeSpec { } } -/// Build the import queue for Aura-based runtimes. -pub struct BuildAuraImportQueue(PhantomData); - -impl BuildImportQueue for BuildAuraImportQueue { - fn build_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry_handle: Option, - task_manager: &TaskManager, - ) -> sc_service::error::Result> { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - - cumulus_client_consensus_aura::import_queue::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - >(cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry: telemetry_handle, - }) - .map_err(Into::into) - } -} - -pub struct RococoParachainNode; - -impl NodeSpec for RococoParachainNode { - type RuntimeApi = FakeRuntimeApi; - type BuildImportQueue = BuildAuraImportQueue; - type BuildRpcExtensions = BuildParachainRpcExtensions; - type StartConsensus = StartLookaheadAuraConsensus; - - const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; -} - /// Build the import queue for the shell runtime. -pub struct BuildShellImportQueue(PhantomData); +pub(crate) struct BuildShellImportQueue(PhantomData); impl BuildImportQueue for BuildShellImportQueue { fn build_import_queue( @@ -445,74 +389,7 @@ impl BuildImportQueue for BuildShellImportQueue } } -pub struct BuildParachainRpcExtensions(PhantomData); - -impl - BuildRpcExtensions< - ParachainClient, - ParachainBackend, - sc_transaction_pool::FullPool>, - > for BuildParachainRpcExtensions -where - RuntimeApi: ConstructNodeRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi - + substrate_frame_rpc_system::AccountNonceApi, -{ - fn build_rpc_extensions( - deny_unsafe: DenyUnsafe, - client: Arc>, - backend: Arc, - pool: Arc>>, - ) -> sc_service::error::Result> { - let deps = rpc::FullDeps { client, pool, deny_unsafe }; - - rpc::create_full(deps, backend).map_err(Into::into) - } -} - -pub struct BuildContractsRpcExtensions; - -impl - BuildRpcExtensions< - ParachainClient, - ParachainBackend, - sc_transaction_pool::FullPool>, - > for BuildContractsRpcExtensions -{ - fn build_rpc_extensions( - deny_unsafe: DenyUnsafe, - client: Arc>, - _backend: Arc, - pool: Arc>>, - ) -> sc_service::error::Result> { - let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; - - crate::rpc::create_contracts_rococo(deps).map_err(Into::into) - } -} - -pub struct BuildEmptyRpcExtensions(PhantomData); - -impl - BuildRpcExtensions< - ParachainClient, - ParachainBackend, - sc_transaction_pool::FullPool>, - > for BuildEmptyRpcExtensions -where - RuntimeApi: ConstructNodeRuntimeApi> + Send + Sync + 'static, -{ - fn build_rpc_extensions( - _deny_unsafe: DenyUnsafe, - _client: Arc>, - _backend: Arc, - _pool: Arc>>, - ) -> sc_service::error::Result> { - Ok(RpcModule::new(())) - } -} - -pub struct ShellNode; +pub(crate) struct ShellNode; impl NodeSpec for ShellNode { type RuntimeApi = FakeRuntimeApi; @@ -551,7 +428,9 @@ where /// Build the import queue for parachain runtimes that started with relay chain consensus and /// switched to aura. -pub struct BuildRelayToAuraImportQueue(PhantomData<(RuntimeApi, AuraId)>); +pub(crate) struct BuildRelayToAuraImportQueue( + PhantomData<(RuntimeApi, AuraId)>, +); impl BuildImportQueue for BuildRelayToAuraImportQueue @@ -615,19 +494,17 @@ where /// Uses the lookahead collator to support async backing. /// /// Start an aura powered parachain node. Some system chains use this. -pub struct GenericAuraLookaheadNode; +pub(crate) struct GenericAuraLookaheadNode( + pub PhantomData<(RuntimeApi, AuraId)>, +); -impl NodeSpec for GenericAuraLookaheadNode { - type RuntimeApi = FakeRuntimeApi; - type BuildImportQueue = BuildRelayToAuraImportQueue; - type BuildRpcExtensions = BuildParachainRpcExtensions; - type StartConsensus = StartLookaheadAuraConsensus; - const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; +impl Default for GenericAuraLookaheadNode { + fn default() -> Self { + Self(Default::default()) + } } -pub struct AssetHubLookaheadNode(pub PhantomData<(RuntimeApi, AuraId)>); - -impl NodeSpec for AssetHubLookaheadNode +impl NodeSpec for GenericAuraLookaheadNode where RuntimeApi: ConstructNodeRuntimeApi>, RuntimeApi::RuntimeApi: AuraRuntimeApi @@ -642,31 +519,9 @@ where const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } -/// Wait for the Aura runtime API to appear on chain. -/// This is useful for chains that started out without Aura. Components that -/// are depending on Aura functionality will wait until Aura appears in the runtime. -async fn wait_for_aura(client: Arc>) -where - RuntimeApi: ConstructNodeRuntimeApi>, - RuntimeApi::RuntimeApi: AuraRuntimeApi, - AuraId: AuraIdT + Sync, -{ - let finalized_hash = client.chain_info().finalized_hash; - if client.runtime_api().has_aura_api(finalized_hash) { - return; - }; - - let mut stream = client.finality_notification_stream(); - while let Some(notification) = stream.next().await { - if client.runtime_api().has_aura_api(notification.hash) { - return; - } - } -} - /// Start relay-chain consensus that is free for all. Everyone can submit a block, the relay-chain /// decides what is backed and included. -pub struct StartRelayChainConsensus; +pub(crate) struct StartRelayChainConsensus; impl StartConsensus for StartRelayChainConsensus { fn start_consensus( @@ -740,8 +595,32 @@ impl StartConsensus for StartRelayChainConsensus { } } +/// Wait for the Aura runtime API to appear on chain. +/// This is useful for chains that started out without Aura. Components that +/// are depending on Aura functionality will wait until Aura appears in the runtime. +async fn wait_for_aura(client: Arc>) +where + RuntimeApi: ConstructNodeRuntimeApi>, + RuntimeApi::RuntimeApi: AuraRuntimeApi, + AuraId: AuraIdT + Sync, +{ + let finalized_hash = client.chain_info().finalized_hash; + if client.runtime_api().has_aura_api(finalized_hash) { + return; + }; + + let mut stream = client.finality_notification_stream(); + while let Some(notification) = stream.next().await { + if client.runtime_api().has_aura_api(notification.hash) { + return; + } + } +} + /// Start consensus using the lookahead aura collator. -pub struct StartLookaheadAuraConsensus(PhantomData<(RuntimeApi, AuraId)>); +pub(crate) struct StartLookaheadAuraConsensus( + PhantomData<(RuntimeApi, AuraId)>, +); impl StartConsensus for StartLookaheadAuraConsensus @@ -820,7 +699,7 @@ where /// Start an aura powered parachain node which uses the lookahead collator to support async backing. /// This node is basic in the sense that its runtime api doesn't include common contents such as /// transaction payment. Used for aura glutton. -pub struct BasicLookaheadNode; +pub(crate) struct BasicLookaheadNode; impl NodeSpec for BasicLookaheadNode { type RuntimeApi = FakeRuntimeApi; @@ -830,17 +709,6 @@ impl NodeSpec for BasicLookaheadNode { const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } -/// Start a parachain node for Rococo Contracts. -pub struct ContractsRococoNode; - -impl NodeSpec for ContractsRococoNode { - type RuntimeApi = FakeRuntimeApi; - type BuildImportQueue = BuildAuraImportQueue; - type BuildRpcExtensions = BuildContractsRpcExtensions; - type StartConsensus = StartLookaheadAuraConsensus; - const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; -} - /// Checks that the hardware meets the requirements and print a warning otherwise. fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) { // Polkadot para-chains should generally use these requirements to ensure that the relay-chain @@ -859,7 +727,7 @@ type SyncCmdResult = sc_cli::Result<()>; type AsyncCmdResult<'a> = sc_cli::Result<(Pin + 'a>>, TaskManager)>; -pub trait DynNodeSpec { +pub(crate) trait DynNodeSpec { fn prepare_check_block_cmd( self: Box, config: Configuration, From 1b63aa66e4c08a5406689edfbd72ab09657ae568 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 5 Jul 2024 23:07:55 +0300 Subject: [PATCH 08/10] Use experimental_use_slot_based flag --- cumulus/polkadot-parachain/src/command.rs | 29 ++++++++++--------- cumulus/polkadot-parachain/src/service.rs | 35 +++++++++++++++++++---- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index be5af70fa2f2..2a63316dddac 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -24,7 +24,7 @@ use crate::{ asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, aura::RuntimeApi as AuraRuntimeApi, }, - service::{BasicLookaheadNode, DynNodeSpec, GenericAuraAsyncBackingNode, ShellNode}, + service::{new_aura_node_spec, BasicLookaheadNode, DynNodeSpec, ShellNode}, }; #[cfg(feature = "runtime-benchmarks")] use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; @@ -387,24 +387,25 @@ impl SubstrateCli for RelayChainCli { fn new_node_spec( config: &sc_service::Configuration, + use_experimental_slot_based: bool, ) -> std::result::Result, sc_cli::Error> { Ok(match config.chain_spec.runtime()? { - Runtime::AssetHubPolkadot => Box::new(GenericAuraAsyncBackingNode::< + Runtime::AssetHubPolkadot => new_aura_node_spec::< AssetHubPolkadotRuntimeApi, AssetHubPolkadotAuraId, - >::default()), + >(use_experimental_slot_based), Runtime::AssetHub | Runtime::BridgeHub(_) | Runtime::Collectives | Runtime::Coretime(_) | Runtime::People(_) | Runtime::ContractsRococo | - Runtime::Penpal(_) => Box::new(GenericAuraAsyncBackingNode::::default()), + Runtime::Penpal(_) => new_aura_node_spec::(use_experimental_slot_based), Runtime::Shell | Runtime::Seedling => Box::new(ShellNode), Runtime::Glutton => Box::new(BasicLookaheadNode), Runtime::Omni(consensus) => match consensus { Consensus::Aura => - Box::new(GenericAuraAsyncBackingNode::::default()), + new_aura_node_spec::(use_experimental_slot_based), Consensus::Relay => Box::new(ShellNode), }, }) @@ -422,35 +423,35 @@ pub fn run() -> Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.prepare_check_block_cmd(config, cmd) }) }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.prepare_export_blocks_cmd(config, cmd) }) }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.prepare_export_state_cmd(config, cmd) }) }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.prepare_import_blocks_cmd(config, cmd) }) }, Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.prepare_revert_cmd(config, cmd) }) }, @@ -472,7 +473,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisHead(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.run_export_genesis_head_cmd(config, cmd) }) }, @@ -495,12 +496,12 @@ pub fn run() -> Result<()> { )) }), BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.run_benchmark_block_cmd(config, cmd) }), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { - let node = new_node_spec(&config)?; + let node = new_node_spec(&config, cli.experimental_use_slot_based)?; node.run_benchmark_storage_cmd(config, cmd) }), BenchmarkCmd::Machine(cmd) => @@ -608,7 +609,7 @@ async fn start_node( use_experimental_slot_based: bool, hwbench: Option, ) -> Result { - let node_spec = new_node_spec(&config)?; + let node_spec = new_node_spec(&config, use_experimental_slot_based)?; node_spec .start_node(config, polkadot_config, collator_options, id, hwbench) .await diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index 618b8418ed6b..136fb4215cc9 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -494,31 +494,56 @@ where /// Uses the lookahead collator to support async backing. /// /// Start an aura powered parachain node. Some system chains use this. -pub(crate) struct GenericAuraAsyncBackingNode( - pub PhantomData<(RuntimeApi, AuraId)>, +pub(crate) struct AuraNode( + pub PhantomData<(RuntimeApi, AuraId, StartConsensus)>, ); -impl Default for GenericAuraAsyncBackingNode { +impl Default for AuraNode { fn default() -> Self { Self(Default::default()) } } -impl NodeSpec for GenericAuraAsyncBackingNode +impl NodeSpec for AuraNode where RuntimeApi: ConstructNodeRuntimeApi>, RuntimeApi::RuntimeApi: AuraRuntimeApi + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + substrate_frame_rpc_system::AccountNonceApi, AuraId: AuraIdT + Sync, + StartConsensus: self::StartConsensus + 'static, { type RuntimeApi = RuntimeApi; type BuildImportQueue = BuildRelayToAuraImportQueue; type BuildRpcExtensions = BuildParachainRpcExtensions; - type StartConsensus = StartLookaheadAuraConsensus; + type StartConsensus = StartConsensus; const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } +pub fn new_aura_node_spec( + use_experimental_slot_based: bool, +) -> Box +where + RuntimeApi: ConstructNodeRuntimeApi>, + RuntimeApi::RuntimeApi: AuraRuntimeApi + + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + substrate_frame_rpc_system::AccountNonceApi, + AuraId: AuraIdT + Sync, +{ + match use_experimental_slot_based { + true => Box::new(AuraNode::< + RuntimeApi, + AuraId, + StartSlotBasedAuraConsensus, + >::default()), + false => Box::new(AuraNode::< + RuntimeApi, + AuraId, + StartLookaheadAuraConsensus, + >::default()), + } +} + /// Start relay-chain consensus that is free for all. Everyone can submit a block, the relay-chain /// decides what is backed and included. pub(crate) struct StartRelayChainConsensus; From 9c5f5bbae4fa465a9684c699679ef3cdc2af0748 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 8 Jul 2024 17:36:27 +0300 Subject: [PATCH 09/10] Code review comments --- cumulus/polkadot-parachain/src/cli.rs | 16 ++++++--- cumulus/polkadot-parachain/src/command.rs | 42 ++++++++++------------- cumulus/polkadot-parachain/src/service.rs | 13 +++---- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/cumulus/polkadot-parachain/src/cli.rs b/cumulus/polkadot-parachain/src/cli.rs index 7c01e34f9a03..7a3a7de0382d 100644 --- a/cumulus/polkadot-parachain/src/cli.rs +++ b/cumulus/polkadot-parachain/src/cli.rs @@ -59,6 +59,15 @@ pub enum Subcommand { Benchmark(frame_benchmarking_cli::BenchmarkCmd), } +#[derive(Debug, clap::Parser)] +pub struct ExtraArgs { + /// EXPERIMENTAL: Use slot-based collator which can handle elastic scaling. + /// + /// Use with care, this flag is unstable and subject to change. + #[arg(long)] + pub experimental_use_slot_based: bool, +} + #[derive(Debug, clap::Parser)] #[command( propagate_version = true, @@ -73,11 +82,8 @@ pub struct Cli { #[command(flatten)] pub run: cumulus_client_cli::RunCmd, - /// EXPERIMENTAL: Use slot-based collator which can handle elastic scaling. - /// - /// Use with care, this flag is unstable and subject to change. - #[arg(long)] - pub experimental_use_slot_based: bool, + #[command(flatten)] + pub extra_args: ExtraArgs, /// Disable automatic hardware benchmarks. /// diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index 2a63316dddac..797938af7d0b 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -19,7 +19,7 @@ use crate::service::Block; use crate::{ chain_spec, chain_spec::GenericChainSpec, - cli::{Cli, RelayChainCli, Subcommand}, + cli::{Cli, ExtraArgs, RelayChainCli, Subcommand}, fake_runtime_api::{ asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, aura::RuntimeApi as AuraRuntimeApi, @@ -387,25 +387,26 @@ impl SubstrateCli for RelayChainCli { fn new_node_spec( config: &sc_service::Configuration, - use_experimental_slot_based: bool, + extra_args: &ExtraArgs, ) -> std::result::Result, sc_cli::Error> { Ok(match config.chain_spec.runtime()? { Runtime::AssetHubPolkadot => new_aura_node_spec::< AssetHubPolkadotRuntimeApi, AssetHubPolkadotAuraId, - >(use_experimental_slot_based), + >(extra_args.experimental_use_slot_based), Runtime::AssetHub | Runtime::BridgeHub(_) | Runtime::Collectives | Runtime::Coretime(_) | Runtime::People(_) | Runtime::ContractsRococo | - Runtime::Penpal(_) => new_aura_node_spec::(use_experimental_slot_based), + Runtime::Penpal(_) => + new_aura_node_spec::(extra_args.experimental_use_slot_based), Runtime::Shell | Runtime::Seedling => Box::new(ShellNode), Runtime::Glutton => Box::new(BasicLookaheadNode), Runtime::Omni(consensus) => match consensus { Consensus::Aura => - new_aura_node_spec::(use_experimental_slot_based), + new_aura_node_spec::(extra_args.experimental_use_slot_based), Consensus::Relay => Box::new(ShellNode), }, }) @@ -423,35 +424,35 @@ pub fn run() -> Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.prepare_check_block_cmd(config, cmd) }) }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.prepare_export_blocks_cmd(config, cmd) }) }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.prepare_export_state_cmd(config, cmd) }) }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.prepare_import_blocks_cmd(config, cmd) }) }, Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.prepare_revert_cmd(config, cmd) }) }, @@ -473,7 +474,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisHead(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.run_export_genesis_head_cmd(config, cmd) }) }, @@ -496,12 +497,12 @@ pub fn run() -> Result<()> { )) }), BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.run_benchmark_block_cmd(config, cmd) }), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { - let node = new_node_spec(&config, cli.experimental_use_slot_based)?; + let node = new_node_spec(&config, &cli.extra_args)?; node.run_benchmark_storage_cmd(config, cmd) }), BenchmarkCmd::Machine(cmd) => @@ -586,15 +587,8 @@ pub fn run() -> Result<()> { info!("🧾 Parachain Account: {}", parachain_account); info!("✍️ Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); - start_node( - config, - polkadot_config, - collator_options, - id, - cli.experimental_use_slot_based, - hwbench, - ) - .await + start_node(config, polkadot_config, collator_options, id, &cli.extra_args, hwbench) + .await }) }, } @@ -606,10 +600,10 @@ async fn start_node( polkadot_config: sc_service::Configuration, collator_options: cumulus_client_cli::CollatorOptions, id: ParaId, - use_experimental_slot_based: bool, + extra_args: &ExtraArgs, hwbench: Option, ) -> Result { - let node_spec = new_node_spec(&config, use_experimental_slot_based)?; + let node_spec = new_node_spec(&config, extra_args)?; node_spec .start_node(config, polkadot_config, collator_options, id, hwbench) .await diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index 136fb4215cc9..696b8b429720 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -521,7 +521,7 @@ where } pub fn new_aura_node_spec( - use_experimental_slot_based: bool, + use_slot_based_consensus: bool, ) -> Box where RuntimeApi: ConstructNodeRuntimeApi>, @@ -530,17 +530,18 @@ where + substrate_frame_rpc_system::AccountNonceApi, AuraId: AuraIdT + Sync, { - match use_experimental_slot_based { - true => Box::new(AuraNode::< + if use_slot_based_consensus { + Box::new(AuraNode::< RuntimeApi, AuraId, StartSlotBasedAuraConsensus, - >::default()), - false => Box::new(AuraNode::< + >::default()) + } else { + Box::new(AuraNode::< RuntimeApi, AuraId, StartLookaheadAuraConsensus, - >::default()), + >::default()) } } From e5b3043e5025b53a2886ba412822e198a0bf11f9 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 9 Jul 2024 09:41:26 +0300 Subject: [PATCH 10/10] Addressing more code review comments --- cumulus/polkadot-parachain/src/cli.rs | 23 ++++----- cumulus/polkadot-parachain/src/command.rs | 50 +++++++++++--------- cumulus/polkadot-parachain/src/common/mod.rs | 5 ++ cumulus/polkadot-parachain/src/service.rs | 23 ++------- 4 files changed, 48 insertions(+), 53 deletions(-) diff --git a/cumulus/polkadot-parachain/src/cli.rs b/cumulus/polkadot-parachain/src/cli.rs index 7a3a7de0382d..d06354dda220 100644 --- a/cumulus/polkadot-parachain/src/cli.rs +++ b/cumulus/polkadot-parachain/src/cli.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . +use crate::common::NodeExtraArgs; use clap::{Command, CommandFactory, FromArgMatches}; use sc_cli::SubstrateCli; use std::path::PathBuf; @@ -59,15 +60,6 @@ pub enum Subcommand { Benchmark(frame_benchmarking_cli::BenchmarkCmd), } -#[derive(Debug, clap::Parser)] -pub struct ExtraArgs { - /// EXPERIMENTAL: Use slot-based collator which can handle elastic scaling. - /// - /// Use with care, this flag is unstable and subject to change. - #[arg(long)] - pub experimental_use_slot_based: bool, -} - #[derive(Debug, clap::Parser)] #[command( propagate_version = true, @@ -82,8 +74,11 @@ pub struct Cli { #[command(flatten)] pub run: cumulus_client_cli::RunCmd, - #[command(flatten)] - pub extra_args: ExtraArgs, + /// EXPERIMENTAL: Use slot-based collator which can handle elastic scaling. + /// + /// Use with care, this flag is unstable and subject to change. + #[arg(long)] + pub experimental_use_slot_based: bool, /// Disable automatic hardware benchmarks. /// @@ -100,6 +95,12 @@ pub struct Cli { pub relay_chain_args: Vec, } +impl Cli { + pub(crate) fn node_extra_args(&self) -> NodeExtraArgs { + NodeExtraArgs { use_slot_based_consensus: self.experimental_use_slot_based } + } +} + #[derive(Debug)] pub struct RelayChainCli { /// The actual relay chain cli object. diff --git a/cumulus/polkadot-parachain/src/command.rs b/cumulus/polkadot-parachain/src/command.rs index 797938af7d0b..fcf6c06f4222 100644 --- a/cumulus/polkadot-parachain/src/command.rs +++ b/cumulus/polkadot-parachain/src/command.rs @@ -19,12 +19,13 @@ use crate::service::Block; use crate::{ chain_spec, chain_spec::GenericChainSpec, - cli::{Cli, ExtraArgs, RelayChainCli, Subcommand}, + cli::{Cli, RelayChainCli, Subcommand}, + common::NodeExtraArgs, fake_runtime_api::{ asset_hub_polkadot_aura::RuntimeApi as AssetHubPolkadotRuntimeApi, aura::RuntimeApi as AuraRuntimeApi, }, - service::{new_aura_node_spec, BasicLookaheadNode, DynNodeSpec, ShellNode}, + service::{new_aura_node_spec, DynNodeSpec, ShellNode}, }; #[cfg(feature = "runtime-benchmarks")] use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; @@ -387,26 +388,22 @@ impl SubstrateCli for RelayChainCli { fn new_node_spec( config: &sc_service::Configuration, - extra_args: &ExtraArgs, + extra_args: NodeExtraArgs, ) -> std::result::Result, sc_cli::Error> { Ok(match config.chain_spec.runtime()? { - Runtime::AssetHubPolkadot => new_aura_node_spec::< - AssetHubPolkadotRuntimeApi, - AssetHubPolkadotAuraId, - >(extra_args.experimental_use_slot_based), + Runtime::AssetHubPolkadot => + new_aura_node_spec::(extra_args), Runtime::AssetHub | Runtime::BridgeHub(_) | Runtime::Collectives | Runtime::Coretime(_) | Runtime::People(_) | Runtime::ContractsRococo | - Runtime::Penpal(_) => - new_aura_node_spec::(extra_args.experimental_use_slot_based), + Runtime::Glutton | + Runtime::Penpal(_) => new_aura_node_spec::(extra_args), Runtime::Shell | Runtime::Seedling => Box::new(ShellNode), - Runtime::Glutton => Box::new(BasicLookaheadNode), Runtime::Omni(consensus) => match consensus { - Consensus::Aura => - new_aura_node_spec::(extra_args.experimental_use_slot_based), + Consensus::Aura => new_aura_node_spec::(extra_args), Consensus::Relay => Box::new(ShellNode), }, }) @@ -424,35 +421,35 @@ pub fn run() -> Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.prepare_check_block_cmd(config, cmd) }) }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.prepare_export_blocks_cmd(config, cmd) }) }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.prepare_export_state_cmd(config, cmd) }) }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.prepare_import_blocks_cmd(config, cmd) }) }, Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.prepare_revert_cmd(config, cmd) }) }, @@ -474,7 +471,7 @@ pub fn run() -> Result<()> { Some(Subcommand::ExportGenesisHead(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.run_export_genesis_head_cmd(config, cmd) }) }, @@ -497,12 +494,12 @@ pub fn run() -> Result<()> { )) }), BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.run_benchmark_block_cmd(config, cmd) }), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { - let node = new_node_spec(&config, &cli.extra_args)?; + let node = new_node_spec(&config, cli.node_extra_args())?; node.run_benchmark_storage_cmd(config, cmd) }), BenchmarkCmd::Machine(cmd) => @@ -587,8 +584,15 @@ pub fn run() -> Result<()> { info!("🧾 Parachain Account: {}", parachain_account); info!("✍️ Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); - start_node(config, polkadot_config, collator_options, id, &cli.extra_args, hwbench) - .await + start_node( + config, + polkadot_config, + collator_options, + id, + cli.node_extra_args(), + hwbench, + ) + .await }) }, } @@ -600,7 +604,7 @@ async fn start_node( polkadot_config: sc_service::Configuration, collator_options: cumulus_client_cli::CollatorOptions, id: ParaId, - extra_args: &ExtraArgs, + extra_args: NodeExtraArgs, hwbench: Option, ) -> Result { let node_spec = new_node_spec(&config, extra_args)?; diff --git a/cumulus/polkadot-parachain/src/common/mod.rs b/cumulus/polkadot-parachain/src/common/mod.rs index 5adbb4137cd3..9f5febafe304 100644 --- a/cumulus/polkadot-parachain/src/common/mod.rs +++ b/cumulus/polkadot-parachain/src/common/mod.rs @@ -65,3 +65,8 @@ where { type BoundedRuntimeApi = T::RuntimeApi; } + +/// Extra args that are passed when creating a new node spec. +pub struct NodeExtraArgs { + pub use_slot_based_consensus: bool, +} diff --git a/cumulus/polkadot-parachain/src/service.rs b/cumulus/polkadot-parachain/src/service.rs index 696b8b429720..f5f6189d1f0d 100644 --- a/cumulus/polkadot-parachain/src/service.rs +++ b/cumulus/polkadot-parachain/src/service.rs @@ -35,12 +35,12 @@ use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; use crate::{ common::{ aura::{AuraIdT, AuraRuntimeApi}, - ConstructNodeRuntimeApi, + ConstructNodeRuntimeApi, NodeExtraArgs, }, fake_runtime_api::aura::RuntimeApi as FakeRuntimeApi, rpc::BuildRpcExtensions, }; -pub use parachains_common::{AccountId, AuraId, Balance, Block, Hash, Nonce}; +pub use parachains_common::{AccountId, Balance, Block, Hash, Nonce}; use crate::rpc::{BuildEmptyRpcExtensions, BuildParachainRpcExtensions}; use frame_benchmarking_cli::BlockCmd; @@ -520,9 +520,7 @@ where const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; } -pub fn new_aura_node_spec( - use_slot_based_consensus: bool, -) -> Box +pub fn new_aura_node_spec(extra_args: NodeExtraArgs) -> Box where RuntimeApi: ConstructNodeRuntimeApi>, RuntimeApi::RuntimeApi: AuraRuntimeApi @@ -530,7 +528,7 @@ where + substrate_frame_rpc_system::AccountNonceApi, AuraId: AuraIdT + Sync, { - if use_slot_based_consensus { + if extra_args.use_slot_based_consensus { Box::new(AuraNode::< RuntimeApi, AuraId, @@ -800,19 +798,6 @@ where } } -/// Start an aura powered parachain node which uses the lookahead collator to support async backing. -/// This node is basic in the sense that its runtime api doesn't include common contents such as -/// transaction payment. Used for aura glutton. -pub(crate) struct BasicLookaheadNode; - -impl NodeSpec for BasicLookaheadNode { - type RuntimeApi = FakeRuntimeApi; - type BuildImportQueue = BuildRelayToAuraImportQueue; - type BuildRpcExtensions = BuildEmptyRpcExtensions; - type StartConsensus = StartLookaheadAuraConsensus; - const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; -} - /// Checks that the hardware meets the requirements and print a warning otherwise. fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) { // Polkadot para-chains should generally use these requirements to ensure that the relay-chain