Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Malus: improvements in dispute ancestor and suggest garbage candidate implementation #5011

Merged
merged 46 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
93656e2
Implement fake validation results
sandreim Feb 14, 2022
f216579
Merge branch 'master' of github.com:paritytech/polkadot into sandreim…
sandreim Feb 28, 2022
2744e75
refactor
sandreim Mar 1, 2022
9941f03
Merge branch 'master' of github.com:paritytech/polkadot into sandreim…
sandreim Mar 1, 2022
a3172b0
cargo lock
sandreim Mar 1, 2022
9100866
spell check
sandreim Mar 1, 2022
efd37ad
spellcheck
sandreim Mar 2, 2022
d4da58d
typos
sandreim Mar 2, 2022
b4719b4
Merge branch 'master' of github.com:paritytech/polkadot into sandreim…
sandreim Mar 4, 2022
b70512b
Review feedback
sandreim Mar 10, 2022
050bab4
Merge branch 'master' of github.com:paritytech/polkadot into sandreim…
sandreim Mar 10, 2022
f786866
move stuff around
sandreim Mar 10, 2022
9e72a42
Merge branch 'master' of github.com:paritytech/polkadot into sandreim…
sandreim Mar 23, 2022
c4a4560
chores
sandreim Mar 23, 2022
e90ab09
Impl valid - still wip
sandreim Mar 24, 2022
8226f4e
fixes
sandreim Mar 26, 2022
35c8c8e
fmt
sandreim Mar 26, 2022
1c279dc
Pull Ladi's implementation:
sandreim Mar 28, 2022
8932494
Fix build
sandreim Mar 28, 2022
fb75de4
Logs and comments
sandreim Mar 28, 2022
9408f45
WIP: suggest garbage candidate + implement validation result caching
sandreim Mar 28, 2022
78ed119
fix
sandreim Mar 28, 2022
efe4e50
Do commitment hash checks in candidate validation
sandreim Mar 30, 2022
1d02b2a
Minor refactor in approval, backing, dispute-coord
sandreim Mar 30, 2022
4719ad3
Working version of suggest garbage candidate
sandreim Mar 30, 2022
519d693
Dedup
sandreim Mar 30, 2022
6724b4a
cleanup #1
sandreim Mar 31, 2022
b6e1bbd
Fix tests
sandreim Apr 1, 2022
1980661
Merge branch 'master' of github.com:paritytech/polkadot into sandreim…
sandreim Apr 1, 2022
5f29b6c
remove debug leftovers
sandreim Apr 1, 2022
ea2b1e5
fmt
sandreim Apr 1, 2022
fca095f
Accidentally commited some local test
sandreim Apr 1, 2022
7d6b472
spellcheck
sandreim Apr 1, 2022
3103ce7
some more fixes
sandreim Apr 4, 2022
bde2403
Refactor and fix it
sandreim Apr 8, 2022
3784972
review feedback
sandreim Apr 8, 2022
991d77f
typo
sandreim Apr 8, 2022
0fa5890
tests review feedback
sandreim Apr 8, 2022
71c35a9
refactor disputer
sandreim Apr 8, 2022
fee4722
fix tests
sandreim Apr 8, 2022
6fb63d2
Fix zombienet disputes test
sandreim Apr 11, 2022
e29433e
Merge branch 'master' of github.com:paritytech/polkadot into sandreim…
sandreim Apr 11, 2022
ab22c59
spellcheck
sandreim Apr 11, 2022
f67b522
fix
sandreim Apr 11, 2022
6181157
Fix ui tests
sandreim Apr 11, 2022
155524c
fix typo
sandreim Apr 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions node/malus/src/malus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! A malus or nemesis node launch code.

use clap::Parser;
use clap::{ArgEnum, Parser};
use color_eyre::eyre;
use polkadot_cli::{Cli, RunCmd};

Expand Down Expand Up @@ -48,11 +48,24 @@ enum NemesisVariant {
PvfExecuteWorker(polkadot_cli::ValidationWorkerCommand),
}

#[derive(ArgEnum, Clone, Debug, PartialEq)]
#[clap(rename_all = "kebab-case")]
pub enum FakeCandidateValidation {
Invalid,
// TODO: impl Valid.
}

