git.delta.rocks / unique-network / refs/commits / ae3d822925b8

difftreelog

Autoseal after idle n seconds

Daniel Shiposha2022-03-31parent: #20779ae.patch.diff
in: master

4 files changed

modifiednode/cli/Cargo.tomldiffbeforeafterboth
294294
295[dependencies]295[dependencies]
296futures = '0.3.17'296futures = '0.3.17'
297futures-timer = '3.0.2'
297log = '0.4.14'298log = '0.4.14'
298flexi_logger = "0.15.7"299flexi_logger = "0.15.7"
299parking_lot = '0.11.2'300parking_lot = '0.11.2'
modifiednode/cli/src/cli.rsdiffbeforeafterboth
--- 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<String>,
modifiednode/cli/src/command.rsdiffbeforeafterboth
--- 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)
 					};
 				};
 
modifiednode/cli/src/service.rsdiffbeforeafterboth
--- 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<Box<Delay>>
+}
+
+impl AutosealInterval {
+	pub fn new(duration: Duration) -> Result<Self, String> {
+		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<Option<Self::Item>> {
+		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<Arc<fc_db::Backend<Block>>, String> {
 	let config_dir = config
 		.base_path
@@ -712,6 +749,7 @@
 /// the parachain inherent
 pub fn start_dev_node<Runtime, RuntimeApi, ExecutorDispatch>(
 	config: Configuration,
+	autoseal_interval: AutosealInterval,
 ) -> sc_service::error::Result<TaskManager>
 where
 	Runtime: RuntimeInstance + Send + Sync + 'static,
@@ -735,7 +773,6 @@
 		+ sp_consensus_aura::AuraApi<Block, AuraId>,
 	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<dyn Stream<Item = EngineCommand<Hash>> + Send + Sync + Unpin> =
+		let transactions_commands_stream: Box<dyn Stream<Item = EngineCommand<Hash>> + 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<dyn Stream<Item = EngineCommand<Hash>> + 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();