referrerpolicy=no-referrer-when-downgrade

polkadot_runtime_common/
try_runtime.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Common try-runtime only tests for runtimes.
18
19use alloc::{collections::btree_set::BTreeSet, vec::Vec};
20use frame_support::{
21	dispatch::RawOrigin,
22	traits::{Get, Hooks},
23};
24use pallet_fast_unstake::{Pallet as FastUnstake, *};
25use pallet_staking::*;
26
27/// register all inactive nominators for fast-unstake, and progress until they have all been
28/// processed.
29pub fn migrate_all_inactive_nominators<T: pallet_fast_unstake::Config + pallet_staking::Config>()
30where
31	<T as frame_system::Config>::RuntimeEvent: TryInto<pallet_fast_unstake::Event<T>>,
32{
33	let mut unstaked_ok = 0;
34	let mut unstaked_err = 0;
35	let mut unstaked_slashed = 0;
36
37	let all_stakers = Ledger::<T>::iter().map(|(ctrl, l)| (ctrl, l.stash)).collect::<BTreeSet<_>>();
38	let mut all_exposed = BTreeSet::new();
39	ErasStakersPaged::<T>::iter().for_each(|((_era, val, _page), expo)| {
40		all_exposed.insert(val);
41		all_exposed.extend(expo.others.iter().map(|ie| ie.who.clone()))
42	});
43
44	let eligible = all_stakers
45		.iter()
46		.filter_map(|(ctrl, stash)| all_exposed.contains(stash).then_some(ctrl))
47		.collect::<Vec<_>>();
48
49	log::info!(
50		target: "runtime::test",
51		"registering {} out of {} stakers for fast-unstake",
52		eligible.len(),
53		all_stakers.len()
54	);
55	for ctrl in eligible {
56		if let Err(why) =
57			FastUnstake::<T>::register_fast_unstake(RawOrigin::Signed(ctrl.clone()).into())
58		{
59			log::warn!(target: "runtime::test", "failed to register {:?} due to {:?}", ctrl, why);
60		}
61	}
62
63	log::info!(
64		target: "runtime::test",
65		"registered {} successfully, starting at {:?}.",
66		Queue::<T>::count(),
67		frame_system::Pallet::<T>::block_number(),
68	);
69	while Queue::<T>::count() != 0 || Head::<T>::get().is_some() {
70		let now = frame_system::Pallet::<T>::block_number();
71		let weight = <T as frame_system::Config>::BlockWeights::get().max_block;
72		let consumed = FastUnstake::<T>::on_idle(now, weight);
73		log::debug!(target: "runtime::test", "consumed {:?} ({})", consumed, consumed.ref_time() as f32 / weight.ref_time() as f32);
74
75		frame_system::Pallet::<T>::read_events_no_consensus()
76			.into_iter()
77			.map(|r| r.event)
78			.filter_map(|e| {
79				let maybe_fast_unstake_event: Option<pallet_fast_unstake::Event<T>> =
80					e.try_into().ok();
81				maybe_fast_unstake_event
82			})
83			.for_each(|e: pallet_fast_unstake::Event<T>| match e {
84				pallet_fast_unstake::Event::<T>::Unstaked { result, .. } =>
85					if result.is_ok() {
86						unstaked_ok += 1;
87					} else {
88						unstaked_err += 1
89					},
90				pallet_fast_unstake::Event::<T>::Slashed { .. } => unstaked_slashed += 1,
91				pallet_fast_unstake::Event::<T>::InternalError => unreachable!(),
92				_ => {},
93			});
94
95		if now % 100u32.into() == sp_runtime::traits::Zero::zero() {
96			log::info!(
97				target: "runtime::test",
98				"status: ok {}, err {}, slash {}",
99				unstaked_ok,
100				unstaked_err,
101				unstaked_slashed,
102			);
103		}
104
105		frame_system::Pallet::<T>::reset_events();
106	}
107}