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

Malus: add disputed block percentage #6100

Merged
merged 52 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
ed18805
Malus: add disputed block percentage
bredamatt Oct 4, 2022
1eb3844
Cleanup tests
bredamatt Oct 4, 2022
f46e97c
* Replace unwrap with expect and meaningful error message
bredamatt Oct 4, 2022
99bc912
* Remove Inner
bredamatt Oct 4, 2022
a259272
* Rename sampled variable
bredamatt Oct 6, 2022
f371e5e
* Add percentage option to dispute_ancestor
bredamatt Oct 6, 2022
f3dca67
* Support static probability for `ReplaceValidationResult` proxy
bredamatt Oct 7, 2022
d08d405
* Add `--percentage` to `back-garbage-candidate` variant
bredamatt Oct 7, 2022
e9a1b3e
* Add probabilistic behavior to `dispute-ancestor` variant
bredamatt Oct 7, 2022
4fff00b
* More descriptive comments
bredamatt Oct 7, 2022
bfe0aa7
* cargo +nightly fmt --all
bredamatt Oct 7, 2022
4704e98
* Move Bernoulli distributrion to ReplaceValidationResult constructor
bredamatt Oct 7, 2022
0ec9bc1
* Remove dangling comment
bredamatt Oct 7, 2022
563fa17
* Consistent log
bredamatt Oct 7, 2022
f789958
* Add logs based on sampled value
bredamatt Oct 7, 2022
decb9e2
* Cargo +nightly fmt --all
bredamatt Oct 7, 2022
3ad5cec
* Remove unused percentage attributed after moving Bernoulli to const…
bredamatt Oct 10, 2022
5001fa5
Squashed commit of the following:
bredamatt Oct 10, 2022
b6e446e
Revert "Squashed commit of the following:"
bredamatt Oct 10, 2022
0a4d2b9
Companion for BEEFY: Simplify hashing for pallet-beefy-mmr (#6098)
serban300 Oct 4, 2022
dffb976
Keep sessions in window for the full unfinalized chain (#6054)
sandreim Oct 4, 2022
89d1f31
Bump lru from 0.7.8 to 0.8.0 (#6060)
dependabot[bot] Oct 4, 2022
b012597
Batch vote import in dispute-distribution (#5894)
eskimor Oct 4, 2022
2fd74d9
Add unknown words (#6105)
eskimor Oct 4, 2022
7e89bab
Buffered connection management for collator-protocol (#6022)
slumber Oct 5, 2022
c169279
Properly migrate weights to v2 (#6091)
KiChjang Oct 5, 2022
233c158
Pass through `runtime-benchmark` feature (#6110)
athei Oct 5, 2022
1655839
Companion for #11649: Bound uses of `Call` (#5729)
gavofyork Oct 5, 2022
e2a977a
update kvdb & co (#6111)
ordian Oct 5, 2022
4a6cf48
Skip `unexpected metric type`
bkontur Oct 6, 2022
78b8294
service: use MmrRootProvider as custom BEEFY payload provider (compan…
acatangiu Oct 6, 2022
82f7ad5
Maximum value for `MultiplierUpdate` (#6021)
Szegoo Oct 6, 2022
978d87f
Companion for upgrading pin-project (#6118)
bkchr Oct 7, 2022
0717246
Companion for 12109 (#5929)
Lezek123 Oct 9, 2022
1e96dfd
Add event to asset claim (#6029)
girazoki Oct 10, 2022
857e635
Fix flaky test (#6131)
slumber Oct 10, 2022
96185c3
ci/guide: install mdbook-graphviz (#6119)
ordian Oct 10, 2022
612302c
Revert "Squashed commit of the following:"
bredamatt Oct 10, 2022
35af7ad
Merge branch 'master' of github.com:paritytech/polkadot into bredamat…
bredamatt Oct 10, 2022
cf3f453
* Remove unused imports
bredamatt Oct 10, 2022
f1440e7
* cargo +nightly fmt --all
bredamatt Oct 10, 2022
6f54587
Make tweaks based on PR comments
bredamatt Oct 11, 2022
9842ee9
unit test related to gum formatting
bredamatt Oct 11, 2022
56347c6
cargo +nightly fmt --all
bredamatt Oct 11, 2022
4a7dd91
Merge branch 'master' of github.com:paritytech/polkadot into bredamat…
bredamatt Oct 12, 2022
72591a9
Resolve merge conflicts
bredamatt Oct 12, 2022
23d9498
cargo +nightly fmt --all
bredamatt Oct 12, 2022
be1f5a9
Fix tests so they use cli rather than cmd
bredamatt Oct 12, 2022
cdc68c4
CI unused import check fix
bredamatt Oct 12, 2022
dd96c47
Move info! log to startup
bredamatt Oct 12, 2022
5c20d8c
make info log more comprehensible
bredamatt Oct 12, 2022
7529e94
Merge branch 'master' of github.com:paritytech/polkadot into bredamat…
bredamatt Oct 13, 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
Prev Previous commit
Next Next commit
* Add probabilistic behavior to dispute-ancestor variant
* Add probabilistic behavior to `back-garbage-candidate` variant
* Rename structs in dispute variant
  • Loading branch information
bredamatt committed Oct 7, 2022
commit e9a1b3ec6054a45f9e93778f21f80db33fca37c6
156 changes: 120 additions & 36 deletions node/malus/src/variants/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ use polkadot_primitives::v2::{

use futures::channel::oneshot;

use rand::distributions::{Bernoulli, Distribution};

#[derive(clap::ArgEnum, Clone, Copy, Debug, PartialEq)]
#[clap(rename_all = "kebab-case")]
#[non_exhaustive]
Expand Down Expand Up @@ -109,6 +111,7 @@ impl Into<InvalidCandidate> for FakeCandidateValidationError {
pub struct ReplaceValidationResult<Spawner> {
fake_validation: FakeCandidateValidation,
fake_validation_error: FakeCandidateValidationError,
percentage: f64,
spawner: Spawner,
}

Expand All @@ -119,9 +122,10 @@ where
pub fn new(
fake_validation: FakeCandidateValidation,
fake_validation_error: FakeCandidateValidationError,
percentage: f64,
spawner: Spawner,
) -> Self {
Self { fake_validation, fake_validation_error, spawner }
Self { fake_validation, fake_validation_error, percentage, spawner }
}

/// Creates and sends the validation response for a given candidate. Queries the runtime to obtain the validation data for the
Expand Down Expand Up @@ -202,13 +206,14 @@ where
{
type Message = CandidateValidationMessage;

// Capture all candidate validation requests and depending on configuration fail them.
// Capture all (approval and backing) candidate validation requests and depending on configuration fail them.
fn intercept_incoming(
&self,
subsystem_sender: &mut Sender,
msg: FromOrchestra<Self::Message>,
) -> Option<FromOrchestra<Self::Message>> {
match msg {
// Behaviour related to the approval subsystem
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
FromOrchestra::Communication {
msg:
CandidateValidationMessage::ValidateFromExhaustive(
Expand Down Expand Up @@ -236,28 +241,70 @@ where
),
})
}
create_validation_response(
validation_data,
candidate_receipt.descriptor,
sender,
);
None
// Create the fake response with probability `p` if the `PoV` is malicious.
let distribution = Bernoulli::new(self.percentage / 100.0).expect("Invalid probability! Percentage cannot be < 0 or > 100.");
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
let random_bool = distribution.sample(&mut rand::thread_rng());
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
match random_bool {
true => {
create_validation_response(
validation_data,
candidate_receipt.descriptor,
sender,
);
None
},
//
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
false => {
// Behave normally with probability `(1-p)` for a malicious `PoV`.
Some(FromOrchestra::Communication {
msg: CandidateValidationMessage::ValidateFromExhaustive(
validation_data,
validation_code,
candidate_receipt,
pov,
timeout,
sender,
),
})
}
}
},
FakeCandidateValidation::ApprovalInvalid |
FakeCandidateValidation::BackingAndApprovalInvalid => {
let validation_result =
ValidationResult::Invalid(InvalidCandidate::InvalidOutputs);
// Set the validation result to invalid with probability `p`
let distribution = Bernoulli::new(self.percentage / 100.0).expect("Invalid probability! Percentage cannot be < 0 or > 100.");
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
let random_bool = distribution.sample(&mut rand::thread_rng());
match random_bool {
true => {
let validation_result =
ValidationResult::Invalid(InvalidCandidate::InvalidOutputs);

gum::debug!(
target: MALUS,
para_id = ?candidate_receipt.descriptor.para_id,
"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
gum::debug!(
target: MALUS,
para_id = ?candidate_receipt.descriptor.para_id,
"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
},
false => {
// Behave normally with probability `(1-p)`
Some(FromOrchestra::Communication {
msg: CandidateValidationMessage::ValidateFromExhaustive(
validation_data,
validation_code,
candidate_receipt,
pov,
timeout,
sender,
),
})
},
}
},
// `dispute-ancestor --fake-validation` disabled case
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
_ => Some(FromOrchestra::Communication {
msg: CandidateValidationMessage::ValidateFromExhaustive(
validation_data,
Expand All @@ -270,6 +317,7 @@ where
}),
}
},
// Behaviour related to the backing subsystem
FromOrchestra::Communication {
msg:
CandidateValidationMessage::ValidateFromChainState(
Expand All @@ -293,27 +341,63 @@ where
),
})
}
self.send_validation_response(
candidate_receipt.descriptor,
subsystem_sender.clone(),
response_sender,
);
None
// If the `PoV` is malicious, back the candidate with some probability `p` (default 100)
let distribution = Bernoulli::new(self.percentage / 100.0).expect("Invalid probability! Percentage cannot be < 0 or > 100.");
let random_bool = distribution.sample(&mut rand::thread_rng());
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
match random_bool {
true => {
self.send_validation_response(
candidate_receipt.descriptor,
subsystem_sender.clone(),
response_sender,
);
None
},
// If the `PoV` is malicious, we behave normally with some probability `(1-p)` (default 0)
false => {
Some(FromOrchestra::Communication {
msg: CandidateValidationMessage::ValidateFromChainState(
candidate_receipt,
pov,
timeout,
response_sender,
),
})
}
}
},
FakeCandidateValidation::BackingInvalid |
FakeCandidateValidation::BackingAndApprovalInvalid => {
let validation_result =
ValidationResult::Invalid(self.fake_validation_error.clone().into());
gum::debug!(
target: MALUS,
para_id = ?candidate_receipt.descriptor.para_id,
"ValidateFromChainState result: {:?}",
&validation_result
);
// We back a garbage candidate with some probability `p` (default 100)
let distribution = Bernoulli::new(self.percentage / 100.0).expect("Invalid probability! Percentage cannot be < 0 or > 100.");
let random_bool = distribution.sample(&mut rand::thread_rng());
match random_bool {
true => {
let validation_result =
ValidationResult::Invalid(self.fake_validation_error.clone().into());
gum::debug!(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd merge this into the info log from above.

target: MALUS,
para_id = ?candidate_receipt.descriptor.para_id,
"ValidateFromChainState result: {:?}",
&validation_result
);

// We're not even checking the candidate, this makes us appear faster than honest validators.
response_sender.send(Ok(validation_result)).unwrap();
None
// We're not even checking the candidate, this makes us appear faster than honest validators.
response_sender.send(Ok(validation_result)).unwrap();
None
},
// With some probability `(1-p)` (default 0) we behave normally
false => {
Some(FromOrchestra::Communication {
bredamatt marked this conversation as resolved.
Show resolved Hide resolved
msg: CandidateValidationMessage::ValidateFromChainState(
candidate_receipt,
pov,
timeout,
response_sender,
),
})
},
}
},
_ => Some(FromOrchestra::Communication {
msg: CandidateValidationMessage::ValidateFromChainState(
Expand Down
7 changes: 4 additions & 3 deletions node/malus/src/variants/dispute_valid_candidates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,18 @@ pub struct DisputeAncestorOptions {
pub cmd: RunCmd,
}

pub(crate) struct DisputeValidCandidates {
pub(crate) struct DisputeValidCandidateWrapper {
/// Fake validation config (applies to disputes as well).
opts: DisputeAncestorOptions,
}

impl DisputeValidCandidates {
impl DisputeValidCandidateWrapper {
pub fn new(opts: DisputeAncestorOptions) -> Self {
Self { opts }
}
}

impl OverseerGen for DisputeValidCandidates {
impl OverseerGen for DisputeValidCandidateWrapper {
fn generate<'a, Spawner, RuntimeClient>(
&self,
connector: OverseerConnector,
Expand All @@ -90,6 +90,7 @@ impl OverseerGen for DisputeValidCandidates {
let validation_filter = ReplaceValidationResult::new(
self.opts.fake_validation,
self.opts.fake_validation_error,
f64::from(self.opts.percentage),
SpawnGlue(spawner.clone()),
);

Expand Down