mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 09:51:10 +00:00
safe multi-era slashing for NPoS (#3846)
* define slashing spans * tests and pruning for slashing-spans record * validators get slashed before nominators * apply slash to nominators as well * chill and end slashing spans * actually perform slashes * integration (tests failing) * prune metadata * fix compilation * some tests for slashing and metadata garbage collection * correctly pass session index to slash handler * test span-max property for nominators and validators * test that slashes are summed correctly * reward value computation * implement rewarding * add comment about rewards * do not adjust slash fraction in offences module * fix offences tests * remove unused new_offenders field * update runtime version * fix up some docs * fix some CI failures * remove no-std incompatible vec! invocation * try to fix span-max rounding error * Update srml/staking/src/slashing.rs Fix type: winow -> window Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com> * slashes from prior spans don't kick validator again * more information for nominators, suppression * ensure ledger is consistent with itself post-slash * implement slash out of unlocking funds also * slashing: create records to be applied after-the-fact * queue slashes for a few eras later * method for canceling deferred slashes * attempt to fix test in CI * storage migration for `Nominators` * update node-runtime to use SlashDeferDuration * adjust migration entry-points somewhat * fix migration compilation * add manual Vec import to migration * enable migrations feature in node-runtime * bump runtime version * update to latest master crate renames * update to use ensure-origin * Apply suggestions from code review use `ensure!` Co-Authored-By: Gavin Wood <gavin@parity.io> * fix multi-slash removal * initialize storage version to current in genesis * add test for version initialization
This commit is contained in:
committed by
Gavin Wood
parent
de5686509c
commit
4598e13015
@@ -24,17 +24,11 @@
|
||||
mod mock;
|
||||
mod tests;
|
||||
|
||||
use rstd::{
|
||||
vec::Vec,
|
||||
collections::btree_set::BTreeSet,
|
||||
};
|
||||
use rstd::vec::Vec;
|
||||
use support::{
|
||||
decl_module, decl_event, decl_storage, Parameter,
|
||||
};
|
||||
use sr_primitives::{
|
||||
Perbill,
|
||||
traits::{Hash, Saturating},
|
||||
};
|
||||
use sr_primitives::traits::Hash;
|
||||
use sr_staking_primitives::{
|
||||
offence::{Offence, ReportOffence, Kind, OnOffenceHandler, OffenceDetails},
|
||||
};
|
||||
@@ -100,10 +94,11 @@ where
|
||||
|
||||
// Go through all offenders in the offence report and find all offenders that was spotted
|
||||
// in unique reports.
|
||||
let TriageOutcome {
|
||||
new_offenders,
|
||||
concurrent_offenders,
|
||||
} = match Self::triage_offence_report::<O>(reporters, &time_slot, offenders) {
|
||||
let TriageOutcome { concurrent_offenders } = match Self::triage_offence_report::<O>(
|
||||
reporters,
|
||||
&time_slot,
|
||||
offenders,
|
||||
) {
|
||||
Some(triage) => triage,
|
||||
// The report contained only duplicates, so there is no need to slash again.
|
||||
None => return,
|
||||
@@ -113,44 +108,18 @@ where
|
||||
Self::deposit_event(Event::Offence(O::ID, time_slot.encode()));
|
||||
|
||||
let offenders_count = concurrent_offenders.len() as u32;
|
||||
let previous_offenders_count = offenders_count - new_offenders.len() as u32;
|
||||
|
||||
// The amount new offenders are slashed
|
||||
let new_fraction = O::slash_fraction(offenders_count, validator_set_count);
|
||||
|
||||
// The amount previous offenders are slashed additionally.
|
||||
//
|
||||
// Since they were slashed in the past, we slash by:
|
||||
// x = (new - prev) / (1 - prev)
|
||||
// because:
|
||||
// Y = X * (1 - prev)
|
||||
// Z = Y * (1 - x)
|
||||
// Z = X * (1 - new)
|
||||
let old_fraction = if previous_offenders_count > 0 {
|
||||
let previous_fraction = O::slash_fraction(
|
||||
offenders_count.saturating_sub(previous_offenders_count),
|
||||
validator_set_count,
|
||||
);
|
||||
let numerator = new_fraction.saturating_sub(previous_fraction);
|
||||
let denominator = Perbill::one().saturating_sub(previous_fraction);
|
||||
denominator.saturating_mul(numerator)
|
||||
} else {
|
||||
new_fraction.clone()
|
||||
};
|
||||
let slash_perbill: Vec<_> = (0..concurrent_offenders.len())
|
||||
.map(|_| new_fraction.clone()).collect();
|
||||
|
||||
// calculate how much to slash
|
||||
let slash_perbill = concurrent_offenders
|
||||
.iter()
|
||||
.map(|details| {
|
||||
if previous_offenders_count > 0 && new_offenders.contains(&details.offender) {
|
||||
new_fraction.clone()
|
||||
} else {
|
||||
old_fraction.clone()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
T::OnOffenceHandler::on_offence(&concurrent_offenders, &slash_perbill);
|
||||
T::OnOffenceHandler::on_offence(
|
||||
&concurrent_offenders,
|
||||
&slash_perbill,
|
||||
offence.session_index(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,13 +142,13 @@ impl<T: Trait> Module<T> {
|
||||
offenders: Vec<T::IdentificationTuple>,
|
||||
) -> Option<TriageOutcome<T>> {
|
||||
let mut storage = ReportIndexStorage::<T, O>::load(time_slot);
|
||||
let mut new_offenders = BTreeSet::new();
|
||||
|
||||
let mut any_new = false;
|
||||
for offender in offenders {
|
||||
let report_id = Self::report_id::<O>(time_slot, &offender);
|
||||
|
||||
if !<Reports<T>>::exists(&report_id) {
|
||||
new_offenders.insert(offender.clone());
|
||||
any_new = true;
|
||||
<Reports<T>>::insert(
|
||||
&report_id,
|
||||
OffenceDetails {
|
||||
@@ -192,7 +161,7 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
}
|
||||
|
||||
if !new_offenders.is_empty() {
|
||||
if any_new {
|
||||
// Load report details for the all reports happened at the same time.
|
||||
let concurrent_offenders = storage.concurrent_reports
|
||||
.iter()
|
||||
@@ -202,7 +171,6 @@ impl<T: Trait> Module<T> {
|
||||
storage.save();
|
||||
|
||||
Some(TriageOutcome {
|
||||
new_offenders,
|
||||
concurrent_offenders,
|
||||
})
|
||||
} else {
|
||||
@@ -212,8 +180,6 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
struct TriageOutcome<T: Trait> {
|
||||
/// Offenders that was spotted in the unique reports.
|
||||
new_offenders: BTreeSet<T::IdentificationTuple>,
|
||||
/// Other reports for the same report kinds.
|
||||
concurrent_offenders: Vec<OffenceDetails<T::AccountId, T::IdentificationTuple>>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user