diff --git a/polkadot/node/malus/src/malus.rs b/polkadot/node/malus/src/malus.rs
index b8a83e54d4f5..7a9e320e2736 100644
--- a/polkadot/node/malus/src/malus.rs
+++ b/polkadot/node/malus/src/malus.rs
@@ -32,6 +32,8 @@ use variants::*;
enum NemesisVariant {
/// Suggest a candidate with an invalid proof of validity.
SuggestGarbageCandidate(SuggestGarbageCandidateOptions),
+ /// Support disabled validators in backing and statement distribution.
+ SupportDisabled(SupportDisabledOptions),
/// Back a candidate with a specifically crafted proof of validity.
BackGarbageCandidate(BackGarbageCandidateOptions),
/// Delayed disputing of ancestors that are perfectly fine.
@@ -68,6 +70,11 @@ impl MalusCli {
finality_delay,
)?
},
+ NemesisVariant::SupportDisabled(opts) => {
+ let SupportDisabledOptions { cli } = opts;
+
+ polkadot_cli::run_node(cli, SupportDisabled, finality_delay)?
+ },
NemesisVariant::DisputeAncestor(opts) => {
let DisputeAncestorOptions {
fake_validation,
diff --git a/polkadot/node/malus/src/variants/mod.rs b/polkadot/node/malus/src/variants/mod.rs
index bb4971c145ce..3ca1bf4b4696 100644
--- a/polkadot/node/malus/src/variants/mod.rs
+++ b/polkadot/node/malus/src/variants/mod.rs
@@ -21,11 +21,13 @@ mod common;
mod dispute_finalized_candidates;
mod dispute_valid_candidates;
mod suggest_garbage_candidate;
+mod support_disabled;
pub(crate) use self::{
back_garbage_candidate::{BackGarbageCandidateOptions, BackGarbageCandidates},
dispute_finalized_candidates::{DisputeFinalizedCandidates, DisputeFinalizedCandidatesOptions},
dispute_valid_candidates::{DisputeAncestorOptions, DisputeValidCandidates},
suggest_garbage_candidate::{SuggestGarbageCandidateOptions, SuggestGarbageCandidates},
+ support_disabled::{SupportDisabled, SupportDisabledOptions},
};
pub(crate) use common::*;
diff --git a/polkadot/node/malus/src/variants/support_disabled.rs b/polkadot/node/malus/src/variants/support_disabled.rs
new file mode 100644
index 000000000000..5fb53be7774b
--- /dev/null
+++ b/polkadot/node/malus/src/variants/support_disabled.rs
@@ -0,0 +1,98 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot. If not, see .
+
+//! This variant of Malus overrides the `disabled_validators` runtime API
+//! to always return an empty set of disabled validators.
+
+use polkadot_cli::{
+ prepared_overseer_builder,
+ service::{
+ AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, HeaderBackend, Overseer,
+ OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle, ParachainHost,
+ ProvideRuntimeApi,
+ },
+ Cli,
+};
+use polkadot_node_subsystem::SpawnGlue;
+use polkadot_node_subsystem_types::DefaultSubsystemClient;
+use sp_core::traits::SpawnNamed;
+
+use crate::interceptor::*;
+
+use std::sync::Arc;
+
+#[derive(Debug, clap::Parser)]
+#[clap(rename_all = "kebab-case")]
+#[allow(missing_docs)]
+pub struct SupportDisabledOptions {
+ #[clap(flatten)]
+ pub cli: Cli,
+}
+
+/// Generates an overseer with a custom runtime API subsystem.
+pub(crate) struct SupportDisabled;
+
+impl OverseerGen for SupportDisabled {
+ fn generate(
+ &self,
+ connector: OverseerConnector,
+ args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
+ ) -> Result<
+ (Overseer, Arc>>, OverseerHandle),
+ Error,
+ >
+ where
+ RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore,
+ RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi,
+ Spawner: 'static + SpawnNamed + Clone + Unpin,
+ {
+ prepared_overseer_builder(args)?
+ .replace_runtime_api(move |ra_subsystem| {
+ InterceptedSubsystem::new(ra_subsystem, IgnoreDisabled)
+ })
+ .build_with_connector(connector)
+ .map_err(|e| e.into())
+ }
+}
+
+#[derive(Clone)]
+struct IgnoreDisabled;
+
+impl MessageInterceptor for IgnoreDisabled
+where
+ Sender: overseer::RuntimeApiSenderTrait + Clone + Send + 'static,
+{
+ type Message = RuntimeApiMessage;
+
+ /// Intercept incoming runtime api requests.
+ fn intercept_incoming(
+ &self,
+ _subsystem_sender: &mut Sender,
+ msg: FromOrchestra,
+ ) -> Option> {
+ match msg {
+ FromOrchestra::Communication {
+ msg:
+ RuntimeApiMessage::Request(_relay_parent, RuntimeApiRequest::DisabledValidators(tx)),
+ } => {
+ let _ = tx.send(Ok(Vec::new()));
+ None
+ },
+ FromOrchestra::Communication { msg } => Some(FromOrchestra::Communication { msg }),
+ FromOrchestra::Signal(signal) => Some(FromOrchestra::Signal(signal)),
+ }
+ }
+}
diff --git a/prdoc/pr_2835.prdoc b/prdoc/pr_2835.prdoc
new file mode 100644
index 000000000000..037e9b8ec770
--- /dev/null
+++ b/prdoc/pr_2835.prdoc
@@ -0,0 +1,9 @@
+title: New malus variant `support-disabled`
+
+doc:
+ - audience: Node Dev
+ description: |
+ A new malicious flavor added to pretend that nobody
+ is disabled onchain.
+
+crates: [ ]