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

* Implement fake validation results

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* refactor

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* cargo lock

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spell check

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spellcheck

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* typos

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Review feedback

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* move stuff around

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* chores

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Impl valid - still wip

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fixes

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fmt

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Pull Ladi's implementation:
https://github.com/paritytech/polkadot/pull/4711

Co-authored-by: Lldenaurois <Ljdenaurois@gmail.com>
Co-authored-by: Andrei Sandu <andrei-mihail@parity.io>
Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix build

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Logs and comments

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* WIP: suggest garbage candidate + implement validation result caching

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Do commitment hash checks in candidate validation

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Minor refactor in approval, backing, dispute-coord

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Working version of suggest garbage candidate

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Dedup

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* cleanup #1

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix tests

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* remove debug leftovers

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fmt

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Accidentally commited some local test

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spellcheck

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* some more fixes

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Refactor and fix it

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* review feedback

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* typo

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* tests review feedback

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* refactor disputer

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix tests

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix zombienet disputes test

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spellcheck

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix ui tests

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix typo

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

Co-authored-by: Lldenaurois <Ljdenaurois@gmail.com>
This commit is contained in:
Andrei Sandu
2022-04-13 16:45:39 +03:00
committed by GitHub
parent a46237cebb
commit cddd5749d3
23 changed files with 921 additions and 529 deletions
@@ -15,7 +15,8 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! A malicious node that replaces approvals with invalid disputes
//! against valid candidates.
//! against valid candidates. Additionally, the malus node can be configured to
//! fake candidate validation and return a static result for candidate checking.
//!
//! Attention: For usage with `zombienet` only!
@@ -28,70 +29,44 @@ use polkadot_cli::{
OverseerConnector, OverseerGen, OverseerGenArgs, OverseerHandle, ParachainHost,
ProvideRuntimeApi, SpawnNamed,
},
RunCmd,
};
// Filter wrapping related types.
use crate::interceptor::*;
// Import extra types relevant to the particular
// subsystem.
use polkadot_node_core_backing::CandidateBackingSubsystem;
use polkadot_node_subsystem::messages::{
ApprovalDistributionMessage, CandidateBackingMessage, DisputeCoordinatorMessage,
};
use sp_keystore::SyncCryptoStorePtr;
use super::common::{FakeCandidateValidation, FakeCandidateValidationError};
use crate::{interceptor::*, variants::ReplaceValidationResult};
use std::sync::Arc;
/// Replace outgoing approval messages with disputes.
#[derive(Clone, Debug)]
struct ReplaceApprovalsWithDisputes;
#[derive(Clone, Debug, clap::Parser)]
#[clap(rename_all = "kebab-case")]
#[allow(missing_docs)]
pub struct DisputeAncestorOptions {
/// Malicious candidate validation subsystem configuration. When enabled, node PVF execution is skipped
/// during backing and/or approval and it's result can by specified by this option and `--fake-validation-error`
/// for invalid candidate outcomes.
#[clap(long, arg_enum, ignore_case = true, default_value_t = FakeCandidateValidation::BackingAndApprovalInvalid)]
pub fake_validation: FakeCandidateValidation,
impl<Sender> MessageInterceptor<Sender> for ReplaceApprovalsWithDisputes
where
Sender: overseer::SubsystemSender<CandidateBackingMessage> + Clone + Send + 'static,
{
type Message = CandidateBackingMessage;
/// Applies only when `--fake-validation` is configured to reject candidates as invalid. It allows
/// to specify the exact error to return from the malicious candidate validation subsystem.
#[clap(long, arg_enum, ignore_case = true, default_value_t = FakeCandidateValidationError::InvalidOutputs)]
pub fake_validation_error: FakeCandidateValidationError,
fn intercept_incoming(
&self,
_sender: &mut Sender,
msg: FromOverseer<Self::Message>,
) -> Option<FromOverseer<Self::Message>> {
Some(msg)
}
fn intercept_outgoing(&self, msg: AllMessages) -> Option<AllMessages> {
match msg {
AllMessages::ApprovalDistribution(ApprovalDistributionMessage::DistributeApproval(
_,
)) => {
// drop the message on the floor
None
},
AllMessages::DisputeCoordinator(DisputeCoordinatorMessage::ImportStatements {
candidate_hash,
candidate_receipt,
session,
..
}) => {
// this would also dispute candidates we were not assigned to approve
Some(AllMessages::DisputeCoordinator(
DisputeCoordinatorMessage::IssueLocalStatement(
session,
candidate_hash,
candidate_receipt,
false,
),
))
},
msg => Some(msg),
}
}
#[clap(flatten)]
pub cmd: RunCmd,
}
/// Generates an overseer that disputes instead of approving valid candidates.
pub(crate) struct DisputeValidCandidates;
pub(crate) struct DisputeValidCandidates {
/// Fake validation config (applies to disputes as well).
opts: DisputeAncestorOptions,
}
impl DisputeValidCandidates {
pub fn new(opts: DisputeAncestorOptions) -> Self {
Self { opts }
}
}
impl OverseerGen for DisputeValidCandidates {
fn generate<'a, Spawner, RuntimeClient>(
@@ -105,15 +80,15 @@ impl OverseerGen for DisputeValidCandidates {
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
let spawner = args.spawner.clone();
let crypto_store_ptr = args.keystore.clone() as SyncCryptoStorePtr;
let filter = ReplaceApprovalsWithDisputes;
let validation_filter = ReplaceValidationResult::new(
self.opts.fake_validation,
self.opts.fake_validation_error,
spawner.clone(),
);
prepared_overseer_builder(args)?
.replace_candidate_backing(move |cb| {
InterceptedSubsystem::new(
CandidateBackingSubsystem::new(spawner, crypto_store_ptr, cb.params.metrics),
filter,
)
.replace_candidate_validation(move |cv_subsystem| {
InterceptedSubsystem::new(cv_subsystem, validation_filter)
})
.build_with_connector(connector)
.map_err(|e| e.into())