Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion cumulus/polkadot-omni-node/lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,23 @@ pub struct Cli<Config: CliConfig> {
///
/// The `--dev` flag sets the `dev_block_time` to a default value of 3000ms unless explicitly
/// provided.
#[arg(long)]
///
/// Cannot be used together with `--instant-seal`.
#[arg(long, conflicts_with = "instant_seal")]
pub dev_block_time: Option<u64>,

/// Start a dev node with instant seal.
///
/// This is a dev option that enables instant sealing, meaning blocks are produced
/// immediately when transactions are received, rather than at fixed intervals.
/// Using this option won't result in starting or connecting to a parachain network.
/// The resulting node will work on its own, running the wasm blob and producing blocks
/// instantly upon receiving transactions.
///
/// Cannot be used together with `--dev-block-time`.
#[arg(long, conflicts_with = "dev_block_time")]
pub instant_seal: bool,

/// DEPRECATED: This feature has been stabilized, pLease use `--authoring slot-based` instead.
///
/// Use slot-based collator which can handle elastic scaling.
Expand Down
12 changes: 9 additions & 3 deletions cumulus/polkadot-omni-node/lib/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
AuraConsensusId, Consensus, Runtime, RuntimeResolver as RuntimeResolverT,
RuntimeResolver,
},
spec::DynNodeSpec,
spec::{DevSealMode, DynNodeSpec},
types::Block,
NodeBlock, NodeExtraArgs,
},
Expand Down Expand Up @@ -303,16 +303,22 @@ where
let node_spec =
new_node_spec(&config, &cmd_config.runtime_resolver, &cli.node_extra_args())?;

if cli.instant_seal {
return node_spec
.start_dev_seal_node(config, DevSealMode::InstantSeal)
.map_err(Into::into);
}

if cli.run.base.is_dev()? {
let dev_block_time = cli.dev_block_time.unwrap_or(DEFAULT_DEV_BLOCK_TIME_MS);
return node_spec
.start_manual_seal_node(config, dev_block_time)
.start_dev_seal_node(config, DevSealMode::ManualSeal(dev_block_time))
.map_err(Into::into);
}

if let Some(dev_block_time) = cli.dev_block_time {
return node_spec
.start_manual_seal_node(config, dev_block_time)
.start_dev_seal_node(config, DevSealMode::ManualSeal(dev_block_time))
.map_err(Into::into);
}

Expand Down
28 changes: 19 additions & 9 deletions cumulus/polkadot-omni-node/lib/src/common/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ use sp_keystore::KeystorePtr;
use sp_runtime::traits::AccountIdConversion;
use std::{future::Future, pin::Pin, sync::Arc, time::Duration};

/// Mode for development sealing (non-consensus block production).
#[derive(Debug, Clone, Copy)]
pub enum DevSealMode {
/// Instant seal mode - produces blocks immediately upon receiving transactions.
InstantSeal,
/// Manual seal mode - produces blocks at fixed time intervals.
/// The u64 parameter represents the block time in milliseconds.
ManualSeal(u64),
}

