Commit 139ecf90 authored by Bernhard Schuster's avatar Bernhard Schuster
Browse files

fix order, add dispute-unavailable-block malus

parent 970647f3
Pipeline #154895 canceled with stages
in 3 minutes and 7 seconds
......@@ -6,21 +6,21 @@ timeout = 1000
[nodes.alice]
validator = true
extra-args = ["--alice"]
image = "{{get_env(name="SYNTHIMAGE") | safe }}"
command = "polkadot"
extra-args = ["--alice"]
[nodes.bob]
validator = true
extra-args = ["--bob"]
image = "{{get_env(name="SYNTHIMAGE") | safe }}"
command = "polkadot"
extra-args = ["--bob"]
[nodes.charlie]
validator = true
extra-args = ["--charlie"]
image = "{{get_env(name="SYNTHIMAGE") | safe }}"
command = "polkadot"
extra-args = ["--charlie"]
[nodes.david]
validator = true
......
......@@ -6,30 +6,30 @@ timeout = 1000
[nodes.alice]
validator = true
extra-args = ["--alice"]
image = "{{get_env(name="SYNTHIMAGE") | safe }}"
command = "polkadot"
extra-args = ["--alice"]
[nodes.bob]
validator = true
extra-args = ["back-garbage-candidate", "--bob"]
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["back-garbage-candidate", "--bob"]
[nodes.charlie]
validator = true
extra-args = ["back-garbage-candidate", "--charlie"]
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["back-garbage-candidate", "--charlie"]
[nodes.david]
validator = true
extra-args = ["back-garbage-candidate", "--dave"]
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["back-garbage-candidate", "--dave"]
[nodes.eve]
validator = true
extra-args = ["suggest-garbage-candidate","--eve"]
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["suggest-garbage-candidate","--eve"]
Feature: Disputes
Scenario: Dispute Invalid Block
Given a test network
Then alice is up
And alice reports node_roles is 4
And alice reports sub_libp2p_is_major_syncing is 0
Then sleep 15 seconds
Then alice reports block height is greater than 2
And alice reports peers count is at least 2
Then bob is up
And bob reports block height is greater than 2
And bob reports peers count is at least 2
Then charlie is up
And charlie reports block height is greater than 2
And charlie reports peers count is at least 2
Then david is up
Then eve is up
And alice reports polkadot_parachain_candidate_open_disputes is 1
Then alice polkadot_parachain_candidate_dispute_votes is at least 1
And bob polkadot_parachain_candidate_dispute_votes is is at least 2
And charlie polkadot_parachain_candidate_dispute_votes is at least 3
And david polkadot_parachain_candidate_dispute_votes is at least 4
Then alice polkadot_parachain_candidate_dispute_concluded is "invalid"
[settings.defaults]
image = "{{get_env(name="SYNTHIMAGE") | safe }}"
command = "polkadot"
chain-name = "polkadot-local"
timeout = 1000
[nodes.alice]
validator = true
image = "{{get_env(name="SYNTHIMAGE") | safe }}"
command = "polkadot"
extra-args = ["--alice"]
[nodes.bob]
validator = true
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["back-garbage-candidate", "--bob"]
[nodes.charlie]
validator = true
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["back-garbage-candidate", "--charlie"]
[nodes.david]
validator = true
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["back-garbage-candidate", "--dave"]
[nodes.eve]
validator = true
image = "{{get_env(name="MALUSIMAGE") | safe }}"
command = "/usr/local/bin/malus"
extra-args = ["suggest-garbage-candidate","--eve"]
......@@ -38,6 +38,8 @@ enum NemesisVariant {
BackGarbageCandidate(RunCmd),
/// Delayed disputing of ancestors that are perfectly fine.
DisputeAncestor(RunCmd),
/// Instant disputing of a block that was never made available.
DisputeUnavailable(RunCmd),
}
#[derive(Debug, StructOpt)]
......@@ -56,6 +58,7 @@ impl MalusCli {
NemesisVariant::SuggestGarabageCandidate(run) =>
polkadot_cli::run_node(run, SuggestGarbageCandidate)?,
NemesisVariant::DisputeAncestor(run) => polkadot_cli::run_node(run, DisputeAncestor)?,
NemesisVariant::DisputeUnavailable(run) => polkadot_cli::run_node(run, DisputeUnavailable)?,
}
Ok(())
}
......
// Copyright 2021 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/>.
//! A malicious overseer that always disputes a block as
//! as it is observed.
//!
//! Attention: For usage with `simnet`/`gurke` only!
#![allow(missing_docs)]
use polkadot_cli::{
create_default_subsystems,
service::{
AuthorityDiscoveryApi, AuxStore, BabeApi, Block, Error, HeaderBackend, Overseer,
OverseerGen, OverseerGenArgs, OverseerHandle, ParachainHost, ProvideRuntimeApi, SpawnNamed,
},
};
// Filter wrapping related types.
use crate::{interceptor::*, shared::*};
use polkadot_node_subsystem::overseer::SubsystemSender;
// Import extra types relevant to the particular
// subsystem.
use polkadot_node_core_backing::{CandidateBackingSubsystem, Metrics as CandidateBackingMetrics};
use polkadot_node_subsystem::messages::{CandidateBackingMessage, DisputeCoordinatorMessage};
use polkadot_node_subsystem_util as util;
use polkadot_primitives::v1::CandidateReceipt;
use sp_keystore::SyncCryptoStorePtr;
use util::{metered, metrics::Metrics as _};
use std::sync::Arc;
/// Become Loki and throw in a dispute once in a while, for an unfinalized block.
#[derive(Clone, Debug)]
struct TrackCollations<Sender>
where
Sender: Send,
{
sink: metered::UnboundedMeteredSender<(Sender, CandidateReceipt)>,
}
impl<Sender> MessageInterceptor<Sender> for TrackCollations<Sender>
where
Sender: overseer::SubsystemSender<CandidateBackingMessage> + Clone + Send + 'static,
{
type Message = CandidateBackingMessage;
fn intercept_incoming(
&self,
sender: &mut Sender,
msg: FromOverseer<Self::Message>,
) -> Option<FromOverseer<Self::Message>> {
match msg {
FromOverseer::Communication {
// `DistributeCollation` is only received
// by a _collator_, but we are a validator.
// `CollatorProtocolMessage::DistributeCollation(ref ccr, ref pov, _)` hence
// cannot be used.
// Intercepting [`fn request_collation`](https://github.com/paritytech/polkadot/blob/117466aa8e471562f921a90b69a6c265cb6c656f/node/network/collator-protocol/src/validator_side/mod.rs#L736-L736)
// is bothersome, so we wait for the seconding and
// make that disappear, and instead craft our own message.
msg: CandidateBackingMessage::Second(_, ccr, _),
} => {
self.sink.unbounded_send((sender.clone(), ccr)).unwrap();
None
},
msg => Some(msg),
}
}
fn intercept_outgoing(&self, msg: AllMessages) -> Option<AllMessages> {
Some(msg)
}
}
/// Generates an overseer that disputes every ancestor.
pub(crate) struct DisputeUnavailable;
impl OverseerGen for DisputeUnavailable {
fn generate<'a, Spawner, RuntimeClient>(
&self,
args: OverseerGenArgs<'a, Spawner, RuntimeClient>,
) -> Result<(Overseer<Spawner, Arc<RuntimeClient>>, OverseerHandle), Error>
where
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block> + AuxStore,
RuntimeClient::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
Spawner: 'static + SpawnNamed + Clone + Unpin,
{
let spawner = args.spawner.clone();
let leaves = args.leaves.clone();
let runtime_client = args.runtime_client.clone();
let registry = args.registry.clone();
let (sink, source) = metered::unbounded();
let coll = TrackCollations { sink };
let metrics = CandidateBackingMetrics::register(registry).unwrap();
let crypto_store_ptr = args.keystore.clone() as SyncCryptoStorePtr;
// modify the subsystem(s) as needed:
let all_subsystems = create_default_subsystems(args)?.replace_candidate_backing(
// create the filtered subsystem
FilteredSubsystem::new(
CandidateBackingSubsystem::new(spawner.clone(), crypto_store_ptr, metrics),
coll,
),
);
let (overseer, handle) =
Overseer::new(leaves, all_subsystems, registry, runtime_client, spawner.clone())?;
launch_processing_task(
&spawner,
source,
|(mut subsystem_sender, candidate_receipt): (_, CandidateReceipt)| async move {
let relay_parent = candidate_receipt.descriptor().relay_parent;
let session_index =
util::request_session_index_for_child(relay_parent, &mut subsystem_sender)
.await;
let session_index = session_index.await.unwrap().unwrap();
let candidate_hash = candidate_receipt.hash();
tracing::warn!(
target = MALUS,
"Disputing unvailable block with candidate /w hash {} in session {:?} on relay_parent {}",
candidate_hash,
session_index,
relay_parent,
);
// no delay, dispute right away, before it becomes available
// 😈
let msg = DisputeCoordinatorMessage::IssueLocalStatement(
session_index,
candidate_hash,
candidate_receipt,
false,
);
subsystem_sender.send_message(msg).await;
},
);
Ok((overseer, handle))
}
}
......@@ -19,8 +19,10 @@
mod back_garbage_candidate;
mod dispute_ancestor;
mod suggest_garbage_candidate;
mod dispute_unavailable_block;
pub(crate) use self::{
back_garbage_candidate::BackGarbageCandidate, dispute_ancestor::DisputeAncestor,
suggest_garbage_candidate::SuggestGarbageCandidate,
dispute_unavailable_block::DisputeUnavailable,
};
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment