Skip to content

Commit

Permalink
Remove im-online pallet from Rococo and Westend (paritytech#2265)
Browse files Browse the repository at this point in the history
Co-authored-by: ordian <write@reusable.software>
Co-authored-by: Vladimir Istyufeev <vladimir@parity.io>
  • Loading branch information
3 people authored Nov 28, 2023
1 parent e06d776 commit cd9ee20
Showing 1 changed file with 7 additions and 228 deletions.
235 changes: 7 additions & 228 deletions substrate/frame/offences/benchmarking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,32 @@ mod mock;
use sp_std::{prelude::*, vec};

use frame_benchmarking::v1::{account, benchmarks};
use frame_support::traits::{Currency, Get, ValidatorSet, ValidatorSetWithIdentification};
use frame_support::traits::{Currency, Get};
use frame_system::{Config as SystemConfig, Pallet as System, RawOrigin};

#[cfg(test)]
use sp_runtime::traits::UniqueSaturatedInto;
use sp_runtime::{
traits::{Convert, Saturating, StaticLookup},
Perbill,
};
use sp_staking::offence::{Offence, ReportOffence};
use sp_staking::offence::ReportOffence;

use pallet_babe::EquivocationOffence as BabeEquivocationOffence;
use pallet_balances::Config as BalancesConfig;
use pallet_grandpa::{
EquivocationOffence as GrandpaEquivocationOffence, TimeSlot as GrandpaTimeSlot,
};
use pallet_im_online::{Config as ImOnlineConfig, Pallet as ImOnline, UnresponsivenessOffence};
use pallet_offences::{Config as OffencesConfig, Pallet as Offences};
use pallet_session::{
historical::{Config as HistoricalConfig, IdentificationTuple},
Config as SessionConfig, SessionManager,
Config as SessionConfig, Pallet as Session, SessionManager,
};
#[cfg(test)]
use pallet_staking::Event as StakingEvent;
use pallet_staking::{
Config as StakingConfig, Exposure, IndividualExposure, MaxNominationsOf, Pallet as Staking,
RewardDestination, ValidatorPrefs,
};

const SEED: u32 = 0;

const MAX_REPORTERS: u32 = 100;
const MAX_OFFENDERS: u32 = 100;
const MAX_NOMINATORS: u32 = 100;

pub struct Pallet<T: Config>(Offences<T>);
Expand All @@ -66,7 +59,6 @@ pub trait Config:
SessionConfig
+ StakingConfig
+ OffencesConfig
+ ImOnlineConfig
+ HistoricalConfig
+ BalancesConfig
+ IdTupleConvert<Self>
Expand Down Expand Up @@ -184,220 +176,7 @@ fn make_offenders<T: Config>(
Ok((id_tuples, offenders))
}

fn make_offenders_im_online<T: Config>(
num_offenders: u32,
num_nominators: u32,
) -> Result<(Vec<pallet_im_online::IdentificationTuple<T>>, Vec<Offender<T>>), &'static str> {
Staking::<T>::new_session(0);

let mut offenders = vec![];
for i in 0..num_offenders {
let offender = create_offender::<T>(i + 1, num_nominators)?;
offenders.push(offender);
}

Staking::<T>::start_session(0);

let id_tuples = offenders
.iter()
.map(|offender| {
<
<T as ImOnlineConfig>::ValidatorSet as ValidatorSet<T::AccountId>
>::ValidatorIdOf::convert(offender.controller.clone())
.expect("failed to get validator id from account id")
})
.map(|validator_id| {
<
<T as ImOnlineConfig>::ValidatorSet as ValidatorSetWithIdentification<T::AccountId>
>::IdentificationOf::convert(validator_id.clone())
.map(|full_id| (validator_id, full_id))
.expect("failed to convert validator id to full identification")
})
.collect::<Vec<pallet_im_online::IdentificationTuple<T>>>();
Ok((id_tuples, offenders))
}

