From ae3d822925b8e3822b241f2a207e2c65404ce8ff Mon Sep 17 00:00:00 2001 From: Daniel Shiposha Date: Thu, 31 Mar 2022 11:38:37 +0000 Subject: [PATCH] Autoseal after idle n seconds --- --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -294,6 +294,7 @@ [dependencies] futures = '0.3.17' +futures-timer = '3.0.2' log = '0.4.14' flexi_logger = "0.15.7" parking_lot = '0.11.2' --- a/node/cli/src/cli.rs +++ b/node/cli/src/cli.rs @@ -104,6 +104,15 @@ #[structopt(flatten)] pub run: cumulus_client_cli::RunCmd, + /// When running the node in the `--dev` mode and + /// there is no transaction in the transaction pool, + /// an empty block will be sealed automatically + /// after the `--idle-autoseal-interval` milliseconds. + /// + /// Default interval is 500 milliseconds + #[structopt(default_value = "500", long)] + pub idle_autoseal_interval: u64, + /// Relaychain arguments #[structopt(raw = true)] pub relaychain_args: Vec, --- a/node/cli/src/command.rs +++ b/node/cli/src/command.rs @@ -35,7 +35,7 @@ use crate::{ chain_spec::{self, RuntimeId, RuntimeIdentification, ServiceId, ServiceIdentification}, cli::{Cli, RelayChainCli, Subcommand}, - service::{new_partial, start_node, start_dev_node}, + service::{new_partial, start_node, start_dev_node, AutosealInterval}, }; #[cfg(feature = "unique-runtime")] @@ -60,7 +60,7 @@ }; use sp_core::hexdisplay::HexDisplay; use sp_runtime::traits::Block as BlockT; -use std::{io::Write, net::SocketAddr}; +use std::{io::Write, net::SocketAddr, time::Duration}; use unique_runtime_common::types::Block; @@ -405,8 +405,12 @@ if is_dev_service { info!("Running Dev service"); + let autoseal_interval = AutosealInterval::new( + Duration::from_millis(cli.idle_autoseal_interval) + )?; + return start_node_using_chain_runtime! { - start_dev_node(config).map_err(Into::into) + start_dev_node(config, autoseal_interval).map_err(Into::into) }; }; --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -21,8 +21,11 @@ use std::sync::Mutex; use std::collections::BTreeMap; use std::time::Duration; +use std::pin::Pin; use fc_rpc_core::types::FeeHistoryCache; -use futures::StreamExt; +use futures::Future; +use futures::{Stream, StreamExt, stream::select, task::{Context, Poll}}; +use futures_timer::Delay; use unique_rpc::overrides_handle; @@ -111,6 +114,40 @@ } } +pub struct AutosealInterval { + duration: Duration, + delay_handle: Pin> +} + +impl AutosealInterval { + pub fn new(duration: Duration) -> Result { + if duration.is_zero() { + return Err("Invalid autoseal interval: 0 seconds".into()); + } + + Ok(Self { + duration, + delay_handle: Box::pin(Delay::new(duration)) + }) + } +} + +impl Stream for AutosealInterval { + type Item = (); + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.delay_handle.as_mut().poll(cx) { + Poll::Ready(_) => { + let duration = self.duration; + self.delay_handle.reset(duration); + + Poll::Ready(Some(())) + } + Poll::Pending => Poll::Pending + } + } +} + pub fn open_frontier_backend(config: &Configuration) -> Result>, String> { let config_dir = config .base_path @@ -712,6 +749,7 @@ /// the parachain inherent pub fn start_dev_node( config: Configuration, + autoseal_interval: AutosealInterval, ) -> sc_service::error::Result where Runtime: RuntimeInstance + Send + Sync + 'static, @@ -735,7 +773,6 @@ + sp_consensus_aura::AuraApi, ExecutorDispatch: NativeExecutionDispatch + 'static, { - use futures::Stream; use sc_consensus_manual_seal::{run_manual_seal, EngineCommand, ManualSealParams}; use fc_consensus::FrontierBlockImport; use sc_client_api::HeaderBackend; @@ -799,21 +836,36 @@ telemetry.as_ref().map(|x| x.handle()), ); - let commands_stream: Box> + Send + Sync + Unpin> = + let transactions_commands_stream: Box> + Send + Sync + Unpin> = Box::new( - // This bit cribbed from the implementation of instant seal. transaction_pool .pool() .validated_pool() .import_notification_stream() .map(|_| EngineCommand::SealNewBlock { - create_empty: true, // was false in Moonbeam + create_empty: true, finalize: false, parent_hash: None, sender: None, }), ); + let autoseal_interval = Box::pin(autoseal_interval); + let idle_commands_stream: Box> + Send + Sync + Unpin> = + Box::new( + autoseal_interval.map(|_| EngineCommand::SealNewBlock { + create_empty: true, + finalize: false, + parent_hash: None, + sender: None, + }) + ); + + let commands_stream = select( + transactions_commands_stream, + idle_commands_stream + ); + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; let client_set_aside_for_cidp = client.clone(); -- gitstuff