#[derive(Debug, Parser)]
#[allow(missing_docs)]
struct MalusCli {
#[clap(subcommand)]
pub variant: NemesisVariant,

#[clap(long, arg_enum, ignore_case = true)]
pub fake_backing_validation: Option<FakeCandidateValidation>,

#[clap(long, arg_enum, ignore_case = true)]
pub fake_approval_validation: Option<FakeCandidateValidation>,
sandreim marked this conversation as resolved.
Show resolved Hide resolved
}

fn run_cmd(run: RunCmd) -> Cli {
Expand All @@ -67,8 +80,13 @@ impl MalusCli {
polkadot_cli::run_node(run_cmd(cmd), BackGarbageCandidate)?,
NemesisVariant::SuggestGarbageCandidate(cmd) =>
polkadot_cli::run_node(run_cmd(cmd), SuggestGarbageCandidate)?,
NemesisVariant::DisputeAncestor(cmd) =>
polkadot_cli::run_node(run_cmd(cmd), DisputeValidCandidates)?,
NemesisVariant::DisputeAncestor(cmd) => polkadot_cli::run_node(
run_cmd(cmd),
DisputeValidCandidates::new(
self.fake_backing_validation,
self.fake_approval_validation,
),
)?,
NemesisVariant::PvfPrepareWorker(cmd) => {
#[cfg(target_os = "android")]
{
Expand Down
133 changes: 133 additions & 0 deletions node/malus/src/variants/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright 2022 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 <http://www.gnu.org/licenses/>.

//! Implements common code for nemesis. Currently, only `FakeValidationResult`
//! interceptor is implemented.

#![allow(missing_docs)]

// Filter wrapping related types.
use crate::{interceptor::*, shared::MALUS, FakeCandidateValidation};
use polkadot_node_primitives::{InvalidCandidate, ValidationResult};
use polkadot_node_subsystem::messages::CandidateValidationMessage;

#[derive(Clone, Debug)]
/// An interceptor which fakes validation result with a preconfigured result.
/// Replaces `CandidateValidationSubsystem`.
pub struct ReplaceValidationResult {
fake_backing_validation: Option<FakeCandidateValidation>,
fake_approval_validation: Option<FakeCandidateValidation>,
sandreim marked this conversation as resolved.
Show resolved Hide resolved
}

impl ReplaceValidationResult {
pub fn new(
fake_backing_validation: Option<FakeCandidateValidation>,
fake_approval_validation: Option<FakeCandidateValidation>,
) -> Self {
Self { fake_backing_validation, fake_approval_validation }
}
}

impl<Sender> MessageInterceptor<Sender> for ReplaceValidationResult
where
Sender: overseer::SubsystemSender<CandidateValidationMessage> + Clone + Send + 'static,
{
type Message = CandidateValidationMessage;

// Capture all candidate validation requests and depending on configuration fail them.
// MaybeTODO: add option to configure the failure reason.
fn intercept_incoming(
&self,
_sender: &mut Sender,
msg: FromOverseer<Self::Message>,
) -> Option<FromOverseer<Self::Message>> {
if self.fake_backing_validation.is_none() && self.fake_approval_validation.is_none() {
return Some(msg)
}

match msg {
FromOverseer::Communication {
msg:
CandidateValidationMessage::ValidateFromExhaustive(
validation_data,
validation_code,
descriptor,
pov,
timeout,
sender,
),
} => {
if let Some(FakeCandidateValidation::Invalid) = self.fake_approval_validation {
let validation_result =
ValidationResult::Invalid(InvalidCandidate::InvalidOutputs);

tracing::info!(
target = MALUS,
para_id = ?descriptor.para_id,
candidate_hash = ?descriptor.para_head,
"ValidateFromExhaustive result: {:?}",
&validation_result
);
// We're not even checking the candidate, this makes us appear faster than honest validators.
sender.send(Ok(validation_result)).unwrap();
None
} else {
Some(FromOverseer::Communication {
msg: CandidateValidationMessage::ValidateFromExhaustive(
validation_data,
validation_code,
descriptor,
pov,
timeout,
sender,
),
})
}
},
FromOverseer::Communication {
msg:
CandidateValidationMessage::ValidateFromChainState(descriptor, pov, timeout, sender),
} => {
if let Some(FakeCandidateValidation::Invalid) = self.fake_backing_validation {
let validation_result =
ValidationResult::Invalid(InvalidCandidate::InvalidOutputs);
tracing::info!(
target = MALUS,
para_id = ?descriptor.para_id,
candidate_hash = ?descriptor.para_head,
"ValidateFromChainState result: {:?}",
&validation_result
);

// We're not even checking the candidate, this makes us appear faster than honest validators.
sender.send(Ok(validation_result)).unwrap();
None
} else {
Some(FromOverseer::Communication {
msg: CandidateValidationMessage::ValidateFromChainState(
descriptor, pov, timeout, sender,
),
})
}
},
msg => Some(msg),
}
}

fn intercept_outgoing(&self, msg: AllMessages) -> Option<AllMessages> {
Some(msg)
}
}
61 changes: 54 additions & 7 deletions node/malus/src/variants/dispute_valid_candidates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@ use polkadot_cli::{
};

// Filter wrapping related types.
use crate::interceptor::*;
use crate::{
interceptor::*, shared::MALUS, variants::ReplaceValidationResult, FakeCandidateValidation,
};

// Import extra types relevant to the particular
// subsystem.
use polkadot_node_core_backing::CandidateBackingSubsystem;
use polkadot_node_core_candidate_validation::CandidateValidationSubsystem;

use polkadot_node_subsystem::messages::{
ApprovalDistributionMessage, CandidateBackingMessage, DisputeCoordinatorMessage,
};
Expand Down Expand Up @@ -75,6 +79,12 @@ where
session,
..
}) => {
tracing::info!(
target = MALUS,
para_id = ?candidate_receipt.descriptor.para_id,
?candidate_hash,
"Disputing candidate",
);
// this would also dispute candidates we were not assigned to approve
Some(AllMessages::DisputeCoordinator(
DisputeCoordinatorMessage::IssueLocalStatement(
Expand All @@ -89,9 +99,27 @@ where
}
}
}
pub(crate) struct DisputeValidCandidates {
/// Backing configuration.
fake_backing_validation: Option<FakeCandidateValidation>,
/// Approval voting configuration (applies to disputes as well).
fake_approval_validation: Option<FakeCandidateValidation>,
}

/// Generates an overseer that disputes instead of approving valid candidates.
pub(crate) struct DisputeValidCandidates;
impl Default for DisputeValidCandidates {
fn default() -> Self {
Self { fake_backing_validation: None, fake_approval_validation: None }
}
}

impl DisputeValidCandidates {
pub fn new(
fake_backing_validation: Option<FakeCandidateValidation>,
fake_approval_validation: Option<FakeCandidateValidation>,
) -> Self {
Self { fake_backing_validation, fake_approval_validation }
}
}

impl OverseerGen for DisputeValidCandidates {
fn generate<'a, Spawner, RuntimeClient>(
Expand All @@ -106,13 +134,32 @@ impl OverseerGen for DisputeValidCandidates {
{
let spawner = args.spawner.clone();
let crypto_store_ptr = args.keystore.clone() as SyncCryptoStorePtr;
let filter = ReplaceApprovalsWithDisputes;
let backing_filter = ReplaceApprovalsWithDisputes;
let validation_filter = ReplaceValidationResult::new(
self.fake_backing_validation.clone(),
self.fake_approval_validation.clone(),
);
let candidate_validation_config = args.candidate_validation_config.clone();

prepared_overseer_builder(args)?
.replace_candidate_backing(move |cb| {
.replace_candidate_backing(move |cb_subsystem| {
InterceptedSubsystem::new(
CandidateBackingSubsystem::new(
spawner,
crypto_store_ptr,
cb_subsystem.params.metrics,
),
backing_filter,
)
})
.replace_candidate_validation(move |cv_subsystem| {
InterceptedSubsystem::new(
CandidateBackingSubsystem::new(spawner, crypto_store_ptr, cb.params.metrics),
filter,
CandidateValidationSubsystem::with_config(
candidate_validation_config,
cv_subsystem.metrics,
cv_subsystem.pvf_metrics,
),
validation_filter,
)
})
.build_with_connector(connector)
Expand Down
2 changes: 2 additions & 0 deletions node/malus/src/variants/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
//! Collection of behavior variants.

mod back_garbage_candidate;
mod common;
mod dispute_valid_candidates;
mod suggest_garbage_candidate;

pub(crate) use self::{
back_garbage_candidate::BackGarbageCandidate, dispute_valid_candidates::DisputeValidCandidates,
suggest_garbage_candidate::SuggestGarbageCandidate,
};
pub(crate) use common::ReplaceValidationResult;