mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
Offences Weight for OnInitialize (#5961)
* Weight accounting for on_offence. * Try to compute weight. * Guesstimate upper bounds on db read/writes for slashing * greater than or equal to * add new trait * Update mock.rs * Add basic weight test * one more test * Update frame/staking/src/lib.rs Co-authored-by: thiolliere <gui.thiolliere@gmail.com> * Update frame/staking/src/lib.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Add test for offences queue Co-authored-by: Tomasz Drwięga <tomasz@parity.io> Co-authored-by: thiolliere <gui.thiolliere@gmail.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
@@ -3218,7 +3218,9 @@ impl<T: Trait> Convert<T::AccountId, Option<Exposure<T::AccountId, BalanceOf<T>>
|
||||
}
|
||||
|
||||
/// This is intended to be used with `FilterHistoricalOffences`.
|
||||
impl <T: Trait> OnOffenceHandler<T::AccountId, pallet_session::historical::IdentificationTuple<T>> for Module<T> where
|
||||
impl <T: Trait>
|
||||
OnOffenceHandler<T::AccountId, pallet_session::historical::IdentificationTuple<T>, Weight>
|
||||
for Module<T> where
|
||||
T: pallet_session::Trait<ValidatorId = <T as frame_system::Trait>::AccountId>,
|
||||
T: pallet_session::historical::Trait<
|
||||
FullIdentification = Exposure<<T as frame_system::Trait>::AccountId, BalanceOf<T>>,
|
||||
@@ -3226,24 +3228,32 @@ impl <T: Trait> OnOffenceHandler<T::AccountId, pallet_session::historical::Ident
|
||||
>,
|
||||
T::SessionHandler: pallet_session::SessionHandler<<T as frame_system::Trait>::AccountId>,
|
||||
T::SessionManager: pallet_session::SessionManager<<T as frame_system::Trait>::AccountId>,
|
||||
T::ValidatorIdOf: Convert<<T as frame_system::Trait>::AccountId, Option<<T as frame_system::Trait>::AccountId>>
|
||||
T::ValidatorIdOf: Convert<
|
||||
<T as frame_system::Trait>::AccountId,
|
||||
Option<<T as frame_system::Trait>::AccountId>,
|
||||
>,
|
||||
{
|
||||
fn on_offence(
|
||||
offenders: &[OffenceDetails<T::AccountId, pallet_session::historical::IdentificationTuple<T>>],
|
||||
slash_fraction: &[Perbill],
|
||||
slash_session: SessionIndex,
|
||||
) -> Result<(), ()> {
|
||||
) -> Result<Weight, ()> {
|
||||
if !Self::can_report() {
|
||||
return Err(())
|
||||
}
|
||||
|
||||
let reward_proportion = SlashRewardFraction::get();
|
||||
let mut consumed_weight: Weight = 0;
|
||||
let mut add_db_reads_writes = |reads, writes| {
|
||||
consumed_weight += T::DbWeight::get().reads_writes(reads, writes);
|
||||
};
|
||||
|
||||
let active_era = {
|
||||
let active_era = Self::active_era();
|
||||
add_db_reads_writes(1, 0);
|
||||
if active_era.is_none() {
|
||||
// this offence need not be re-submitted.
|
||||
return Ok(())
|
||||
return Ok(consumed_weight)
|
||||
}
|
||||
active_era.expect("value checked not to be `None`; qed").index
|
||||
};
|
||||
@@ -3252,6 +3262,7 @@ impl <T: Trait> OnOffenceHandler<T::AccountId, pallet_session::historical::Ident
|
||||
frame_support::print("Error: start_session_index must be set for current_era");
|
||||
0
|
||||
});
|
||||
add_db_reads_writes(1, 0);
|
||||
|
||||
let window_start = active_era.saturating_sub(T::BondingDuration::get());
|
||||
|
||||
@@ -3261,11 +3272,13 @@ impl <T: Trait> OnOffenceHandler<T::AccountId, pallet_session::historical::Ident
|
||||
active_era
|
||||
} else {
|
||||
let eras = BondedEras::get();
|
||||
add_db_reads_writes(1, 0);
|
||||
|
||||
// reverse because it's more likely to find reports from recent eras.
|
||||
match eras.iter().rev().filter(|&&(_, ref sesh)| sesh <= &slash_session).next() {
|
||||
None => return Ok(()), // before bonding period. defensive - should be filtered out.
|
||||
Some(&(ref slash_era, _)) => *slash_era,
|
||||
// before bonding period. defensive - should be filtered out.
|
||||
None => return Ok(consumed_weight),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3274,14 +3287,18 @@ impl <T: Trait> OnOffenceHandler<T::AccountId, pallet_session::historical::Ident
|
||||
*earliest = Some(active_era)
|
||||
}
|
||||
});
|
||||
add_db_reads_writes(1, 1);
|
||||
|
||||
let slash_defer_duration = T::SlashDeferDuration::get();
|
||||
|
||||
let invulnerables = Self::invulnerables();
|
||||
add_db_reads_writes(1, 0);
|
||||
|
||||
for (details, slash_fraction) in offenders.iter().zip(slash_fraction) {
|
||||
let (stash, exposure) = &details.offender;
|
||||
|
||||
// Skip if the validator is invulnerable.
|
||||
if Self::invulnerables().contains(stash) {
|
||||
if invulnerables.contains(stash) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -3296,21 +3313,40 @@ impl <T: Trait> OnOffenceHandler<T::AccountId, pallet_session::historical::Ident
|
||||
});
|
||||
|
||||
if let Some(mut unapplied) = unapplied {
|
||||
let nominators_len = unapplied.others.len() as u64;
|
||||
let reporters_len = details.reporters.len() as u64;
|
||||
|
||||
{
|
||||
let upper_bound = 1 /* Validator/NominatorSlashInEra */ + 2 /* fetch_spans */;
|
||||
let rw = upper_bound + nominators_len * upper_bound;
|
||||
add_db_reads_writes(rw, rw);
|
||||
}
|
||||
unapplied.reporters = details.reporters.clone();
|
||||
if slash_defer_duration == 0 {
|
||||
// apply right away.
|
||||
slashing::apply_slash::<T>(unapplied);
|
||||
{
|
||||
let slash_cost = (6, 5);
|
||||
let reward_cost = (2, 2);
|
||||
add_db_reads_writes(
|
||||
(1 + nominators_len) * slash_cost.0 + reward_cost.0 * reporters_len,
|
||||
(1 + nominators_len) * slash_cost.1 + reward_cost.1 * reporters_len
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// defer to end of some `slash_defer_duration` from now.
|
||||
<Self as Store>::UnappliedSlashes::mutate(
|
||||
active_era,
|
||||
move |for_later| for_later.push(unapplied),
|
||||
);
|
||||
add_db_reads_writes(1, 1);
|
||||
}
|
||||
} else {
|
||||
add_db_reads_writes(4 /* fetch_spans */, 5 /* kick_out_if_recent */)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(consumed_weight)
|
||||
}
|
||||
|
||||
fn can_report() -> bool {
|
||||
|
||||
@@ -4667,6 +4667,49 @@ fn migrate_era_should_handle_errors_2() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offences_weight_calculated_correctly() {
|
||||
ExtBuilder::default().nominate(true).build_and_execute(|| {
|
||||
// On offence with zero offenders: 4 Reads, 1 Write
|
||||
let zero_offence_weight = <Test as frame_system::Trait>::DbWeight::get().reads_writes(4, 1);
|
||||
assert_eq!(Staking::on_offence(&[], &[Perbill::from_percent(50)], 0), Ok(zero_offence_weight));
|
||||
|
||||
// On Offence with N offenders, Unapplied: 4 Reads, 1 Write + 4 Reads, 5 Writes
|
||||
let n_offence_unapplied_weight = <Test as frame_system::Trait>::DbWeight::get().reads_writes(4, 1)
|
||||
+ <Test as frame_system::Trait>::DbWeight::get().reads_writes(4, 5);
|
||||
|
||||
let offenders: Vec<OffenceDetails<<Test as frame_system::Trait>::AccountId, pallet_session::historical::IdentificationTuple<Test>>>
|
||||
= (1..10).map(|i|
|
||||
OffenceDetails {
|
||||
offender: (i, Staking::eras_stakers(Staking::active_era().unwrap().index, i)),
|
||||
reporters: vec![],
|
||||
}
|
||||
).collect();
|
||||
assert_eq!(Staking::on_offence(&offenders, &[Perbill::from_percent(50)], 0), Ok(n_offence_unapplied_weight));
|
||||
|
||||
// On Offence with one offenders, Applied
|
||||
let one_offender = [
|
||||
OffenceDetails {
|
||||
offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)),
|
||||
reporters: vec![1],
|
||||
},
|
||||
];
|
||||
|
||||
let n = 1; // Number of offenders
|
||||
let rw = 3 + 3 * n; // rw reads and writes
|
||||
let one_offence_unapplied_weight = <Test as frame_system::Trait>::DbWeight::get().reads_writes(4, 1)
|
||||
+ <Test as frame_system::Trait>::DbWeight::get().reads_writes(rw, rw)
|
||||
// One `slash_cost`
|
||||
+ <Test as frame_system::Trait>::DbWeight::get().reads_writes(6, 5)
|
||||
// `slash_cost` * nominators (1)
|
||||
+ <Test as frame_system::Trait>::DbWeight::get().reads_writes(6, 5)
|
||||
// `reward_cost` * reporters (1)
|
||||
+ <Test as frame_system::Trait>::DbWeight::get().reads_writes(2, 2);
|
||||
|
||||
assert_eq!(Staking::on_offence(&one_offender, &[Perbill::from_percent(50)], 0), Ok(one_offence_unapplied_weight));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn on_initialize_weight_is_correct() {
|
||||
ExtBuilder::default().has_stakers(false).build_and_execute(|| {
|
||||
|
||||
Reference in New Issue
Block a user