pub(crate) trait BuildImportQueue<
Block: BlockT,
RuntimeApi,
Expand Down Expand Up @@ -300,11 +310,11 @@ pub(crate) trait NodeSpec: BaseNodeSpec {

const SYBIL_RESISTANCE: CollatorSybilResistance;

fn start_manual_seal_node(
fn start_dev_seal_node(
_config: Configuration,
_block_time: u64,
_mode: DevSealMode,
) -> sc_service::error::Result<TaskManager> {
Err(sc_service::Error::Other("Manual seal not supported for this node type".into()))
Err(sc_service::Error::Other("Dev seal not supported for this node type".into()))
}

/// Start a node with the given parachain spec.
Expand Down Expand Up @@ -557,11 +567,11 @@ pub(crate) trait NodeSpec: BaseNodeSpec {
}

pub(crate) trait DynNodeSpec: NodeCommandRunner {
/// Start node with manual-seal consensus.
fn start_manual_seal_node(
/// Start node with dev seal consensus.
fn start_dev_seal_node(
self: Box<Self>,
config: Configuration,
block_time: u64,
mode: DevSealMode,
) -> sc_service::error::Result<TaskManager>;

/// Start the node.
Expand All @@ -579,12 +589,12 @@ impl<T> DynNodeSpec for T
where
T: NodeSpec + NodeCommandRunner,
{
fn start_manual_seal_node(
fn start_dev_seal_node(
self: Box<Self>,
config: Configuration,
block_time: u64,
mode: DevSealMode,
) -> sc_service::error::Result<TaskManager> {
<Self as NodeSpec>::start_manual_seal_node(config, block_time)
<Self as NodeSpec>::start_dev_seal_node(config, mode)
}

fn start_node(
Expand Down
116 changes: 68 additions & 48 deletions cumulus/polkadot-omni-node/lib/src/nodes/aura.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use crate::{
aura::{AuraIdT, AuraRuntimeApi},
rpc::{BuildParachainRpcExtensions, BuildRpcExtensions},
spec::{
BaseNodeSpec, BuildImportQueue, ClientBlockImport, DynNodeSpec, InitBlockImport,
NodeSpec, StartConsensus,
BaseNodeSpec, BuildImportQueue, ClientBlockImport, DevSealMode, DynNodeSpec,
InitBlockImport, NodeSpec, StartConsensus,
},
types::{
AccountId, Balance, Hash, Nonce, ParachainBackend, ParachainBlockImport,
Expand Down Expand Up @@ -211,9 +211,9 @@ where
type StartConsensus = StartConsensus;
const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant;

fn start_manual_seal_node(
fn start_dev_seal_node(
mut config: Configuration,
block_time: u64,
mode: DevSealMode,
) -> sc_service::error::Result<TaskManager> {
let PartialComponents {
client,
Expand Down Expand Up @@ -277,24 +277,6 @@ where
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_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();
}
});

// Note: Changing slot durations are currently not supported
let slot_duration = sc_consensus_aura::slot_duration(&*client)
.expect("slot_duration is always present; qed.");
Expand All @@ -305,29 +287,67 @@ where

let para_id =
Self::parachain_id(&client, &config).ok_or("Failed to retrieve the parachain id")?;
let create_inherent_data_providers = Self::create_manual_seal_inherent_data_providers(
client.clone(),
para_id,
slot_duration,
);

let params = sc_consensus_manual_seal::ManualSealParams {
block_import: client.clone(),
env: proposer,
client: client.clone(),
pool: transaction_pool.clone(),
select_chain: LongestChain::new(backend.clone()),
commands_stream: Box::pin(manual_seal_stream),
consensus_data_provider: Some(Box::new(aura_digest_provider)),
create_inherent_data_providers,
};

let authorship_future = sc_consensus_manual_seal::run_manual_seal(params);
task_manager.spawn_essential_handle().spawn_blocking(
"manual-seal",
None,
authorship_future,
);
let create_inherent_data_providers =
Self::create_dev_seal_inherent_data_providers(client.clone(), para_id, slot_duration);

match mode {
DevSealMode::InstantSeal => {
let params = sc_consensus_manual_seal::InstantSealParams {
block_import: client.clone(),
env: proposer,
client: client.clone(),
pool: transaction_pool.clone(),
select_chain: LongestChain::new(backend.clone()),
consensus_data_provider: Some(Box::new(aura_digest_provider)),
create_inherent_data_providers,
};

let authorship_future = sc_consensus_manual_seal::run_instant_seal(params);
task_manager.spawn_essential_handle().spawn_blocking(
"instant-seal",
None,
authorship_future,
);
},
DevSealMode::ManualSeal(block_time) => {
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_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 params = sc_consensus_manual_seal::ManualSealParams {
block_import: client.clone(),
env: proposer,
client: client.clone(),
pool: transaction_pool.clone(),
select_chain: LongestChain::new(backend.clone()),
commands_stream: Box::pin(manual_seal_stream),
consensus_data_provider: Some(Box::new(aura_digest_provider)),
create_inherent_data_providers,
};

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();
Expand Down Expand Up @@ -373,11 +393,11 @@ where
RuntimeApi::RuntimeApi: AuraRuntimeApi<Block, AuraId>,
AuraId: AuraIdT + Sync,
{
/// Creates the inherent data providers for manual seal consensus.
/// Creates the inherent data providers for dev seal consensus.
///
/// This function sets up the timestamp and parachain validation data providers
/// required for manual seal block production in a parachain environment.
fn create_manual_seal_inherent_data_providers(
/// required for dev seal block production in a parachain environment.
fn create_dev_seal_inherent_data_providers(
client: Arc<ParachainClient<Block, RuntimeApi>>,
para_id: ParaId,
slot_duration: sp_consensus_aura::SlotDuration,
Expand Down
12 changes: 12 additions & 0 deletions prdoc/pr_10008.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
title: Add instant seal to omni-node
doc:
- audience: Runtime Dev
description: |-
Adds a new `--instant-seal` CLI flag to enable instant seal mode in omni-node. When this flag
is passed, blocks are produced immediately upon receiving transactions, rather than at fixed
intervals. This flag cannot be used together with `--dev-block-time`.

fixes https://github.com/paritytech/polkadot-sdk/issues/9996
crates:
- name: polkadot-omni-node-lib
bump: patch
Loading