#[cfg(test)]
fn check_events<
T: Config,
I: Iterator<Item = Item>,
Item: sp_std::borrow::Borrow<<T as SystemConfig>::RuntimeEvent> + sp_std::fmt::Debug,
>(
expected: I,
) {
let events = System::<T>::events()
.into_iter()
.map(|frame_system::EventRecord { event, .. }| event)
.collect::<Vec<_>>();
let expected = expected.collect::<Vec<_>>();

fn pretty<D: sp_std::fmt::Debug>(header: &str, ev: &[D], offset: usize) {
log::info!("{}", header);
for (idx, ev) in ev.iter().enumerate() {
log::info!("\t[{:04}] {:?}", idx + offset, ev);
}
}
fn print_events<D: sp_std::fmt::Debug, E: sp_std::fmt::Debug>(
idx: usize,
events: &[D],
expected: &[E],
) {
let window = 10;
let start = idx.saturating_sub(window / 2);
let end_got = (idx + window / 2).min(events.len());
pretty("Got(window):", &events[start..end_got], start);
let end_expected = (idx + window / 2).min(expected.len());
pretty("Expected(window):", &expected[start..end_expected], start);
log::info!("---------------");
let start_got = events.len().saturating_sub(window);
pretty("Got(end):", &events[start_got..], start_got);
let start_expected = expected.len().saturating_sub(window);
pretty("Expected(end):", &expected[start_expected..], start_expected);
}

for (idx, (a, b)) in events.iter().zip(expected.iter()).enumerate() {
if a != sp_std::borrow::Borrow::borrow(b) {
print_events(idx, &events, &expected);
log::info!("Mismatch at: {}", idx);
log::info!(" Got: {:?}", b);
log::info!("Expected: {:?}", a);
if events.len() != expected.len() {
log::info!(
"Mismatching lengths. Got: {}, Expected: {}",
events.len(),
expected.len()
)
}
panic!("Mismatching events.");
}
}

if events.len() != expected.len() {
print_events(0, &events, &expected);
panic!("Mismatching lengths. Got: {}, Expected: {}", events.len(), expected.len(),)
}
}

