Skip to content

Commit 31001cd

Browse files
pgherveougithub-actions[bot]iulianbarbu
authored
Add instant seal to omni-node (#10008)
Adds a new `--instant-seal` CLI flag to enable instant seal mode in omni-node. fixes #9996 --------- Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Iulian Barbu <[email protected]>
1 parent 5982154 commit 31001cd

File tree

5 files changed

+129
-71
lines changed

5 files changed

+129
-71
lines changed

cumulus/polkadot-omni-node/lib/src/cli.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
//! CLI options of the omni-node. See [`Command`].
1818
19+
/// Default block time for dev mode when using `--dev` flag.
20+
const DEFAULT_DEV_BLOCK_TIME_MS: u64 = 3000;
21+
1922
use crate::{
2023
chain_spec::DiskChainSpecLoader,
2124
common::{
@@ -163,9 +166,19 @@ pub struct Cli<Config: CliConfig> {
163166
///
164167
/// The `--dev` flag sets the `dev_block_time` to a default value of 3000ms unless explicitly
165168
/// provided.
166-
#[arg(long)]
169+
#[arg(long, conflicts_with = "instant_seal")]
167170
pub dev_block_time: Option<u64>,
168171

172+
/// Start a dev node with instant seal.
173+
///
174+
/// This is a dev option that enables instant sealing, meaning blocks are produced
175+
/// immediately when transactions are received, rather than at fixed intervals.
176+
/// Using this option won't result in starting or connecting to a parachain network.
177+
/// The resulting node will work on its own, running the wasm blob and producing blocks
178+
/// instantly upon receiving transactions.
179+
#[arg(long, conflicts_with = "dev_block_time")]
180+
pub instant_seal: bool,
181+
169182
/// DEPRECATED: This feature has been stabilized, pLease use `--authoring slot-based` instead.
170183
///
171184
/// Use slot-based collator which can handle elastic scaling.
@@ -209,6 +222,16 @@ pub struct Cli<Config: CliConfig> {
209222
pub(crate) _phantom: PhantomData<Config>,
210223
}
211224

225+
/// Development sealing mode.
226+
#[derive(Debug, Clone, Copy)]
227+
pub(crate) enum DevSealMode {
228+
/// Produces blocks immediately upon receiving transactions.
229+
InstantSeal,
230+
/// Produces blocks at fixed time intervals.
231+
/// The u64 parameter represents the block time in milliseconds.
232+
ManualSeal(u64),
233+
}
234+
212235
/// Collator implementation to use.
213236
#[derive(PartialEq, Debug, ValueEnum, Clone, Copy)]
214237
pub enum AuthoringPolicy {
@@ -242,6 +265,19 @@ impl<Config: CliConfig> Cli<Config> {
242265
enable_statement_store: self.enable_statement_store,
243266
}
244267
}
268+
269+
/// Returns the dev seal mode if the node is in dev mode.
270+
pub(crate) fn dev_mode(&self) -> Option<DevSealMode> {
271+
if self.instant_seal {
272+
Some(DevSealMode::InstantSeal)
273+
} else if let Some(dev_block_time) = self.dev_block_time {
274+
Some(DevSealMode::ManualSeal(dev_block_time))
275+
} else if self.run.base.is_dev().unwrap_or(false) {
276+
Some(DevSealMode::ManualSeal(DEFAULT_DEV_BLOCK_TIME_MS))
277+
} else {
278+
None
279+
}
280+
}
245281
}
246282

247283
impl<Config: CliConfig> SubstrateCli for Cli<Config> {

cumulus/polkadot-omni-node/lib/src/command.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,10 @@ use clap::{CommandFactory, FromArgMatches};
3535
use cumulus_client_service::storage_proof_size::HostFunctions as ReclaimHostFunctions;
3636
use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE};
3737
use log::info;
38-
use sc_cli::{CliConfiguration, Result, SubstrateCli};
38+
use sc_cli::{Result, SubstrateCli};
3939
#[cfg(feature = "runtime-benchmarks")]
4040
use sp_runtime::traits::HashingFor;
4141

42-
const DEFAULT_DEV_BLOCK_TIME_MS: u64 = 3000;
43-
4442
/// Structure that can be used in order to provide customizers for different functionalities of the
4543
/// node binary that is being built using this library.
4644
pub struct RunConfig {
@@ -303,17 +301,8 @@ where
303301
let node_spec =
304302
new_node_spec(&config, &cmd_config.runtime_resolver, &cli.node_extra_args())?;
305303

306-
if cli.run.base.is_dev()? {
307-
let dev_block_time = cli.dev_block_time.unwrap_or(DEFAULT_DEV_BLOCK_TIME_MS);
308-
return node_spec
309-
.start_manual_seal_node(config, dev_block_time)
310-
.map_err(Into::into);
311-
}
312-
313-
if let Some(dev_block_time) = cli.dev_block_time {
314-
return node_spec
315-
.start_manual_seal_node(config, dev_block_time)
316-
.map_err(Into::into);
304+
if let Some(dev_mode) = cli.dev_mode() {
305+
return node_spec.start_dev_node(config, dev_mode).map_err(Into::into);
317306
}
318307

319308
// If Statemint (Statemine, Westmint, Rockmine) DB exists and we're using the

cumulus/polkadot-omni-node/lib/src/common/spec.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
use crate::{
1818
chain_spec::Extensions,
19+
cli::DevSealMode,
1920
common::{
2021
command::NodeCommandRunner,
2122
rpc::BuildRpcExtensions,
@@ -300,11 +301,11 @@ pub(crate) trait NodeSpec: BaseNodeSpec {
300301

301302
const SYBIL_RESISTANCE: CollatorSybilResistance;
302303

303-
fn start_manual_seal_node(
304+
fn start_dev_node(
304305
_config: Configuration,
305-
_block_time: u64,
306+
_mode: DevSealMode,
306307
) -> sc_service::error::Result<TaskManager> {
307-
Err(sc_service::Error::Other("Manual seal not supported for this node type".into()))
308+
Err(sc_service::Error::Other("Dev not supported for this node type".into()))
308309
}
309310

310311
/// Start a node with the given parachain spec.
@@ -557,11 +558,11 @@ pub(crate) trait NodeSpec: BaseNodeSpec {
557558
}
558559

559560
pub(crate) trait DynNodeSpec: NodeCommandRunner {
560-
/// Start node with manual-seal consensus.
561-
fn start_manual_seal_node(
561+
/// Start node with manual or instant seal consensus.
562+
fn start_dev_node(
562563
self: Box<Self>,
563564
config: Configuration,
564-
block_time: u64,
565+
mode: DevSealMode,
565566
) -> sc_service::error::Result<TaskManager>;
566567

567568
/// Start the node.
@@ -579,12 +580,12 @@ impl<T> DynNodeSpec for T
579580
where
580581
T: NodeSpec + NodeCommandRunner,
581582
{
582-
fn start_manual_seal_node(
583+
fn start_dev_node(
583584
self: Box<Self>,
584585
config: Configuration,
585-
block_time: u64,
586+
mode: DevSealMode,
586587
) -> sc_service::error::Result<TaskManager> {
587-
<Self as NodeSpec>::start_manual_seal_node(config, block_time)
588+
<Self as NodeSpec>::start_dev_node(config, mode)
588589
}
589590

590591
fn start_node(

cumulus/polkadot-omni-node/lib/src/nodes/aura.rs

Lines changed: 67 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// limitations under the License.
1616

1717
use crate::{
18-
cli::AuthoringPolicy,
18+
cli::{AuthoringPolicy, DevSealMode},
1919
common::{
2020
aura::{AuraIdT, AuraRuntimeApi},
2121
rpc::{BuildParachainRpcExtensions, BuildRpcExtensions},
@@ -211,9 +211,9 @@ where
211211
type StartConsensus = StartConsensus;
212212
const SYBIL_RESISTANCE: CollatorSybilResistance = CollatorSybilResistance::Resistant;
213213

214-
fn start_manual_seal_node(
214+
fn start_dev_node(
215215
mut config: Configuration,
216-
block_time: u64,
216+
mode: DevSealMode,
217217
) -> sc_service::error::Result<TaskManager> {
218218
let PartialComponents {
219219
client,
@@ -277,24 +277,6 @@ where
277277
None,
278278
);
279279

280-
let (manual_seal_sink, manual_seal_stream) = futures::channel::mpsc::channel(1024);
281-
let mut manual_seal_sink_clone = manual_seal_sink.clone();
282-
task_manager
283-
.spawn_essential_handle()
284-
.spawn("block_authoring", None, async move {
285-
loop {
286-
futures_timer::Delay::new(std::time::Duration::from_millis(block_time)).await;
287-
manual_seal_sink_clone
288-
.try_send(sc_consensus_manual_seal::EngineCommand::SealNewBlock {
289-
create_empty: true,
290-
finalize: true,
291-
parent_hash: None,
292-
sender: None,
293-
})
294-
.unwrap();
295-
}
296-
});
297-
298280
// Note: Changing slot durations are currently not supported
299281
let slot_duration = sc_consensus_aura::slot_duration(&*client)
300282
.expect("slot_duration is always present; qed.");
@@ -305,29 +287,67 @@ where
305287

306288
let para_id =
307289
Self::parachain_id(&client, &config).ok_or("Failed to retrieve the parachain id")?;
308-
let create_inherent_data_providers = Self::create_manual_seal_inherent_data_providers(
309-
client.clone(),
310-
para_id,
311-
slot_duration,
312-
);
313-
314-
let params = sc_consensus_manual_seal::ManualSealParams {
315-
block_import: client.clone(),
316-
env: proposer,
317-
client: client.clone(),
318-
pool: transaction_pool.clone(),
319-
select_chain: LongestChain::new(backend.clone()),
320-
commands_stream: Box::pin(manual_seal_stream),
321-
consensus_data_provider: Some(Box::new(aura_digest_provider)),
322-
create_inherent_data_providers,
323-
};
324-
325-
let authorship_future = sc_consensus_manual_seal::run_manual_seal(params);
326-
task_manager.spawn_essential_handle().spawn_blocking(
327-
"manual-seal",
328-
None,
329-
authorship_future,
330-
);
290+
let create_inherent_data_providers =
291+
Self::create_dev_node_inherent_data_providers(client.clone(), para_id, slot_duration);
292+
293+
match mode {
294+
DevSealMode::InstantSeal => {
295+
let params = sc_consensus_manual_seal::InstantSealParams {
296+
block_import: client.clone(),
297+
env: proposer,
298+
client: client.clone(),
299+
pool: transaction_pool.clone(),
300+
select_chain: LongestChain::new(backend.clone()),
301+
consensus_data_provider: Some(Box::new(aura_digest_provider)),
302+
create_inherent_data_providers,
303+
};
304+
305+
let authorship_future = sc_consensus_manual_seal::run_instant_seal(params);
306+
task_manager.spawn_essential_handle().spawn_blocking(
307+
"instant-seal",
308+
None,
309+
authorship_future,
310+
);
311+
},
312+
DevSealMode::ManualSeal(block_time) => {
313+
let (manual_seal_sink, manual_seal_stream) = futures::channel::mpsc::channel(1024);
314+
let mut manual_seal_sink_clone = manual_seal_sink.clone();
315+
task_manager
316+
.spawn_essential_handle()
317+
.spawn("block_authoring", None, async move {
318+
loop {
319+
futures_timer::Delay::new(std::time::Duration::from_millis(block_time))
320+
.await;
321+
manual_seal_sink_clone
322+
.try_send(sc_consensus_manual_seal::EngineCommand::SealNewBlock {
323+
create_empty: true,
324+
finalize: true,
325+
parent_hash: None,
326+
sender: None,
327+
})
328+
.unwrap();
329+
}
330+
});
331+
332+
let params = sc_consensus_manual_seal::ManualSealParams {
333+
block_import: client.clone(),
334+
env: proposer,
335+
client: client.clone(),
336+
pool: transaction_pool.clone(),
337+
select_chain: LongestChain::new(backend.clone()),
338+
commands_stream: Box::pin(manual_seal_stream),
339+
consensus_data_provider: Some(Box::new(aura_digest_provider)),
340+
create_inherent_data_providers,
341+
};
342+
343+
let authorship_future = sc_consensus_manual_seal::run_manual_seal(params);
344+
task_manager.spawn_essential_handle().spawn_blocking(
345+
"manual-seal",
346+
None,
347+
authorship_future,
348+
);
349+
},
350+
}
331351

332352
let rpc_extensions_builder = {
333353
let client = client.clone();
@@ -373,11 +393,11 @@ where
373393
RuntimeApi::RuntimeApi: AuraRuntimeApi<Block, AuraId>,
374394
AuraId: AuraIdT + Sync,
375395
{
376-
/// Creates the inherent data providers for manual seal consensus.
396+
/// Creates the inherent data providers for manual and instant seal consensus.
377397
///
378398
/// This function sets up the timestamp and parachain validation data providers
379-
/// required for manual seal block production in a parachain environment.
380-
fn create_manual_seal_inherent_data_providers(
399+
/// required for dev seal block production in a parachain environment.
400+
fn create_dev_node_inherent_data_providers(
381401
client: Arc<ParachainClient<Block, RuntimeApi>>,
382402
para_id: ParaId,
383403
slot_duration: sp_consensus_aura::SlotDuration,

prdoc/pr_10008.prdoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
title: Add instant seal to omni-node
2+
doc:
3+
- audience: Runtime Dev
4+
description: |-
5+
Adds a new `--instant-seal` CLI flag to enable instant seal mode in omni-node. When this flag
6+
is passed, blocks are produced immediately upon receiving transactions, rather than at fixed
7+
intervals. This flag cannot be used together with `--dev-block-time`.
8+
9+
fixes https://github.com/paritytech/polkadot-sdk/issues/9996
10+
crates:
11+
- name: polkadot-omni-node-lib
12+
bump: patch

0 commit comments

Comments
 (0)