referrerpolicy=no-referrer-when-downgrade

malus/variants/
dispute_valid_candidates.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! A malicious node that replaces approvals with invalid disputes
18//! against valid candidates. Additionally, the malus node can be configured to
19//! fake candidate validation and return a static result for candidate checking.
20//!
21//! Attention: For usage with `zombienet` only!
22
23#![allow(missing_docs)]
24
25use polkadot_cli::{
26	service::{
27		AuxStore, Error, ExtendedOverseerGenArgs, Overseer, OverseerConnector, OverseerGen,
28		OverseerGenArgs, OverseerHandle,
29	},
30	validator_overseer_builder, Cli,
31};
32use polkadot_node_subsystem::SpawnGlue;
33use polkadot_node_subsystem_types::{ChainApiBackend, RuntimeApiSubsystemClient};
34use sp_core::traits::SpawnNamed;
35
36// Filter wrapping related types.
37use super::common::{FakeCandidateValidation, FakeCandidateValidationError};
38use crate::{interceptor::*, variants::ReplaceValidationResult};
39
40use std::sync::Arc;
41
42#[derive(Debug, clap::Parser)]
43#[command(rename_all = "kebab-case")]
44#[allow(missing_docs)]
45pub struct DisputeAncestorOptions {
46	/// Malicious candidate validation subsystem configuration. When enabled, node PVF execution is
47	/// skipped during backing and/or approval and it's result can by specified by this option and
48	/// `--fake-validation-error` for invalid candidate outcomes.
49	#[arg(long, value_enum, ignore_case = true, default_value_t = FakeCandidateValidation::BackingAndApprovalInvalid)]
50	pub fake_validation: FakeCandidateValidation,
51
52	/// Applies only when `--fake-validation` is configured to reject candidates as invalid. It
53	/// allows to specify the exact error to return from the malicious candidate validation
54	/// subsystem.
55	#[arg(long, value_enum, ignore_case = true, default_value_t = FakeCandidateValidationError::InvalidOutputs)]
56	pub fake_validation_error: FakeCandidateValidationError,
57
58	/// Determines the percentage of candidates that should be disputed. Allows for fine-tuning
59	/// the intensity of the behavior of the malicious node. Value must be in the range [0..=100].
60	#[clap(short, long, ignore_case = true, default_value_t = 100, value_parser = clap::value_parser!(u8).range(0..=100))]
61	pub percentage: u8,
62
63	#[clap(flatten)]
64	pub cli: Cli,
65}
66
67pub(crate) struct DisputeValidCandidates {
68	/// Fake validation config (applies to disputes as well).
69	pub fake_validation: FakeCandidateValidation,
70	/// Fake validation error config.
71	pub fake_validation_error: FakeCandidateValidationError,
72	/// The probability of behaving maliciously.
73	pub percentage: u8,
74}
75
76impl OverseerGen for DisputeValidCandidates {
77	fn generate<Spawner, RuntimeClient>(
78		&self,
79		connector: OverseerConnector,
80		args: OverseerGenArgs<'_, Spawner, RuntimeClient>,
81		ext_args: Option<ExtendedOverseerGenArgs>,
82	) -> Result<(Overseer<SpawnGlue<Spawner>, Arc<RuntimeClient>>, OverseerHandle), Error>
83	where
84		RuntimeClient: RuntimeApiSubsystemClient + ChainApiBackend + AuxStore + 'static,
85		Spawner: 'static + SpawnNamed + Clone + Unpin,
86	{
87		let validation_filter = ReplaceValidationResult::new(
88			self.fake_validation,
89			self.fake_validation_error,
90			f64::from(self.percentage),
91		);
92
93		validator_overseer_builder(
94			args,
95			ext_args.expect("Extended arguments required to build validator overseer are provided"),
96		)?
97		.replace_candidate_validation(move |cv_subsystem| {
98			InterceptedSubsystem::new(cv_subsystem, validation_filter)
99		})
100		.build_with_connector(connector)
101		.map_err(|e| e.into())
102	}
103}