Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
prepend unsafe to clear and regenerate
  • Loading branch information
gui1117 committed Nov 16, 2021
commit fede8863a60477476ba519f9d3365bdd61f05076
2 changes: 1 addition & 1 deletion frame/bags-list/remote-tests/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub async fn execute<Runtime: RuntimeT, Block: BlockT>(
log::info!(target: LOG_TARGET, "Nominator count: {}", pre_migrate_nominator_count);

// run the actual migration,
let moved = <Runtime as pallet_staking::Config>::SortedListProvider::regenerate(
let moved = <Runtime as pallet_staking::Config>::SortedListProvider::unsafe_regenerate(
pallet_staking::Nominators::<Runtime>::iter().map(|(n, _)| n),
pallet_staking::Pallet::<Runtime>::weight_of_fn(),
);
Expand Down
6 changes: 4 additions & 2 deletions frame/bags-list/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ frame_benchmarking::benchmarks! {
// node in the destination in addition to the work we do otherwise. (2 W/R)

// clear any pre-existing storage.
List::<T>::clear();
// NOTE: safe to call outside block production
List::<T>::unsafe_clear();

// define our origin and destination thresholds.
let origin_bag_thresh = T::BagThresholds::get()[0];
Expand Down Expand Up @@ -94,7 +95,8 @@ frame_benchmarking::benchmarks! {
// node in the destination in addition to the work we do otherwise. (2 W/R)

// clear any pre-existing storage.
List::<T>::clear();
// NOTE: safe to call outside block production
List::<T>::unsafe_clear();

// define our origin and destination thresholds.
let origin_bag_thresh = T::BagThresholds::get()[0];
Expand Down
16 changes: 11 additions & 5 deletions frame/bags-list/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
//! weights of accounts via [`sp_election_provider_support::VoteWeightProvider`].
//!
//! This pallet is not configurable at genesis. Whoever uses it should call appropriate functions of
//! the `SortedListProvider` (e.g. `on_insert`, or `regenerate`) at their genesis.
//! the `SortedListProvider` (e.g. `on_insert`, or `unsafe_regenerate`) at their genesis.
//!
//! # Goals
//!
Expand Down Expand Up @@ -255,11 +255,14 @@ impl<T: Config> SortedListProvider<T::AccountId> for Pallet<T> {
List::<T>::remove(id)
}

fn regenerate(
fn unsafe_regenerate(
all: impl IntoIterator<Item = T::AccountId>,
weight_of: Box<dyn Fn(&T::AccountId) -> VoteWeight>,
) -> u32 {
List::<T>::regenerate(all, weight_of)
// NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_regenerate.
// I.e. because it can lead to many storage accesses.
// So it is ok to call it as caller must ensure the conditions.
List::<T>::unsafe_regenerate(all, weight_of)
}

#[cfg(feature = "std")]
Expand All @@ -272,8 +275,11 @@ impl<T: Config> SortedListProvider<T::AccountId> for Pallet<T> {
Ok(())
}

fn clear() {
List::<T>::clear()
fn unsafe_clear() {
// NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_clear.
// I.e. because it can lead to many storage accesses.
// So it is ok to call it as caller must ensure the conditions.
List::<T>::unsafe_clear()
}

#[cfg(feature = "runtime-benchmarks")]
Expand Down
9 changes: 6 additions & 3 deletions frame/bags-list/src/list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl<T: Config> List<T> {
///
/// this function should generally not be used in production as it could lead to a very large
/// number of storage accesses.
pub(crate) fn clear() {
pub(crate) fn unsafe_clear() {
crate::ListBags::<T>::remove_all(None);
crate::ListNodes::<T>::remove_all();
}
Expand All @@ -96,11 +96,14 @@ impl<T: Config> List<T> {
/// pallet using this `List`.
///
/// Returns the number of ids migrated.
pub fn regenerate(
pub fn unsafe_regenerate(
all: impl IntoIterator<Item = T::AccountId>,
weight_of: Box<dyn Fn(&T::AccountId) -> VoteWeight>,
) -> u32 {
Self::clear();
// NOTE: This call is unsafe for the same reason as SortedListProvider::unsafe_regenerate.
// I.e. because it can lead to many storage accesses.
// So it is ok to call it as caller must ensure the conditions.
Self::unsafe_clear();
Self::insert_many(all, weight_of)
}

Expand Down
9 changes: 7 additions & 2 deletions frame/election-provider-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,12 @@ pub trait SortedListProvider<AccountId> {
/// Regenerate this list from scratch. Returns the count of items inserted.
///
/// This should typically only be used at a runtime upgrade.
fn regenerate(
///
/// ## WARNING
///
/// This function should be called with care, regenerate will remove the current list write the
/// new list, which can lead to too many storage accesses, exhausting the block weight.
fn unsafe_regenerate(
all: impl IntoIterator<Item = AccountId>,
weight_of: Box<dyn Fn(&AccountId) -> VoteWeight>,
) -> u32;
Expand All @@ -344,7 +349,7 @@ pub trait SortedListProvider<AccountId> {
///
/// This function should never be called in production settings because it can lead to an
/// unbounded amount of storage accesses.
fn clear();
fn unsafe_clear();

/// Sanity check internal state of list. Only meant for debug compilation.
fn sanity_check() -> Result<(), &'static str>;
Expand Down
2 changes: 1 addition & 1 deletion frame/staking/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub mod v8 {
if StorageVersion::<T>::get() == crate::Releases::V7_0_0 {
crate::log!(info, "migrating staking to Releases::V8_0_0");

let migrated = T::SortedListProvider::regenerate(
let migrated = T::SortedListProvider::unsafe_regenerate(
Nominators::<T>::iter().map(|(id, _)| id),
Pallet::<T>::weight_of_fn(),
);
Expand Down
6 changes: 4 additions & 2 deletions frame/staking/src/pallet/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1297,7 +1297,7 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsMap<T> {
fn on_remove(_: &T::AccountId) {
// nothing to do on remove.
}
fn regenerate(
fn unsafe_regenerate(
_: impl IntoIterator<Item = T::AccountId>,
_: Box<dyn Fn(&T::AccountId) -> VoteWeight>,
) -> u32 {
Expand All @@ -1307,7 +1307,9 @@ impl<T: Config> SortedListProvider<T::AccountId> for UseNominatorsMap<T> {
fn sanity_check() -> Result<(), &'static str> {
Ok(())
}
fn clear() {
fn unsafe_clear() {
// NOTE: Caller must ensure this doesn't lead to too many storage accesses. This is a
// condition of SortedListProvider::unsafe_clear.
Nominators::<T>::remove_all(None);
CounterForNominators::<T>::take();
}
Expand Down
3 changes: 2 additions & 1 deletion frame/staking/src/testing_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ pub fn clear_validators_and_nominators<T: Config>() {
// whenever we touch nominators counter we should update `T::SortedListProvider` as well.
Nominators::<T>::remove_all(None);
CounterForNominators::<T>::kill();
T::SortedListProvider::clear();
// NOTE: safe to call outside block production
T::SortedListProvider::unsafe_clear();
}

/// Grab a funded user.
Expand Down