benchmarks! {
report_offence_im_online {
let r in 1 .. MAX_REPORTERS;
// we skip 1 offender, because in such case there is no slashing
let o in 2 .. MAX_OFFENDERS;
let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::<T>::get());

// Make r reporters
let mut reporters = vec![];
for i in 0 .. r {
let reporter = account("reporter", i, SEED);
reporters.push(reporter);
}

// make sure reporters actually get rewarded
Staking::<T>::set_slash_reward_fraction(Perbill::one());

let (offenders, raw_offenders) = make_offenders_im_online::<T>(o, n)?;
let keys = ImOnline::<T>::keys();
let validator_set_count = keys.len() as u32;
let offenders_count = offenders.len() as u32;
let offence = UnresponsivenessOffence {
session_index: 0,
validator_set_count,
offenders,
};
let slash_fraction = offence.slash_fraction(offenders_count);
assert_eq!(System::<T>::event_count(), 0);
}: {
let _ = <T as ImOnlineConfig>::ReportUnresponsiveness::report_offence(
reporters.clone(),
offence
);
}
verify {
#[cfg(test)]
{
let bond_amount: u32 = UniqueSaturatedInto::<u32>::unique_saturated_into(bond_amount::<T>());
let slash_amount = slash_fraction * bond_amount;
let reward_amount = slash_amount.saturating_mul(1 + n) / 2;
let reward = reward_amount / r;
let slash_report = |id| core::iter::once(
<T as StakingConfig>::RuntimeEvent::from(StakingEvent::<T>::SlashReported{ validator: id, fraction: slash_fraction, slash_era: 0})
);
let slash = |id| core::iter::once(
<T as StakingConfig>::RuntimeEvent::from(StakingEvent::<T>::Slashed{ staker: id, amount: BalanceOf::<T>::from(slash_amount) })
);
let balance_slash = |id| core::iter::once(
<T as BalancesConfig>::RuntimeEvent::from(pallet_balances::Event::<T>::Slashed{ who: id, amount: slash_amount.into() })
);
let balance_locked = |id| core::iter::once(
<T as BalancesConfig>::RuntimeEvent::from(pallet_balances::Event::<T>::Locked{ who: id, amount: slash_amount.into() })
);
let balance_unlocked = |id| core::iter::once(
<T as BalancesConfig>::RuntimeEvent::from(pallet_balances::Event::<T>::Unlocked{ who: id, amount: slash_amount.into() })
);
let chill = |id| core::iter::once(
<T as StakingConfig>::RuntimeEvent::from(StakingEvent::<T>::Chilled{ stash: id })
);
let balance_deposit = |id, amount: u32|
<T as BalancesConfig>::RuntimeEvent::from(pallet_balances::Event::<T>::Deposit{ who: id, amount: amount.into() });
let mut first = true;

// We need to box all events to prevent running into too big allocations in wasm.
// The event in FRAME is represented as an enum and the size of the enum depends on the biggest variant.
// So, instead of requiring `size_of<Event>() * expected_events` we only need to
// allocate `size_of<Box<Event>>() * expected_events`.
let slash_events = raw_offenders.into_iter()
.flat_map(|offender| {
let nom_slashes = offender.nominator_stashes.into_iter().flat_map(|nom| {
balance_slash(nom.clone()).map(Into::into)
.chain(balance_unlocked(nom.clone()).map(Into::into))
.chain(slash(nom).map(Into::into)).map(Box::new)
});

let events = chill(offender.stash.clone()).map(Into::into).map(Box::new)
.chain(slash_report(offender.stash.clone()).map(Into::into).map(Box::new))
.chain(balance_slash(offender.stash.clone()).map(Into::into).map(Box::new))
.chain(balance_unlocked(offender.stash.clone()).map(Into::into).map(Box::new))
.chain(slash(offender.stash).map(Into::into).map(Box::new))
.chain(nom_slashes)
.collect::<Vec<_>>();

// the first deposit creates endowed events, see `endowed_reward_events`
if first {
first = false;
let reward_events = reporters.iter()
.flat_map(|reporter| vec![
Box::new(balance_deposit(reporter.clone(), reward).into()),
Box::new(frame_system::Event::<T>::NewAccount { account: reporter.clone() }.into()),
Box::new(<T as BalancesConfig>::RuntimeEvent::from(
pallet_balances::Event::<T>::Endowed{ account: reporter.clone(), free_balance: reward.into() }
).into()),
])
.collect::<Vec<_>>();
events.into_iter().chain(reward_events)
} else {
let reward_events = reporters.iter()
.map(|reporter| Box::new(balance_deposit(reporter.clone(), reward).into()))
.collect::<Vec<_>>();
events.into_iter().chain(reward_events)
}
});

// In case of error it's useful to see the inputs
log::info!("Inputs: r: {}, o: {}, n: {}", r, o, n);
// make sure that all slashes have been applied
check_events::<T, _, _>(
sp_std::iter::empty()
.chain(slash_events)
.chain(sp_std::iter::once(Box::new(<T as OffencesConfig>::RuntimeEvent::from(
pallet_offences::Event::Offence{
kind: UnresponsivenessOffence::<T>::ID,
timeslot: 0_u32.to_le_bytes().to_vec(),
}
).into())))
);
}
}

report_offence_grandpa {
let n in 0 .. MAX_NOMINATORS.min(MaxNominationsOf::<T>::get());

Expand All @@ -409,12 +188,12 @@ benchmarks! {
Staking::<T>::set_slash_reward_fraction(Perbill::one());

let (mut offenders, raw_offenders) = make_offenders::<T>(1, n)?;
let keys = ImOnline::<T>::keys();
let validator_set_count = Session::<T>::validators().len() as u32;

let offence = GrandpaEquivocationOffence {
time_slot: GrandpaTimeSlot { set_id: 0, round: 0 },
session_index: 0,
validator_set_count: keys.len() as u32,
validator_set_count,
offender: T::convert(offenders.pop().unwrap()),
};
assert_eq!(System::<T>::event_count(), 0);
Expand Down Expand Up @@ -446,12 +225,12 @@ benchmarks! {
Staking::<T>::set_slash_reward_fraction(Perbill::one());

let (mut offenders, raw_offenders) = make_offenders::<T>(1, n)?;
let keys = ImOnline::<T>::keys();
let validator_set_count = Session::<T>::validators().len() as u32;

let offence = BabeEquivocationOffence {
slot: 0u64.into(),
session_index: 0,
validator_set_count: keys.len() as u32,
validator_set_count,
offender: T::convert(offenders.pop().unwrap()),
};
assert_eq!(System::<T>::event_count(), 0);
Expand Down

0 comments on commit cd9ee20

Please sign in to comment.