From b1f8445d622b4ce4da2e9743aa6baf437b21f9de Mon Sep 17 00:00:00 2001
From: Andronik <write@reusable.software>
Date: Sat, 23 Jul 2022 01:24:33 +0200
Subject: [PATCH] malus: add `finality_delay` cli flag (#5770)

* add malus_finality_delay flag

* cargo update -p sp-io

* no warnings when malus is disabled

* subpar workaround for feature unification problem

* remove malus_finality_delay from regular cli

* document finality_delay param, rename cli arg
---
 polkadot/cli/src/command.rs                   | 19 ++++++++++++++++---
 polkadot/node/malus/src/malus.rs              |  8 ++++++--
 polkadot/node/service/src/lib.rs              | 16 +++++++++++++++-
 polkadot/node/test/service/src/lib.rs         |  1 +
 .../adder/collator/src/main.rs                |  1 +
 .../undying/collator/src/main.rs              |  1 +
 6 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/polkadot/cli/src/command.rs b/polkadot/cli/src/command.rs
index babfa1c3ce5..a7ab8f67aad 100644
--- a/polkadot/cli/src/command.rs
+++ b/polkadot/cli/src/command.rs
@@ -267,14 +267,21 @@ fn host_perf_check() -> Result<()> {
 /// Launch a node, accepting arguments just like a regular node,
 /// accepts an alternative overseer generator, to adjust behavior
 /// for integration tests as needed.
+/// `malus_finality_delay` restrict finality votes of this node
+/// to be at most `best_block - malus_finality_delay` height.
 #[cfg(feature = "malus")]
-pub fn run_node(run: Cli, overseer_gen: impl service::OverseerGen) -> Result<()> {
-	run_node_inner(run, overseer_gen, |_logger_builder, _config| {})
+pub fn run_node(
+	run: Cli,
+	overseer_gen: impl service::OverseerGen,
+	malus_finality_delay: Option<u32>,
+) -> Result<()> {
+	run_node_inner(run, overseer_gen, malus_finality_delay, |_logger_builder, _config| {})
 }
 
 fn run_node_inner<F>(
 	cli: Cli,
 	overseer_gen: impl service::OverseerGen,
+	maybe_malus_finality_delay: Option<u32>,
 	logger_hook: F,
 ) -> Result<()>
 where
@@ -340,6 +347,7 @@ where
 			false,
 			overseer_gen,
 			cli.run.overseer_channel_capacity_override,
+			maybe_malus_finality_delay,
 			hwbench,
 		)
 		.map(|full| full.task_manager)
@@ -377,7 +385,12 @@ pub fn run() -> Result<()> {
 	}
 
 	match &cli.subcommand {
-		None => run_node_inner(cli, service::RealOverseerGen, polkadot_node_metrics::logger_hook()),
+		None => run_node_inner(
+			cli,
+			service::RealOverseerGen,
+			None,
+			polkadot_node_metrics::logger_hook(),
+		),
 		Some(Subcommand::BuildSpec(cmd)) => {
 			let runner = cli.create_runner(cmd)?;
 			Ok(runner.sync_run(|config| cmd.run(config.chain_spec, config.network))?)
diff --git a/polkadot/node/malus/src/malus.rs b/polkadot/node/malus/src/malus.rs
index 88b3f8130ab..dd9f1377f14 100644
--- a/polkadot/node/malus/src/malus.rs
+++ b/polkadot/node/malus/src/malus.rs
@@ -53,6 +53,8 @@ enum NemesisVariant {
 struct MalusCli {
 	#[clap(subcommand)]
 	pub variant: NemesisVariant,
+	/// Sets the minimum delay between the best and finalized block.
+	pub finality_delay: Option<u32>,
 }
 
 fn run_cmd(run: RunCmd) -> Cli {
@@ -62,14 +64,16 @@ fn run_cmd(run: RunCmd) -> Cli {
 impl MalusCli {
 	/// Launch a malus node.
 	fn launch(self) -> eyre::Result<()> {
+		let finality_delay = self.finality_delay;
 		match self.variant {
 			NemesisVariant::BackGarbageCandidate(cmd) =>
-				polkadot_cli::run_node(run_cmd(cmd), BackGarbageCandidate)?,
+				polkadot_cli::run_node(run_cmd(cmd), BackGarbageCandidate, finality_delay)?,
 			NemesisVariant::SuggestGarbageCandidate(cmd) =>
-				polkadot_cli::run_node(run_cmd(cmd), BackGarbageCandidateWrapper)?,
+				polkadot_cli::run_node(run_cmd(cmd), BackGarbageCandidateWrapper, finality_delay)?,
 			NemesisVariant::DisputeAncestor(opts) => polkadot_cli::run_node(
 				run_cmd(opts.clone().cmd),
 				DisputeValidCandidates::new(opts),
+				finality_delay,
 			)?,
 			NemesisVariant::PvfPrepareWorker(cmd) => {
 				#[cfg(target_os = "android")]
diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs
index 0f131280b51..f199bbdbc07 100644
--- a/polkadot/node/service/src/lib.rs
+++ b/polkadot/node/service/src/lib.rs
@@ -725,6 +725,7 @@ pub fn new_full<RuntimeApi, ExecutorDispatch, OverseerGenerator>(
 	overseer_enable_anyways: bool,
 	overseer_gen: OverseerGenerator,
 	overseer_message_channel_capacity_override: Option<usize>,
+	_malus_finality_delay: Option<u32>,
 	hwbench: Option<sc_sysinfo::HwBench>,
 ) -> Result<NewFull<Arc<FullClient<RuntimeApi, ExecutorDispatch>>>, Error>
 where
@@ -1222,7 +1223,15 @@ where
 		// add a custom voting rule to temporarily stop voting for new blocks
 		// after the given pause block is finalized and restarting after the
 		// given delay.
-		let builder = grandpa::VotingRulesBuilder::default();
+		let mut builder = grandpa::VotingRulesBuilder::default();
+
+		#[cfg(not(feature = "malus"))]
+		let _malus_finality_delay = None;
+
+		if let Some(delay) = _malus_finality_delay {
+			info!(?delay, "Enabling malus finality delay",);
+			builder = builder.add(grandpa::BeforeBestBlockBy(delay));
+		};
 
 		let voting_rule = match grandpa_pause {
 			Some((block, delay)) => {
@@ -1350,6 +1359,7 @@ pub fn build_full(
 	overseer_enable_anyways: bool,
 	overseer_gen: impl OverseerGen,
 	overseer_message_channel_override: Option<usize>,
+	malus_finality_delay: Option<u32>,
 	hwbench: Option<sc_sysinfo::HwBench>,
 ) -> Result<NewFull<Client>, Error> {
 	#[cfg(feature = "rococo-native")]
@@ -1368,6 +1378,7 @@ pub fn build_full(
 			overseer_enable_anyways,
 			overseer_gen,
 			overseer_message_channel_override,
+			malus_finality_delay,
 			hwbench,
 		)
 		.map(|full| full.with_client(Client::Rococo))
@@ -1386,6 +1397,7 @@ pub fn build_full(
 			overseer_enable_anyways,
 			overseer_gen,
 			overseer_message_channel_override,
+			malus_finality_delay,
 			hwbench,
 		)
 		.map(|full| full.with_client(Client::Kusama))
@@ -1404,6 +1416,7 @@ pub fn build_full(
 			overseer_enable_anyways,
 			overseer_gen,
 			overseer_message_channel_override,
+			malus_finality_delay,
 			hwbench,
 		)
 		.map(|full| full.with_client(Client::Westend))
@@ -1425,6 +1438,7 @@ pub fn build_full(
 				gum::warn!("Channel capacity should _never_ be tampered with on polkadot!");
 				capacity
 			}),
+			malus_finality_delay,
 			hwbench,
 		)
 		.map(|full| full.with_client(Client::Polkadot))
diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs
index 90e311b910d..b9b99f28d1b 100644
--- a/polkadot/node/test/service/src/lib.rs
+++ b/polkadot/node/test/service/src/lib.rs
@@ -102,6 +102,7 @@ pub fn new_full(
 		polkadot_service::RealOverseerGen,
 		None,
 		None,
+		None,
 	)
 }
 
diff --git a/polkadot/parachain/test-parachains/adder/collator/src/main.rs b/polkadot/parachain/test-parachains/adder/collator/src/main.rs
index 3a0b7805c64..e0845f68720 100644
--- a/polkadot/parachain/test-parachains/adder/collator/src/main.rs
+++ b/polkadot/parachain/test-parachains/adder/collator/src/main.rs
@@ -67,6 +67,7 @@ fn main() -> Result<()> {
 					polkadot_service::RealOverseerGen,
 					None,
 					None,
+					None,
 				)
 				.map_err(|e| e.to_string())?;
 				let mut overseer_handle = full_node
diff --git a/polkadot/parachain/test-parachains/undying/collator/src/main.rs b/polkadot/parachain/test-parachains/undying/collator/src/main.rs
index 2f7d683400a..e352235679c 100644
--- a/polkadot/parachain/test-parachains/undying/collator/src/main.rs
+++ b/polkadot/parachain/test-parachains/undying/collator/src/main.rs
@@ -67,6 +67,7 @@ fn main() -> Result<()> {
 					polkadot_service::RealOverseerGen,
 					None,
 					None,
+					None,
 				)
 				.map_err(|e| e.to_string())?;
 				let mut overseer_handle = full_node
-- 
GitLab