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
--- 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'
modifiednode/cli/src/cli.rsdiffbeforeafterboth
before · node/cli/src/cli.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use crate::chain_spec;18use std::{path::PathBuf, env};19use clap::Parser;2021const NODE_NAME_ENV: &str = "UNIQUE_NODE_NAME";2223/// Sub-commands supported by the collator.24#[derive(Debug, Parser)]25pub enum Subcommand {26	/// Export the genesis state of the parachain.27	#[clap(name = "export-genesis-state")]28	ExportGenesisState(ExportGenesisStateCommand),2930	/// Export the genesis wasm of the parachain.31	#[clap(name = "export-genesis-wasm")]32	ExportGenesisWasm(ExportGenesisWasmCommand),3334	/// Build a chain specification.35	BuildSpec(sc_cli::BuildSpecCmd),3637	/// Validate blocks.38	CheckBlock(sc_cli::CheckBlockCmd),3940	/// Export blocks.41	ExportBlocks(sc_cli::ExportBlocksCmd),4243	/// Export the state of a given block into a chain spec.44	ExportState(sc_cli::ExportStateCmd),4546	/// Import blocks.47	ImportBlocks(sc_cli::ImportBlocksCmd),4849	/// Remove the whole chain.50	PurgeChain(cumulus_client_cli::PurgeChainCmd),5152	/// Revert the chain to a previous state.53	Revert(sc_cli::RevertCmd),5455	/// The custom benchmark subcommmand benchmarking runtime pallets.56	#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]57	Benchmark(frame_benchmarking_cli::BenchmarkCmd),58}5960/// Command for exporting the genesis state of the parachain61#[derive(Debug, Parser)]62pub struct ExportGenesisStateCommand {63	/// Output file name or stdout if unspecified.64	#[clap(parse(from_os_str))]65	pub output: Option<PathBuf>,6667	/// Id of the parachain this state is for.68	///69	/// Default: 10070	#[clap(long, conflicts_with = "chain")]71	pub parachain_id: Option<u32>,7273	/// Write output in binary. Default is to write in hex.74	#[clap(short, long)]75	pub raw: bool,7677	/// The name of the chain for that the genesis state should be exported.78	#[clap(long, conflicts_with = "parachain-id")]79	pub chain: Option<String>,80}8182/// Command for exporting the genesis wasm file.83#[derive(Debug, Parser)]84pub struct ExportGenesisWasmCommand {85	/// Output file name or stdout if unspecified.86	#[clap(parse(from_os_str))]87	pub output: Option<PathBuf>,8889	/// Write output in binary. Default is to write in hex.90	#[clap(short, long)]91	pub raw: bool,9293	/// The name of the chain for that the genesis wasm file should be exported.94	#[clap(long)]95	pub chain: Option<String>,96}9798#[derive(Debug, Parser)]99#[clap(args_conflicts_with_subcommands = true, subcommand_negates_reqs = true)]100pub struct Cli {101	#[structopt(subcommand)]102	pub subcommand: Option<Subcommand>,103104	#[structopt(flatten)]105	pub run: cumulus_client_cli::RunCmd,106107	/// Relaychain arguments108	#[structopt(raw = true)]109	pub relaychain_args: Vec<String>,110}111112impl Cli {113	pub fn node_name() -> String {114		match env::var(NODE_NAME_ENV).ok() {115			Some(name) => name,116			None => {117				if cfg!(feature = "unique-runtime") {118					"Unique"119				} else if cfg!(feature = "quartz-runtime") {120					"Quartz"121				} else {122					"Opal"123				}124			}125			.into(),126		}127	}128}129130#[derive(Debug)]131pub struct RelayChainCli {132	/// The actual relay chain cli object.133	pub base: polkadot_cli::RunCmd,134135	/// Optional chain id that should be passed to the relay chain.136	pub chain_id: Option<String>,137138	/// The base path that should be used by the relay chain.139	pub base_path: Option<PathBuf>,140}141142impl RelayChainCli {143	/// Parse the relay chain CLI parameters using the para chain `Configuration`.144	pub fn new<'a>(145		para_config: &sc_service::Configuration,146		relay_chain_args: impl Iterator<Item = &'a String>,147	) -> Self {148		let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);149		let chain_id = extension.map(|e| e.relay_chain.clone());150		let base_path = para_config151			.base_path152			.as_ref()153			.map(|x| x.path().join("polkadot"));154		Self {155			base_path,156			chain_id,157			base: polkadot_cli::RunCmd::parse_from(relay_chain_args),158		}159	}160}
after · node/cli/src/cli.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use crate::chain_spec;18use std::{path::PathBuf, env};19use clap::Parser;2021const NODE_NAME_ENV: &str = "UNIQUE_NODE_NAME";2223/// Sub-commands supported by the collator.24#[derive(Debug, Parser)]25pub enum Subcommand {26	/// Export the genesis state of the parachain.27	#[clap(name = "export-genesis-state")]28	ExportGenesisState(ExportGenesisStateCommand),2930	/// Export the genesis wasm of the parachain.31	#[clap(name = "export-genesis-wasm")]32	ExportGenesisWasm(ExportGenesisWasmCommand),3334	/// Build a chain specification.35	BuildSpec(sc_cli::BuildSpecCmd),3637	/// Validate blocks.38	CheckBlock(sc_cli::CheckBlockCmd),3940	/// Export blocks.41	ExportBlocks(sc_cli::ExportBlocksCmd),4243	/// Export the state of a given block into a chain spec.44	ExportState(sc_cli::ExportStateCmd),4546	/// Import blocks.47	ImportBlocks(sc_cli::ImportBlocksCmd),4849	/// Remove the whole chain.50	PurgeChain(cumulus_client_cli::PurgeChainCmd),5152	/// Revert the chain to a previous state.53	Revert(sc_cli::RevertCmd),5455	/// The custom benchmark subcommmand benchmarking runtime pallets.56	#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]57	Benchmark(frame_benchmarking_cli::BenchmarkCmd),58}5960/// Command for exporting the genesis state of the parachain61#[derive(Debug, Parser)]62pub struct ExportGenesisStateCommand {63	/// Output file name or stdout if unspecified.64	#[clap(parse(from_os_str))]65	pub output: Option<PathBuf>,6667	/// Id of the parachain this state is for.68	///69	/// Default: 10070	#[clap(long, conflicts_with = "chain")]71	pub parachain_id: Option<u32>,7273	/// Write output in binary. Default is to write in hex.74	#[clap(short, long)]75	pub raw: bool,7677	/// The name of the chain for that the genesis state should be exported.78	#[clap(long, conflicts_with = "parachain-id")]79	pub chain: Option<String>,80}8182/// Command for exporting the genesis wasm file.83#[derive(Debug, Parser)]84pub struct ExportGenesisWasmCommand {85	/// Output file name or stdout if unspecified.86	#[clap(parse(from_os_str))]87	pub output: Option<PathBuf>,8889	/// Write output in binary. Default is to write in hex.90	#[clap(short, long)]91	pub raw: bool,9293	/// The name of the chain for that the genesis wasm file should be exported.94	#[clap(long)]95	pub chain: Option<String>,96}9798#[derive(Debug, Parser)]99#[clap(args_conflicts_with_subcommands = true, subcommand_negates_reqs = true)]100pub struct Cli {101	#[structopt(subcommand)]102	pub subcommand: Option<Subcommand>,103104	#[structopt(flatten)]105	pub run: cumulus_client_cli::RunCmd,106107	/// When running the node in the `--dev` mode and108	/// there is no transaction in the transaction pool,109	/// an empty block will be sealed automatically110	/// after the `--idle-autoseal-interval` milliseconds.111	///112	/// Default interval is 500 milliseconds113	#[structopt(default_value = "500", long)]114	pub idle_autoseal_interval: u64,115116	/// Relaychain arguments117	#[structopt(raw = true)]118	pub relaychain_args: Vec<String>,119}120121impl Cli {122	pub fn node_name() -> String {123		match env::var(NODE_NAME_ENV).ok() {124			Some(name) => name,125			None => {126				if cfg!(feature = "unique-runtime") {127					"Unique"128				} else if cfg!(feature = "quartz-runtime") {129					"Quartz"130				} else {131					"Opal"132				}133			}134			.into(),135		}136	}137}138139#[derive(Debug)]140pub struct RelayChainCli {141	/// The actual relay chain cli object.142	pub base: polkadot_cli::RunCmd,143144	/// Optional chain id that should be passed to the relay chain.145	pub chain_id: Option<String>,146147	/// The base path that should be used by the relay chain.148	pub base_path: Option<PathBuf>,149}150151impl RelayChainCli {152	/// Parse the relay chain CLI parameters using the para chain `Configuration`.153	pub fn new<'a>(154		para_config: &sc_service::Configuration,155		relay_chain_args: impl Iterator<Item = &'a String>,156	) -> Self {157		let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);158		let chain_id = extension.map(|e| e.relay_chain.clone());159		let base_path = para_config160			.base_path161			.as_ref()162			.map(|x| x.path().join("polkadot"));163		Self {164			base_path,165			chain_id,166			base: polkadot_cli::RunCmd::parse_from(relay_chain_args),167		}168	}169}
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();