From c03cb1fc5d59a864f25bfcaedb435c74eef500c0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 3 Sep 2024 17:09:03 +0300 Subject: [PATCH 01/10] Split NodeSpec --- .../src/common/command.rs | 4 ++-- .../polkadot-parachain-lib/src/common/mod.rs | 18 ++++++++++---- .../polkadot-parachain-lib/src/common/spec.rs | 24 ++++++++++--------- .../polkadot-parachain-lib/src/service.rs | 23 ++++++++++++++---- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/command.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/command.rs index e2826826d40e..a60fc9232d91 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/command.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/command.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use crate::common::spec::NodeSpec; +use crate::common::spec::BaseNodeSpec; use cumulus_client_cli::ExportGenesisHeadCommand; use frame_benchmarking_cli::BlockCmd; #[cfg(any(feature = "runtime-benchmarks"))] @@ -81,7 +81,7 @@ pub trait NodeCommandRunner { impl NodeCommandRunner for T where - T: NodeSpec, + T: BaseNodeSpec, { fn prepare_check_block_cmd( self: Box, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs index 907f09263fc1..e7c2e12b9ef5 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs @@ -36,21 +36,31 @@ use sp_runtime::{ }; use sp_session::SessionKeys; use sp_transaction_pool::runtime_api::TaggedTransactionQueue; -use std::{fmt::Debug, path::PathBuf, str::FromStr}; +use std::{ + fmt::Debug, + panic::{RefUnwindSafe, UnwindSafe}, + path::PathBuf, + str::FromStr, +}; pub trait NodeBlock: BlockT + for<'de> serde::Deserialize<'de> + + UnwindSafe + + RefUnwindSafe { type BoundedFromStrErr: Debug; type BoundedNumber: FromStr + BlockNumber; - type BoundedHeader: HeaderT + Unpin; + type BoundedHeader: HeaderT + Unpin + UnwindSafe + RefUnwindSafe; } impl NodeBlock for T where - T: BlockT + for<'de> serde::Deserialize<'de>, - ::Header: Unpin, + T: BlockT + + for<'de> serde::Deserialize<'de> + + UnwindSafe + + RefUnwindSafe, + ::Header: Unpin + UnwindSafe + RefUnwindSafe, as FromStr>::Err: Debug, { type BoundedFromStrErr = as FromStr>::Err; diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs index 8e19cf304b07..6cbbd2e99240 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs @@ -89,7 +89,7 @@ fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) { } } -pub(crate) trait NodeSpec { +pub(crate) trait BaseNodeSpec { type Block: NodeBlock; type RuntimeApi: ConstructNodeRuntimeApi< @@ -99,16 +99,6 @@ pub(crate) trait NodeSpec { type BuildImportQueue: BuildImportQueue; - type BuildRpcExtensions: BuildRpcExtensions< - ParachainClient, - ParachainBackend, - FullPool>, - >; - - type StartConsensus: StartConsensus; - - 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 @@ -185,6 +175,18 @@ pub(crate) trait NodeSpec { other: (block_import, telemetry, telemetry_worker_handle), }) } +} + +pub(crate) trait NodeSpec: BaseNodeSpec { + type BuildRpcExtensions: BuildRpcExtensions< + ParachainClient, + ParachainBackend, + FullPool>, + >; + + type StartConsensus: StartConsensus; + + const SYBIL_RESISTANCE: CollatorSybilResistance; /// Start a node with the given parachain spec. /// diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs index 303ec1e3b298..075d357f4296 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs @@ -18,7 +18,7 @@ use crate::{ common::{ aura::{AuraIdT, AuraRuntimeApi}, rpc::{BuildEmptyRpcExtensions, BuildParachainRpcExtensions}, - spec::{BuildImportQueue, DynNodeSpec, NodeSpec, StartConsensus}, + spec::{BaseNodeSpec, BuildImportQueue, DynNodeSpec, NodeSpec, StartConsensus}, types::{ AccountId, Balance, Block, Hash, Nonce, ParachainBackend, ParachainBlockImport, ParachainClient, @@ -87,10 +87,13 @@ impl BuildImportQueue, FakeRuntimeApi> for BuildShellImportQueue { pub(crate) struct ShellNode; -impl NodeSpec for ShellNode { +impl BaseNodeSpec for ShellNode { type Block = Block; type RuntimeApi = FakeRuntimeApi; type BuildImportQueue = BuildShellImportQueue; +} + +impl NodeSpec for ShellNode { type BuildRpcExtensions = BuildEmptyRpcExtensions, Self::RuntimeApi>; type StartConsensus = StartRelayChainConsensus; @@ -205,7 +208,7 @@ impl Default } } -impl NodeSpec +impl BaseNodeSpec for AuraNode where Block: NodeBlock, @@ -214,11 +217,23 @@ where + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + substrate_frame_rpc_system::AccountNonceApi, AuraId: AuraIdT + Sync, - StartConsensus: self::StartConsensus + 'static, { type Block = Block; type RuntimeApi = RuntimeApi; type BuildImportQueue = BuildRelayToAuraImportQueue; +} + +impl NodeSpec + for AuraNode +where + Block: NodeBlock, + RuntimeApi: ConstructNodeRuntimeApi>, + RuntimeApi::RuntimeApi: AuraRuntimeApi + + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + substrate_frame_rpc_system::AccountNonceApi, + AuraId: AuraIdT + Sync, + StartConsensus: self::StartConsensus + 'static, +{ type BuildRpcExtensions = BuildParachainRpcExtensions; type StartConsensus = StartConsensus; const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant; From c9b346953dab412d6ca52ef1736f0ca2c4d2b24d Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 3 Sep 2024 17:31:22 +0300 Subject: [PATCH 02/10] Split service.rs --- .../polkadot-parachain-lib/src/command.rs | 6 +- .../polkadot-parachain-lib/src/lib.rs | 2 +- .../src/{service.rs => nodes/aura.rs} | 132 +-------------- .../polkadot-parachain-lib/src/nodes/mod.rs | 18 +++ .../polkadot-parachain-lib/src/nodes/shell.rs | 152 ++++++++++++++++++ 5 files changed, 181 insertions(+), 129 deletions(-) rename cumulus/polkadot-parachain/polkadot-parachain-lib/src/{service.rs => nodes/aura.rs} (77%) create mode 100644 cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs create mode 100644 cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/shell.rs diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs index 320511ece5e5..d015b0b9b3bf 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs @@ -27,8 +27,8 @@ use crate::{ NodeBlock, NodeExtraArgs, }, fake_runtime_api, + nodes::shell::ShellNode, runtime::BlockNumber, - service::ShellNode, }; #[cfg(feature = "runtime-benchmarks")] use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions; @@ -59,12 +59,12 @@ where Block::BoundedHeader: UnwindSafe + RefUnwindSafe, { match aura_id { - AuraConsensusId::Sr25519 => crate::service::new_aura_node_spec::< + AuraConsensusId::Sr25519 => crate::nodes::aura::new_aura_node_spec::< Block, fake_runtime_api::aura_sr25519::RuntimeApi, sp_consensus_aura::sr25519::AuthorityId, >(extra_args), - AuraConsensusId::Ed25519 => crate::service::new_aura_node_spec::< + AuraConsensusId::Ed25519 => crate::nodes::aura::new_aura_node_spec::< Block, fake_runtime_api::aura_ed25519::RuntimeApi, sp_consensus_aura::ed25519::AuthorityId, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/lib.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/lib.rs index 6aa2f656a48b..a293ab225c6f 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/lib.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/lib.rs @@ -45,7 +45,7 @@ mod cli; mod command; mod common; mod fake_runtime_api; -mod service; +mod nodes; pub use cli::CliConfig; pub use command::{run, RunConfig}; diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs similarity index 77% rename from cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs rename to cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs index 075d357f4296..86a04f127c28 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs @@ -14,18 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use crate::{ - common::{ - aura::{AuraIdT, AuraRuntimeApi}, - rpc::{BuildEmptyRpcExtensions, BuildParachainRpcExtensions}, - spec::{BaseNodeSpec, BuildImportQueue, DynNodeSpec, NodeSpec, StartConsensus}, - types::{ - AccountId, Balance, Block, Hash, Nonce, ParachainBackend, ParachainBlockImport, - ParachainClient, - }, - ConstructNodeRuntimeApi, NodeBlock, NodeExtraArgs, +use crate::common::{ + aura::{AuraIdT, AuraRuntimeApi}, + rpc::BuildParachainRpcExtensions, + spec::{BaseNodeSpec, BuildImportQueue, DynNodeSpec, NodeSpec, StartConsensus}, + types::{ + AccountId, Balance, Hash, Nonce, ParachainBackend, ParachainBlockImport, ParachainClient, }, - fake_runtime_api::aura_sr25519::RuntimeApi as FakeRuntimeApi, + ConstructNodeRuntimeApi, NodeBlock, NodeExtraArgs, }; use cumulus_client_collator::service::{ CollatorService, ServiceInterface as CollatorServiceInterface, @@ -38,7 +34,6 @@ use cumulus_client_consensus_aura::collators::slot_based::{ use cumulus_client_consensus_proposer::{Proposer, ProposerInterface}; use cumulus_client_consensus_relay_chain::Verifier as RelayChainVerifier; #[allow(deprecated)] -use cumulus_client_service::old_consensus; use cumulus_client_service::CollatorSybilResistance; use cumulus_primitives_core::{relay_chain::ValidationCode, ParaId}; use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; @@ -63,43 +58,6 @@ use sp_runtime::{ }; use std::{marker::PhantomData, sync::Arc, time::Duration}; -/// Build the import queue for the shell runtime. -pub(crate) struct BuildShellImportQueue; - -impl BuildImportQueue, FakeRuntimeApi> for BuildShellImportQueue { - fn build_import_queue( - client: Arc, FakeRuntimeApi>>, - block_import: ParachainBlockImport, FakeRuntimeApi>, - 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) - } -} - -pub(crate) struct ShellNode; - -impl BaseNodeSpec for ShellNode { - type Block = Block; - type RuntimeApi = FakeRuntimeApi; - type BuildImportQueue = BuildShellImportQueue; -} - -impl NodeSpec for ShellNode { - type BuildRpcExtensions = BuildEmptyRpcExtensions, Self::RuntimeApi>; - type StartConsensus = StartRelayChainConsensus; - - const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Unresistant; -} - struct Verifier { client: Arc, aura_verifier: Box>, @@ -267,82 +225,6 @@ where } } -/// 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; - -impl StartConsensus, FakeRuntimeApi> for StartRelayChainConsensus { - fn start_consensus( - client: Arc, FakeRuntimeApi>>, - block_import: ParachainBlockImport, FakeRuntimeApi>, - prometheus_registry: Option<&Registry>, - telemetry: Option, - task_manager: &TaskManager, - relay_chain_interface: Arc, - transaction_pool: Arc, ParachainClient, FakeRuntimeApi>>>, - _keystore: KeystorePtr, - _relay_chain_slot_duration: Duration, - para_id: ParaId, - collator_key: CollatorPair, - overseer_handle: OverseerHandle, - announce_block: Arc>) + Send + Sync>, - _backend: Arc>>, - _node_extra_args: NodeExtraArgs, - ) -> 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 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. pub(crate) struct StartSlotBasedAuraConsensus( PhantomData<(Block, RuntimeApi, AuraId)>, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs new file mode 100644 index 000000000000..23654df6f9b2 --- /dev/null +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs @@ -0,0 +1,18 @@ +// 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 . + +pub mod aura; +pub mod shell; diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/shell.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/shell.rs new file mode 100644 index 000000000000..5f9c671d7107 --- /dev/null +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/shell.rs @@ -0,0 +1,152 @@ +// 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 . + +use crate::{ + common::{ + rpc::BuildEmptyRpcExtensions, + spec::{BaseNodeSpec, BuildImportQueue, NodeSpec, StartConsensus}, + types::{Block, Hash, ParachainBackend, ParachainBlockImport, ParachainClient}, + NodeExtraArgs, + }, + fake_runtime_api::aura_sr25519::RuntimeApi as FakeRuntimeApi, +}; +#[docify::export(slot_based_colator_import)] +#[allow(deprecated)] +use cumulus_client_service::old_consensus; +use cumulus_client_service::CollatorSybilResistance; +use cumulus_primitives_core::ParaId; +use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; +use polkadot_primitives::CollatorPair; +use prometheus_endpoint::Registry; +use sc_consensus::DefaultImportQueue; +use sc_service::{Configuration, Error, TaskManager}; +use sc_telemetry::TelemetryHandle; +use sc_transaction_pool::FullPool; +use sp_keystore::KeystorePtr; +use std::{sync::Arc, time::Duration}; + +/// Build the import queue for the shell runtime. +pub(crate) struct BuildShellImportQueue; + +impl BuildImportQueue, FakeRuntimeApi> for BuildShellImportQueue { + fn build_import_queue( + client: Arc, FakeRuntimeApi>>, + block_import: ParachainBlockImport, FakeRuntimeApi>, + 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) + } +} + +/// 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; + +impl StartConsensus, FakeRuntimeApi> for StartRelayChainConsensus { + fn start_consensus( + client: Arc, FakeRuntimeApi>>, + block_import: ParachainBlockImport, FakeRuntimeApi>, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, + relay_chain_interface: Arc, + transaction_pool: Arc, ParachainClient, FakeRuntimeApi>>>, + _keystore: KeystorePtr, + _relay_chain_slot_duration: Duration, + para_id: ParaId, + collator_key: CollatorPair, + overseer_handle: OverseerHandle, + announce_block: Arc>) + Send + Sync>, + _backend: Arc>>, + _node_extra_args: NodeExtraArgs, + ) -> 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 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(()) + } +} + +pub(crate) struct ShellNode; + +impl BaseNodeSpec for ShellNode { + type Block = Block; + type RuntimeApi = FakeRuntimeApi; + type BuildImportQueue = BuildShellImportQueue; +} + +impl NodeSpec for ShellNode { + type BuildRpcExtensions = BuildEmptyRpcExtensions, Self::RuntimeApi>; + type StartConsensus = StartRelayChainConsensus; + + const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Unresistant; +} From 0c8a9949489f542d8b28146fb61e96f2feca2529 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 3 Sep 2024 17:35:32 +0300 Subject: [PATCH 03/10] Add manual seal node --- Cargo.lock | 2 + .../polkadot-parachain-lib/Cargo.toml | 2 + .../polkadot-parachain-lib/src/cli.rs | 6 + .../polkadot-parachain-lib/src/command.rs | 49 ++-- .../polkadot-parachain-lib/src/nodes/aura.rs | 20 +- .../src/nodes/manual_seal.rs | 223 ++++++++++++++++++ .../polkadot-parachain-lib/src/nodes/mod.rs | 34 +++ .../src/guides/enable_elastic_scaling_mvp.rs | 4 +- 8 files changed, 311 insertions(+), 29 deletions(-) create mode 100644 cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs diff --git a/Cargo.lock b/Cargo.lock index 83c40e9a4c7a..4c72709e777c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14060,6 +14060,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "futures", + "futures-timer", "jsonrpsee", "log", "nix 0.28.0", @@ -14076,6 +14077,7 @@ dependencies = [ "sc-client-api", "sc-client-db", "sc-consensus", + "sc-consensus-manual-seal", "sc-executor", "sc-network", "sc-rpc", diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/Cargo.toml b/cumulus/polkadot-parachain/polkadot-parachain-lib/Cargo.toml index 066cbfae53ae..5e4c9fcf1a3d 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/Cargo.toml +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/Cargo.toml @@ -61,6 +61,7 @@ pallet-transaction-payment-rpc-runtime-api = { workspace = true, default-feature sp-inherents = { workspace = true, default-features = true } sp-api = { workspace = true, default-features = true } sp-consensus-aura = { workspace = true, default-features = true } +sc-consensus-manual-seal = { workspace = true, default-features = true } sc-sysinfo = { workspace = true, default-features = true } prometheus-endpoint = { workspace = true, default-features = true } substrate-frame-rpc-system = { workspace = true, default-features = true } @@ -83,6 +84,7 @@ cumulus-client-service = { workspace = true, default-features = true } cumulus-primitives-aura = { workspace = true, default-features = true } cumulus-primitives-core = { workspace = true, default-features = true } cumulus-relay-chain-interface = { workspace = true, default-features = true } +futures-timer = "3.0.3" [dev-dependencies] assert_cmd = { workspace = true } diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs index 349dc01d8a4f..77ecde736691 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs @@ -119,6 +119,12 @@ pub struct Cli { #[command(flatten)] pub run: cumulus_client_cli::RunCmd, + /// Use manual seal consensus. + /// + /// This works only with dev chains (e.g. asset-hub-rococo-dev). + #[arg(long)] + pub manual_seal: bool, + /// EXPERIMENTAL: Use slot-based collator which can handle elastic scaling. /// /// Use with care, this flag is unstable and subject to change. diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs index d015b0b9b3bf..e1c5c75337ab 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs @@ -22,12 +22,11 @@ use crate::{ AuraConsensusId, Consensus, Runtime, RuntimeResolver as RuntimeResolverT, RuntimeResolver, }, - spec::DynNodeSpec, types::Block, NodeBlock, NodeExtraArgs, }, fake_runtime_api, - nodes::shell::ShellNode, + nodes::{shell::ShellNode, DynNodeSpecExt}, runtime::BlockNumber, }; #[cfg(feature = "runtime-benchmarks")] @@ -39,7 +38,6 @@ use sc_cli::{Result, SubstrateCli}; use sp_runtime::traits::AccountIdConversion; #[cfg(feature = "runtime-benchmarks")] use sp_runtime::traits::HashingFor; -use std::panic::{RefUnwindSafe, UnwindSafe}; /// Structure that can be used in order to provide customizers for different functionalities of the /// node binary that is being built using this library. @@ -53,10 +51,9 @@ pub struct RunConfig { pub fn new_aura_node_spec( aura_id: AuraConsensusId, extra_args: &NodeExtraArgs, -) -> Box +) -> Box where - Block: NodeBlock + UnwindSafe + RefUnwindSafe, - Block::BoundedHeader: UnwindSafe + RefUnwindSafe, + Block: NodeBlock, { match aura_id { AuraConsensusId::Sr25519 => crate::nodes::aura::new_aura_node_spec::< @@ -76,7 +73,7 @@ fn new_node_spec( config: &sc_service::Configuration, runtime_resolver: &Box, extra_args: &NodeExtraArgs, -) -> std::result::Result, sc_cli::Error> { +) -> std::result::Result, sc_cli::Error> { let runtime = runtime_resolver.runtime(config.chain_spec.as_ref())?; Ok(match runtime { @@ -215,7 +212,24 @@ pub fn run(cmd_config: RunConfig) -> Result<() RelayChainCli::::new(runner.config(), cli.relay_chain_args.iter()); let collator_options = cli.run.collator_options(); + let is_dev_chain = runner.config().chain_spec.id().ends_with("-dev"); + if cli.manual_seal && !is_dev_chain { + return Err("Manual sealing can be turned on only for dev chains".into()); + } + runner.run_node_until_exit(|config| async move { + let node_spec = + new_node_spec(&config, &cmd_config.runtime_resolver, &cli.node_extra_args())?; + let para_id = ParaId::from( + Extensions::try_get(&*config.chain_spec) + .map(|e| e.para_id) + .ok_or("Could not find parachain extension in chain-spec.")?, + ); + + if cli.manual_seal { + return node_spec.start_manual_seal_node(config, para_id).map_err(Into::into) + } + // If Statemint (Statemine, Westmint, Rockmine) DB exists and we're using the // asset-hub chain spec, then rename the base path to the new chain ID. In the case // that both file paths exist, the node will exit, as the user must decide (by @@ -262,15 +276,9 @@ pub fn run(cmd_config: RunConfig) -> Result<() })) .flatten(); - let para_id = Extensions::try_get(&*config.chain_spec) - .map(|e| e.para_id) - .ok_or("Could not find parachain extension in chain-spec.")?; - - let id = ParaId::from(para_id); - let parachain_account = AccountIdConversion::::into_account_truncating( - &id, + ¶_id, ); let tokio_handle = config.tokio_handle.clone(); @@ -278,16 +286,16 @@ pub fn run(cmd_config: RunConfig) -> Result<() SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, tokio_handle) .map_err(|err| format!("Relay chain argument error: {}", err))?; - info!("🪪 Parachain id: {:?}", id); + info!("🪪 Parachain id: {:?}", para_id); info!("🧾 Parachain Account: {}", parachain_account); info!("✍️ Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); start_node( + node_spec, config, - &cmd_config.runtime_resolver, polkadot_config, collator_options, - id, + para_id, cli.node_extra_args(), hwbench, ) @@ -297,17 +305,20 @@ pub fn run(cmd_config: RunConfig) -> Result<() } } +/// This method is needed only for `#[sc_tracing::logging::prefix_logs_with("Parachain")]`. +/// +/// Adding this annotation to `DynNodeSpec::start_node()` doesn't work, probably because of the +/// `Pin>>` return type. #[sc_tracing::logging::prefix_logs_with("Parachain")] async fn start_node( + node_spec: Box, config: sc_service::Configuration, - runtime_resolver: &Box, polkadot_config: sc_service::Configuration, collator_options: cumulus_client_cli::CollatorOptions, id: ParaId, extra_args: NodeExtraArgs, hwbench: Option, ) -> Result { - let node_spec = new_node_spec(&config, runtime_resolver, &extra_args)?; node_spec .start_node(config, polkadot_config, collator_options, id, hwbench, extra_args) .await diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs index 86a04f127c28..533072c6cea5 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs @@ -14,14 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . -use crate::common::{ - aura::{AuraIdT, AuraRuntimeApi}, - rpc::BuildParachainRpcExtensions, - spec::{BaseNodeSpec, BuildImportQueue, DynNodeSpec, NodeSpec, StartConsensus}, - types::{ - AccountId, Balance, Hash, Nonce, ParachainBackend, ParachainBlockImport, ParachainClient, +use crate::{ + common::{ + aura::{AuraIdT, AuraRuntimeApi}, + rpc::BuildParachainRpcExtensions, + spec::{BaseNodeSpec, BuildImportQueue, NodeSpec, StartConsensus}, + types::{ + AccountId, Balance, Hash, Nonce, ParachainBackend, ParachainBlockImport, + ParachainClient, + }, + ConstructNodeRuntimeApi, NodeBlock, NodeExtraArgs, }, - ConstructNodeRuntimeApi, NodeBlock, NodeExtraArgs, + nodes::DynNodeSpecExt, }; use cumulus_client_collator::service::{ CollatorService, ServiceInterface as CollatorServiceInterface, @@ -199,7 +203,7 @@ where pub fn new_aura_node_spec( extra_args: &NodeExtraArgs, -) -> Box +) -> Box where Block: NodeBlock, RuntimeApi: ConstructNodeRuntimeApi>, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs new file mode 100644 index 000000000000..de7f96c75af5 --- /dev/null +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs @@ -0,0 +1,223 @@ +// 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 . + +use crate::common::{ + rpc::BuildRpcExtensions as BuildRpcExtensionsT, + spec::{BaseNodeSpec, BuildImportQueue, NodeSpec as NodeSpecT}, + types::{Hash, ParachainBlockImport, ParachainClient}, + ConstructNodeRuntimeApi, NodeBlock, +}; +use codec::Encode; +use cumulus_client_parachain_inherent::{MockValidationDataInherentDataProvider, MockXcmConfig}; +use cumulus_primitives_core::ParaId; +use sc_consensus::{DefaultImportQueue, LongestChain}; +use sc_consensus_manual_seal::rpc::{ManualSeal, ManualSealApiServer}; +use sc_network::NetworkBackend; +use sc_service::{Configuration, PartialComponents, TaskManager}; +use sc_telemetry::TelemetryHandle; +use sp_runtime::traits::Header; +use sp_timestamp::Timestamp; +use std::{marker::PhantomData, sync::Arc}; + +/// Build the import queue for a manual seal node. +pub struct BuildManualSealImportQueue(PhantomData<(Block, RuntimeApi)>); + +impl< + Block: NodeBlock, + RuntimeApi: ConstructNodeRuntimeApi>, + > BuildImportQueue for BuildManualSealImportQueue +{ + fn build_import_queue( + client: Arc>, + _block_import: ParachainBlockImport, + config: &Configuration, + _telemetry_handle: Option, + task_manager: &TaskManager, + ) -> sc_service::error::Result> { + Ok(sc_consensus_manual_seal::import_queue( + Box::new(client.clone()), + &task_manager.spawn_essential_handle(), + config.prometheus_registry(), + )) + } +} + +pub struct ManualSealNode(PhantomData); + +impl BaseNodeSpec for ManualSealNode { + type Block = NodeSpec::Block; + type RuntimeApi = NodeSpec::RuntimeApi; + type BuildImportQueue = BuildManualSealImportQueue; +} + +impl ManualSealNode { + pub fn new() -> Self { + Self(Default::default()) + } + + pub fn start_node( + &self, + config: Configuration, + para_id: ParaId, + ) -> sc_service::error::Result + where + Net: NetworkBackend, + { + let PartialComponents { + client, + backend, + mut task_manager, + import_queue, + keystore_container, + select_chain: _, + transaction_pool, + other: (_, mut telemetry, _), + } = Self::new_partial(&config)?; + let select_chain = LongestChain::new(backend.clone()); + + let net_config = sc_network::config::FullNetworkConfiguration::<_, _, Net>::new( + &config.network, + config.prometheus_config.as_ref().map(|cfg| cfg.registry.clone()), + ); + let metrics = Net::register_notification_metrics( + config.prometheus_config.as_ref().map(|cfg| &cfg.registry), + ); + + let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + net_config, + block_announce_validator_builder: None, + warp_sync_config: None, + block_relay: None, + metrics, + })?; + + let proposer = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + None, + None, + ); + + let (manual_seal_sink, manual_seal_stream) = futures::channel::mpsc::channel(1024); + let mut manual_seal_sink_clone = manual_seal_sink.clone(); + task_manager.spawn_handle().spawn("block_authoring", None, async move { + loop { + futures_timer::Delay::new(std::time::Duration::from_millis(6000)).await; + manual_seal_sink_clone + .try_send(sc_consensus_manual_seal::EngineCommand::SealNewBlock { + create_empty: true, + finalize: true, + parent_hash: None, + sender: None, + }) + .unwrap(); + } + }); + + let client_for_cidp = client.clone(); + let params = sc_consensus_manual_seal::ManualSealParams { + block_import: client.clone(), + env: proposer, + client: client.clone(), + pool: transaction_pool.clone(), + select_chain, + commands_stream: Box::pin(manual_seal_stream), + consensus_data_provider: None, + create_inherent_data_providers: move |block: Hash, ()| { + let current_para_head = client_for_cidp + .header(block) + .expect("Header lookup should succeed") + .expect("Header passed in as parent should be present in backend."); + let current_para_block_head = + Some(polkadot_primitives::HeadData(current_para_head.encode())); + let client_for_xcm = client_for_cidp.clone(); + async move { + use sp_runtime::traits::UniqueSaturatedInto; + + let mocked_parachain = MockValidationDataInherentDataProvider { + // When using manual seal we start from block 0, and it's very unlikely to + // reach a block number > u32::MAX. + current_para_block: UniqueSaturatedInto::::unique_saturated_into( + *current_para_head.number(), + ), + para_id, + current_para_block_head, + relay_offset: 1000, + relay_blocks_per_para_block: 1, + para_blocks_per_relay_epoch: 10, + relay_randomness_config: (), + xcm_config: MockXcmConfig::new(&*client_for_xcm, block, Default::default()), + raw_downward_messages: vec![], + raw_horizontal_messages: vec![], + additional_key_values: None, + }; + Ok(( + sp_timestamp::InherentDataProvider::new(Timestamp::new(0)), + mocked_parachain, + )) + } + }, + }; + let authorship_future = sc_consensus_manual_seal::run_manual_seal(params); + task_manager.spawn_essential_handle().spawn_blocking( + "manual-seal", + None, + authorship_future, + ); + let rpc_extensions_builder = { + let client = client.clone(); + let transaction_pool = transaction_pool.clone(); + let backend_for_rpc = backend.clone(); + + Box::new(move |_| { + let mut module = NodeSpec::BuildRpcExtensions::build_rpc_extensions( + client.clone(), + backend_for_rpc.clone(), + transaction_pool.clone(), + )?; + module + .merge(ManualSeal::new(manual_seal_sink.clone()).into_rpc()) + .map_err(|e| sc_service::Error::Application(e.into()))?; + Ok(module) + }) + }; + + let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + network, + client: client.clone(), + keystore: keystore_container.keystore(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + rpc_builder: rpc_extensions_builder, + backend, + system_rpc_tx, + tx_handler_controller, + sync_service, + config, + telemetry: telemetry.as_mut(), + })?; + + start_network.start_network(); + Ok(task_manager) + } +} diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs index 23654df6f9b2..7601805420e4 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs @@ -15,4 +15,38 @@ // along with Cumulus. If not, see . pub mod aura; +mod manual_seal; pub mod shell; + +use crate::common::spec::{DynNodeSpec, NodeSpec as NodeSpecT}; +use cumulus_primitives_core::ParaId; +use manual_seal::ManualSealNode; +use sc_service::{Configuration, TaskManager}; + +pub trait DynNodeSpecExt: DynNodeSpec { + fn start_manual_seal_node( + &self, + config: Configuration, + para_id: ParaId, + ) -> sc_service::error::Result; +} + +impl DynNodeSpecExt for T +where + T: NodeSpecT + DynNodeSpec, +{ + #[sc_tracing::logging::prefix_logs_with("Parachain")] + fn start_manual_seal_node( + &self, + config: Configuration, + para_id: ParaId, + ) -> sc_service::error::Result { + let node = ManualSealNode::::new(); + match config.network.network_backend { + sc_network::config::NetworkBackendType::Libp2p => + node.start_node::>(config, para_id), + sc_network::config::NetworkBackendType::Litep2p => + node.start_node::(config, para_id), + } + } +} diff --git a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs b/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs index 38ef18b88e0d..14a0b6107966 100644 --- a/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs +++ b/docs/sdk/src/guides/enable_elastic_scaling_mvp.rs @@ -85,7 +85,7 @@ //! This phase consists of plugging in the new slot-based collator. //! //! 1. In `node/src/service.rs` import the slot based collator instead of the lookahead collator. -#![doc = docify::embed!("../../cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs", slot_based_colator_import)] +#![doc = docify::embed!("../../cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs", slot_based_colator_import)] //! //! 2. In `start_consensus()` //! - Remove the `overseer_handle` param (also remove the @@ -94,7 +94,7 @@ //! `slot_drift` field with a value of `Duration::from_secs(1)`. //! - Replace the single future returned by `aura::run` with the two futures returned by it and //! spawn them as separate tasks: -#![doc = docify::embed!("../../cumulus/polkadot-parachain/polkadot-parachain-lib/src/service.rs", launch_slot_based_collator)] +#![doc = docify::embed!("../../cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/aura.rs", launch_slot_based_collator)] //! //! 3. In `start_parachain_node()` remove the `overseer_handle` param passed to `start_consensus`. //! From 097aa4bbbd8c4939e55308134ec2bf152e056771 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 5 Sep 2024 12:23:52 +0300 Subject: [PATCH 04/10] manual_seal -> dev_block_time --- .../polkadot-parachain/polkadot-parachain-lib/src/cli.rs | 4 ++-- .../polkadot-parachain-lib/src/command.rs | 8 +++++--- .../polkadot-parachain-lib/src/nodes/manual_seal.rs | 3 ++- .../polkadot-parachain-lib/src/nodes/mod.rs | 6 ++++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs index 77ecde736691..8a22d390c8d7 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs @@ -119,11 +119,11 @@ pub struct Cli { #[command(flatten)] pub run: cumulus_client_cli::RunCmd, - /// Use manual seal consensus. + /// Dev option for producing a block each `dev_block_time` ms. /// /// This works only with dev chains (e.g. asset-hub-rococo-dev). #[arg(long)] - pub manual_seal: bool, + pub dev_block_time: Option, /// EXPERIMENTAL: Use slot-based collator which can handle elastic scaling. /// diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs index e1c5c75337ab..3cd8779bd318 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs @@ -213,7 +213,7 @@ pub fn run(cmd_config: RunConfig) -> Result<() let collator_options = cli.run.collator_options(); let is_dev_chain = runner.config().chain_spec.id().ends_with("-dev"); - if cli.manual_seal && !is_dev_chain { + if cli.dev_block_time.is_some() && !is_dev_chain { return Err("Manual sealing can be turned on only for dev chains".into()); } @@ -226,8 +226,10 @@ pub fn run(cmd_config: RunConfig) -> Result<() .ok_or("Could not find parachain extension in chain-spec.")?, ); - if cli.manual_seal { - return node_spec.start_manual_seal_node(config, para_id).map_err(Into::into) + if let Some(dev_block_time) = cli.dev_block_time { + return node_spec + .start_manual_seal_node(config, para_id, dev_block_time) + .map_err(Into::into) } // If Statemint (Statemine, Westmint, Rockmine) DB exists and we're using the diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs index de7f96c75af5..5eba5e667085 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs @@ -72,6 +72,7 @@ impl ManualSealNode { &self, config: Configuration, para_id: ParaId, + block_time: u64, ) -> sc_service::error::Result where Net: NetworkBackend, @@ -122,7 +123,7 @@ impl ManualSealNode { let mut manual_seal_sink_clone = manual_seal_sink.clone(); task_manager.spawn_handle().spawn("block_authoring", None, async move { loop { - futures_timer::Delay::new(std::time::Duration::from_millis(6000)).await; + futures_timer::Delay::new(std::time::Duration::from_millis(block_time)).await; manual_seal_sink_clone .try_send(sc_consensus_manual_seal::EngineCommand::SealNewBlock { create_empty: true, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs index 7601805420e4..e6995d4925dc 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs @@ -28,6 +28,7 @@ pub trait DynNodeSpecExt: DynNodeSpec { &self, config: Configuration, para_id: ParaId, + block_time: u64, ) -> sc_service::error::Result; } @@ -40,13 +41,14 @@ where &self, config: Configuration, para_id: ParaId, + block_time: u64, ) -> sc_service::error::Result { let node = ManualSealNode::::new(); match config.network.network_backend { sc_network::config::NetworkBackendType::Libp2p => - node.start_node::>(config, para_id), + node.start_node::>(config, para_id, block_time), sc_network::config::NetworkBackendType::Litep2p => - node.start_node::(config, para_id), + node.start_node::(config, para_id, block_time), } } } From d94e75e9d7c5b11b486b04d48427514dc85d568a Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 5 Sep 2024 15:14:50 +0300 Subject: [PATCH 05/10] Remove check --- .../polkadot-parachain/polkadot-parachain-lib/src/command.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs index 3cd8779bd318..63a76b29d2a4 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs @@ -212,11 +212,6 @@ pub fn run(cmd_config: RunConfig) -> Result<() RelayChainCli::::new(runner.config(), cli.relay_chain_args.iter()); let collator_options = cli.run.collator_options(); - let is_dev_chain = runner.config().chain_spec.id().ends_with("-dev"); - if cli.dev_block_time.is_some() && !is_dev_chain { - return Err("Manual sealing can be turned on only for dev chains".into()); - } - runner.run_node_until_exit(|config| async move { let node_spec = new_node_spec(&config, &cmd_config.runtime_resolver, &cli.node_extra_args())?; From 755af4a8eedf0f31c09a3d5dc4c4a6fd8ebee8a4 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 20 Sep 2024 09:21:46 +0300 Subject: [PATCH 06/10] Address code review comments --- .../polkadot-parachain-lib/src/cli.rs | 2 - .../polkadot-parachain-lib/src/command.rs | 41 +-- .../polkadot-parachain-lib/src/common/mod.rs | 5 +- .../polkadot-parachain-lib/src/common/spec.rs | 271 +++++++++--------- 4 files changed, 153 insertions(+), 166 deletions(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs index 8a22d390c8d7..51f7f8178908 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs @@ -120,8 +120,6 @@ pub struct Cli { pub run: cumulus_client_cli::RunCmd, /// Dev option for producing a block each `dev_block_time` ms. - /// - /// This works only with dev chains (e.g. asset-hub-rococo-dev). #[arg(long)] pub dev_block_time: Option, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs index 63a76b29d2a4..acb7dcea719f 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/command.rs @@ -287,37 +287,18 @@ pub fn run(cmd_config: RunConfig) -> Result<() info!("🧾 Parachain Account: {}", parachain_account); info!("✍️ Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); - start_node( - node_spec, - config, - polkadot_config, - collator_options, - para_id, - cli.node_extra_args(), - hwbench, - ) - .await + node_spec + .start_node( + config, + polkadot_config, + collator_options, + para_id, + hwbench, + cli.node_extra_args(), + ) + .await + .map_err(Into::into) }) }, } } - -/// This method is needed only for `#[sc_tracing::logging::prefix_logs_with("Parachain")]`. -/// -/// Adding this annotation to `DynNodeSpec::start_node()` doesn't work, probably because of the -/// `Pin>>` return type. -#[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_node( - node_spec: Box, - config: sc_service::Configuration, - polkadot_config: sc_service::Configuration, - collator_options: cumulus_client_cli::CollatorOptions, - id: ParaId, - extra_args: NodeExtraArgs, - hwbench: Option, -) -> Result { - node_spec - .start_node(config, polkadot_config, collator_options, id, hwbench, extra_args) - .await - .map_err(Into::into) -} diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs index e7c2e12b9ef5..8a338ad0369a 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs @@ -28,6 +28,7 @@ pub mod types; use cumulus_primitives_core::CollectCollationInfo; use sc_client_db::DbHash; +use serde::de::DeserializeOwned; use sp_api::{ApiExt, CallApiAt, ConstructRuntimeApi, Metadata}; use sp_block_builder::BlockBuilder; use sp_runtime::{ @@ -45,7 +46,7 @@ use std::{ pub trait NodeBlock: BlockT - + for<'de> serde::Deserialize<'de> + + DeserializeOwned + UnwindSafe + RefUnwindSafe { @@ -57,7 +58,7 @@ pub trait NodeBlock: impl NodeBlock for T where T: BlockT - + for<'de> serde::Deserialize<'de> + + DeserializeOwned + UnwindSafe + RefUnwindSafe, ::Header: Unpin + UnwindSafe + RefUnwindSafe, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs index 6cbbd2e99240..5c662ad78a3c 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/spec.rs @@ -39,6 +39,7 @@ use sc_network::{config::FullNetworkConfiguration, NetworkBackend, NetworkBlock} use sc_service::{Configuration, ImportQueue, PartialComponents, TaskManager}; use sc_sysinfo::HwBench; use sc_telemetry::{TelemetryHandle, TelemetryWorker}; +use sc_tracing::tracing::Instrument; use sc_transaction_pool::FullPool; use sp_keystore::KeystorePtr; use std::{future::Future, pin::Pin, sync::Arc, time::Duration}; @@ -202,147 +203,153 @@ pub(crate) trait NodeSpec: BaseNodeSpec { 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, - prometheus_registry.clone(), - ); - - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = - build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - net_config, + 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, + prometheus_registry.clone(), + ); + + 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 |_| { + Self::BuildRpcExtensions::build_rpc_extensions( + 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, - 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 |_| { - Self::BuildRpcExtensions::build_rpc_extensions( - 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); + 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, + })?; + if validator { - warn_if_slow_hardware(&hwbench); + 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, + 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(), + node_extra_args, + )?; } - 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), - ); - } - } + start_network.start_network(); - 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, - })?; - - 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, - 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(), - node_extra_args, - )?; + Ok(task_manager) } - - start_network.start_network(); - - Ok(task_manager) - }) + .instrument(sc_tracing::tracing::info_span!( + sc_tracing::logging::PREFIX_LOG_SPAN, + name = "Parachain", + )), + ) } } From f7bfff83880e8dc5700dd2cb8820f3ea53fec656 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 20 Sep 2024 10:31:23 +0300 Subject: [PATCH 07/10] Fix merge change --- .../src/nodes/manual_seal.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs index 5eba5e667085..f0936743a9ec 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs @@ -26,7 +26,7 @@ use cumulus_primitives_core::ParaId; use sc_consensus::{DefaultImportQueue, LongestChain}; use sc_consensus_manual_seal::rpc::{ManualSeal, ManualSealApiServer}; use sc_network::NetworkBackend; -use sc_service::{Configuration, PartialComponents, TaskManager}; +use sc_service::{build_polkadot_syncing_strategy, Configuration, PartialComponents, TaskManager}; use sc_telemetry::TelemetryHandle; use sp_runtime::traits::Header; use sp_timestamp::Timestamp; @@ -89,7 +89,7 @@ impl ManualSealNode { } = Self::new_partial(&config)?; let select_chain = LongestChain::new(backend.clone()); - let net_config = sc_network::config::FullNetworkConfiguration::<_, _, Net>::new( + let mut net_config = sc_network::config::FullNetworkConfiguration::<_, _, Net>::new( &config.network, config.prometheus_config.as_ref().map(|cfg| cfg.registry.clone()), ); @@ -97,6 +97,16 @@ impl ManualSealNode { config.prometheus_config.as_ref().map(|cfg| &cfg.registry), ); + let syncing_strategy = build_polkadot_syncing_strategy( + config.protocol_id(), + config.chain_spec.fork_id(), + &mut net_config, + None, + client.clone(), + &task_manager.spawn_handle(), + config.prometheus_config.as_ref().map(|config| &config.registry), + )?; + let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -106,7 +116,7 @@ impl ManualSealNode { import_queue, net_config, block_announce_validator_builder: None, - warp_sync_config: None, + syncing_strategy, block_relay: None, metrics, })?; From b5da3b85c1ac6bc5cd40f41ba913085b6dc06e47 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 26 Sep 2024 15:31:35 +0300 Subject: [PATCH 08/10] Address code review comments --- .../src/nodes/manual_seal.rs | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs index f0936743a9ec..d00d7adf27e1 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/manual_seal.rs @@ -18,7 +18,6 @@ use crate::common::{ rpc::BuildRpcExtensions as BuildRpcExtensionsT, spec::{BaseNodeSpec, BuildImportQueue, NodeSpec as NodeSpecT}, types::{Hash, ParachainBlockImport, ParachainClient}, - ConstructNodeRuntimeApi, NodeBlock, }; use codec::Encode; use cumulus_client_parachain_inherent::{MockValidationDataInherentDataProvider, MockXcmConfig}; @@ -32,21 +31,18 @@ use sp_runtime::traits::Header; use sp_timestamp::Timestamp; use std::{marker::PhantomData, sync::Arc}; -/// Build the import queue for a manual seal node. -pub struct BuildManualSealImportQueue(PhantomData<(Block, RuntimeApi)>); +pub struct ManualSealNode(PhantomData); -impl< - Block: NodeBlock, - RuntimeApi: ConstructNodeRuntimeApi>, - > BuildImportQueue for BuildManualSealImportQueue +impl BuildImportQueue + for ManualSealNode { fn build_import_queue( - client: Arc>, - _block_import: ParachainBlockImport, + client: Arc>, + _block_import: ParachainBlockImport, config: &Configuration, _telemetry_handle: Option, task_manager: &TaskManager, - ) -> sc_service::error::Result> { + ) -> sc_service::error::Result> { Ok(sc_consensus_manual_seal::import_queue( Box::new(client.clone()), &task_manager.spawn_essential_handle(), @@ -55,12 +51,10 @@ impl< } } -pub struct ManualSealNode(PhantomData); - impl BaseNodeSpec for ManualSealNode { type Block = NodeSpec::Block; type RuntimeApi = NodeSpec::RuntimeApi; - type BuildImportQueue = BuildManualSealImportQueue; + type BuildImportQueue = Self; } impl ManualSealNode { @@ -70,7 +64,7 @@ impl ManualSealNode { pub fn start_node( &self, - config: Configuration, + mut config: Configuration, para_id: ParaId, block_time: u64, ) -> sc_service::error::Result @@ -89,6 +83,9 @@ impl ManualSealNode { } = Self::new_partial(&config)?; let select_chain = LongestChain::new(backend.clone()); + // Since this is a dev node, prevent it from connecting to peers. + config.network.default_peers_set.in_peers = 0; + config.network.default_peers_set.out_peers = 0; let mut net_config = sc_network::config::FullNetworkConfiguration::<_, _, Net>::new( &config.network, config.prometheus_config.as_ref().map(|cfg| cfg.registry.clone()), @@ -131,19 +128,21 @@ impl ManualSealNode { let (manual_seal_sink, manual_seal_stream) = futures::channel::mpsc::channel(1024); let mut manual_seal_sink_clone = manual_seal_sink.clone(); - task_manager.spawn_handle().spawn("block_authoring", None, async move { - loop { - futures_timer::Delay::new(std::time::Duration::from_millis(block_time)).await; - manual_seal_sink_clone - .try_send(sc_consensus_manual_seal::EngineCommand::SealNewBlock { - create_empty: true, - finalize: true, - parent_hash: None, - sender: None, - }) - .unwrap(); - } - }); + task_manager + .spawn_essential_handle() + .spawn("block_authoring", None, async move { + loop { + futures_timer::Delay::new(std::time::Duration::from_millis(block_time)).await; + manual_seal_sink_clone + .try_send(sc_consensus_manual_seal::EngineCommand::SealNewBlock { + create_empty: true, + finalize: true, + parent_hash: None, + sender: None, + }) + .unwrap(); + } + }); let client_for_cidp = client.clone(); let params = sc_consensus_manual_seal::ManualSealParams { From 9468b4bcdea07c035a7aeb1870a080d7049ef48f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 27 Sep 2024 15:46:46 +0300 Subject: [PATCH 09/10] Remove UnwindSafe and RefUnwindSafe --- .../polkadot-parachain-lib/src/common/mod.rs | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs index 8010cffc9dbc..37660a5347a2 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/common/mod.rs @@ -37,31 +37,20 @@ use sp_runtime::{ }; use sp_session::SessionKeys; use sp_transaction_pool::runtime_api::TaggedTransactionQueue; -use std::{ - fmt::Debug, - panic::{RefUnwindSafe, UnwindSafe}, - path::PathBuf, - str::FromStr, -}; +use std::{fmt::Debug, path::PathBuf, str::FromStr}; pub trait NodeBlock: - BlockT - + DeserializeOwned - + UnwindSafe - + RefUnwindSafe + BlockT + DeserializeOwned { type BoundedFromStrErr: Debug; type BoundedNumber: FromStr + BlockNumber; - type BoundedHeader: HeaderT + Unpin + UnwindSafe + RefUnwindSafe; + type BoundedHeader: HeaderT + Unpin; } impl NodeBlock for T where - T: BlockT - + DeserializeOwned - + UnwindSafe - + RefUnwindSafe, - ::Header: Unpin + UnwindSafe + RefUnwindSafe, + T: BlockT + DeserializeOwned, + ::Header: Unpin, as FromStr>::Err: Debug, { type BoundedFromStrErr = as FromStr>::Err; From 99240e489bd8f4823f8c6310bdb674eae46c7dff Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 2 Oct 2024 10:42:16 +0300 Subject: [PATCH 10/10] Add comments --- .../polkadot-parachain/polkadot-parachain-lib/src/cli.rs | 6 +++++- .../polkadot-parachain-lib/src/nodes/mod.rs | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs index 51f7f8178908..6ca328912bba 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/cli.rs @@ -119,7 +119,11 @@ pub struct Cli { #[command(flatten)] pub run: cumulus_client_cli::RunCmd, - /// Dev option for producing a block each `dev_block_time` ms. + /// Start a dev node that produces a block each `dev_block_time` ms. + /// + /// This is a dev option, and it won't result in starting or connecting to a parachain network. + /// The resulting node will work on its own, running the wasm blob and artificially producing + /// a block each `dev_block_time` ms, as if it was part of a parachain. #[arg(long)] pub dev_block_time: Option, diff --git a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs index e6995d4925dc..36f54fa3d051 100644 --- a/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs +++ b/cumulus/polkadot-parachain/polkadot-parachain-lib/src/nodes/mod.rs @@ -23,6 +23,10 @@ use cumulus_primitives_core::ParaId; use manual_seal::ManualSealNode; use sc_service::{Configuration, TaskManager}; +/// Trait that extends the `DynNodeSpec` trait with manual seal related logic. +/// +/// We need it in order to be able to access both the `DynNodeSpec` and the manual seal logic +/// through dynamic dispatch. pub trait DynNodeSpecExt: DynNodeSpec { fn start_manual_seal_node( &self,