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 4 commits
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
6 changes: 3 additions & 3 deletions frame/nomination-pools/benchmarking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ frame_benchmarking::benchmarks! {
depositor: depositor.clone(),
root: Some(depositor.clone()),
nominator: Some(depositor.clone()),
state_toggler: Some(depositor.clone()),
bouncer: Some(depositor.clone()),
},
}
);
Expand Down Expand Up @@ -557,7 +557,7 @@ frame_benchmarking::benchmarks! {
depositor: depositor.clone(),
root: Some(depositor.clone()),
nominator: Some(depositor.clone()),
state_toggler: Some(depositor.clone()),
bouncer: Some(depositor.clone()),
}
}
);
Expand Down Expand Up @@ -630,7 +630,7 @@ frame_benchmarking::benchmarks! {
pallet_nomination_pools::PoolRoles {
depositor: root,
nominator: Some(random.clone()),
state_toggler: Some(random.clone()),
bouncer: Some(random.clone()),
root: Some(random),
},
)
Expand Down
4 changes: 2 additions & 2 deletions frame/nomination-pools/fuzzer/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ fn random_call<R: Rng>(mut rng: &mut R) -> (pools::Call<T>, RuntimeOrigin) {
let amount = random_ed_multiple(&mut rng);
fund_account(&mut rng, &who);
let root = who;
let state_toggler = who;
let bouncer = who;
let nominator = who;
(PoolsCall::<T>::create { amount, root, state_toggler, nominator }, origin)
(PoolsCall::<T>::create { amount, root, bouncer, nominator }, origin)
},
7 => {
// nominate
Expand Down
65 changes: 31 additions & 34 deletions frame/nomination-pools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@
//! * Depositor: creates the pool and is the initial member. They can only leave the pool once all
//! other members have left. Once they fully withdraw their funds, the pool is destroyed.
//! * Nominator: can select which validators the pool nominates.
//! * State-Toggler: can change the pools state and kick members if the pool is blocked.
//! * Root: can change the nominator, state-toggler, or itself and can perform any of the actions
//! the nominator or state-toggler can.
//! * Bouncer: can change the pools state and kick members if the pool is blocked.
//! * Root: can change the nominator, bouncer, or itself and can perform any of the actions the
//! nominator or bouncer can.
//!
//! ### Dismantling
//!
Expand Down Expand Up @@ -573,13 +573,13 @@ pub struct PoolRoles<AccountId> {
/// Creates the pool and is the initial member. They can only leave the pool once all other
/// members have left. Once they fully leave, the pool is destroyed.
pub depositor: AccountId,
/// Can change the nominator, state-toggler, or itself and can perform any of the actions the
/// nominator or state-toggler can.
/// Can change the nominator, bouncer, or itself and can perform any of the actions the
/// nominator or bouncer can.
pub root: Option<AccountId>,
/// Can select which validators the pool nominates.
pub nominator: Option<AccountId>,
/// Can change the pools state and kick members if the pool is blocked.
pub state_toggler: Option<AccountId>,
pub bouncer: Option<AccountId>,
}

/// Pool permissions and state
Expand Down Expand Up @@ -734,11 +734,8 @@ impl<T: Config> BondedPool<T> {
self.roles.root.as_ref().map_or(false, |root| root == who)
}

fn is_state_toggler(&self, who: &T::AccountId) -> bool {
self.roles
.state_toggler
.as_ref()
.map_or(false, |state_toggler| state_toggler == who)
fn is_bouncer(&self, who: &T::AccountId) -> bool {
self.roles.bouncer.as_ref().map_or(false, |bouncer| bouncer == who)
}

fn can_update_roles(&self, who: &T::AccountId) -> bool {
Expand All @@ -751,15 +748,15 @@ impl<T: Config> BondedPool<T> {
}

fn can_kick(&self, who: &T::AccountId) -> bool {
self.state == PoolState::Blocked && (self.is_root(who) || self.is_state_toggler(who))
self.state == PoolState::Blocked && (self.is_root(who) || self.is_bouncer(who))
}

fn can_toggle_state(&self, who: &T::AccountId) -> bool {
(self.is_root(who) || self.is_state_toggler(who)) && !self.is_destroying()
(self.is_root(who) || self.is_bouncer(who)) && !self.is_destroying()
}

fn can_set_metadata(&self, who: &T::AccountId) -> bool {
self.is_root(who) || self.is_state_toggler(who)
self.is_root(who) || self.is_bouncer(who)
}

fn is_destroying(&self) -> bool {
Expand Down Expand Up @@ -1173,7 +1170,7 @@ pub mod pallet {
use frame_system::{ensure_signed, pallet_prelude::*};

/// The current storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(3);
const STORAGE_VERSION: StorageVersion = StorageVersion::new(4);

#[pallet::pallet]
#[pallet::generate_store(pub(crate) trait Store)]
Expand Down Expand Up @@ -1407,7 +1404,7 @@ pub mod pallet {
/// can never change.
RolesUpdated {
root: Option<T::AccountId>,
state_toggler: Option<T::AccountId>,
bouncer: Option<T::AccountId>,
nominator: Option<T::AccountId>,
},
/// The active balance of pool `pool_id` has been slashed to `balance`.
Expand Down Expand Up @@ -1630,8 +1627,8 @@ pub mod pallet {
///
/// # Conditions for a permissionless dispatch.
///
/// * The pool is blocked and the caller is either the root or state-toggler. This is
/// refereed to as a kick.
/// * The pool is blocked and the caller is either the root or bouncer. This is refereed to
/// as a kick.
/// * The pool is destroying and the member is not the depositor.
/// * The pool is destroying, the member is the depositor and no other members are in the
/// pool.
Expand Down Expand Up @@ -1754,7 +1751,7 @@ pub mod pallet {
///
/// * The pool is in destroy mode and the target is not the depositor.
/// * The target is the depositor and they are the only member in the sub pools.
/// * The pool is blocked and the caller is either the root or state-toggler.
/// * The pool is blocked and the caller is either the root or bouncer.
///
/// # Conditions for permissioned dispatch
///
Expand Down Expand Up @@ -1879,7 +1876,7 @@ pub mod pallet {
/// creating multiple pools in the same extrinsic.
/// * `root` - The account to set as [`PoolRoles::root`].
/// * `nominator` - The account to set as the [`PoolRoles::nominator`].
/// * `state_toggler` - The account to set as the [`PoolRoles::state_toggler`].
/// * `bouncer` - The account to set as the [`PoolRoles::bouncer`].
///
/// # Note
///
Expand All @@ -1892,7 +1889,7 @@ pub mod pallet {
#[pallet::compact] amount: BalanceOf<T>,
root: AccountIdLookupOf<T>,
nominator: AccountIdLookupOf<T>,
state_toggler: AccountIdLookupOf<T>,
bouncer: AccountIdLookupOf<T>,
) -> DispatchResult {
let depositor = ensure_signed(origin)?;

Expand All @@ -1901,7 +1898,7 @@ pub mod pallet {
Ok(*id)
})?;

Self::do_create(depositor, amount, root, nominator, state_toggler, pool_id)
Self::do_create(depositor, amount, root, nominator, bouncer, pool_id)
}

/// Create a new delegation pool with a previously used pool id
Expand All @@ -1917,15 +1914,15 @@ pub mod pallet {
#[pallet::compact] amount: BalanceOf<T>,
root: AccountIdLookupOf<T>,
nominator: AccountIdLookupOf<T>,
state_toggler: AccountIdLookupOf<T>,
bouncer: AccountIdLookupOf<T>,
pool_id: PoolId,
) -> DispatchResult {
let depositor = ensure_signed(origin)?;

ensure!(!BondedPools::<T>::contains_key(pool_id), Error::<T>::PoolIdInUse);
ensure!(pool_id < LastPoolId::<T>::get(), Error::<T>::InvalidPoolId);

Self::do_create(depositor, amount, root, nominator, state_toggler, pool_id)
Self::do_create(depositor, amount, root, nominator, bouncer, pool_id)
}

/// Nominate on behalf of the pool.
Expand Down Expand Up @@ -1955,7 +1952,7 @@ pub mod pallet {
///
/// The dispatch origin of this call must be either:
///
/// 1. signed by the state toggler, or the root role of the pool,
/// 1. signed by the bouncer, or the root role of the pool,
/// 2. if the pool conditions to be open are NOT met (as described by `ok_to_be_open`), and
/// then the state of the pool can be permissionlessly changed to `Destroying`.
#[pallet::call_index(9)]
Expand Down Expand Up @@ -1985,7 +1982,7 @@ pub mod pallet {

/// Set a new metadata for the pool.
///
/// The dispatch origin of this call must be signed by the state toggler, or the root role
/// The dispatch origin of this call must be signed by the bouncer, or the root role
/// of the pool.
#[pallet::call_index(10)]
#[pallet::weight(T::WeightInfo::set_metadata(metadata.len() as u32))]
Expand Down Expand Up @@ -2063,7 +2060,7 @@ pub mod pallet {
pool_id: PoolId,
new_root: ConfigOp<T::AccountId>,
new_nominator: ConfigOp<T::AccountId>,
new_state_toggler: ConfigOp<T::AccountId>,
new_bouncer: ConfigOp<T::AccountId>,
) -> DispatchResult {
let mut bonded_pool = match ensure_root(origin.clone()) {
Ok(()) => BondedPool::<T>::get(pool_id).ok_or(Error::<T>::PoolNotFound)?,
Expand All @@ -2086,16 +2083,16 @@ pub mod pallet {
ConfigOp::Remove => bonded_pool.roles.nominator = None,
ConfigOp::Set(v) => bonded_pool.roles.nominator = Some(v),
};
match new_state_toggler {
match new_bouncer {
ConfigOp::Noop => (),
ConfigOp::Remove => bonded_pool.roles.state_toggler = None,
ConfigOp::Set(v) => bonded_pool.roles.state_toggler = Some(v),
ConfigOp::Remove => bonded_pool.roles.bouncer = None,
ConfigOp::Set(v) => bonded_pool.roles.bouncer = Some(v),
};

Self::deposit_event(Event::<T>::RolesUpdated {
root: bonded_pool.roles.root.clone(),
nominator: bonded_pool.roles.nominator.clone(),
state_toggler: bonded_pool.roles.state_toggler.clone(),
bouncer: bonded_pool.roles.bouncer.clone(),
});

bonded_pool.put();
Expand Down Expand Up @@ -2354,12 +2351,12 @@ impl<T: Config> Pallet<T> {
amount: BalanceOf<T>,
root: AccountIdLookupOf<T>,
nominator: AccountIdLookupOf<T>,
state_toggler: AccountIdLookupOf<T>,
bouncer: AccountIdLookupOf<T>,
pool_id: PoolId,
) -> DispatchResult {
let root = T::Lookup::lookup(root)?;
let nominator = T::Lookup::lookup(nominator)?;
let state_toggler = T::Lookup::lookup(state_toggler)?;
let bouncer = T::Lookup::lookup(bouncer)?;

ensure!(amount >= Pallet::<T>::depositor_min_bond(), Error::<T>::MinimumBondNotMet);
ensure!(
Expand All @@ -2372,7 +2369,7 @@ impl<T: Config> Pallet<T> {
PoolRoles {
root: Some(root),
nominator: Some(nominator),
state_toggler: Some(state_toggler),
bouncer: Some(bouncer),
depositor: who.clone(),
},
);
Expand Down
97 changes: 95 additions & 2 deletions frame/nomination-pools/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub mod v1 {
pub depositor: AccountId,
pub root: AccountId,
pub nominator: AccountId,
pub state_toggler: AccountId,
pub bouncer: AccountId,
}

impl<AccountId> OldPoolRoles<AccountId> {
Expand All @@ -37,7 +37,7 @@ pub mod v1 {
depositor: self.depositor,
root: Some(self.root),
nominator: Some(self.nominator),
state_toggler: Some(self.state_toggler),
bouncer: Some(self.bouncer),
}
}
}
Expand Down Expand Up @@ -449,3 +449,96 @@ pub mod v3 {
}
}
}

pub mod v4 {
use super::*;

#[derive(Decode)]
pub struct OldBondedPoolInner<T: Config> {
pub points: BalanceOf<T>,
pub state: PoolState,
pub member_counter: u32,
pub roles: OldPoolRoles<T::AccountId>,
}

#[derive(Decode)]
pub struct OldPoolRoles<AccountId> {
pub depositor: AccountId,
pub root: Option<AccountId>,
pub nominator: Option<AccountId>,
pub state_toggler: Option<AccountId>,
}

impl<T: Config> OldBondedPoolInner<T> {
fn migrate_to_v4(self) -> BondedPoolInner<T> {
BondedPoolInner {
member_counter: self.member_counter,
points: self.points,
state: self.state,
roles: PoolRoles {
depositor: self.roles.depositor,
root: self.roles.root,
nominator: self.roles.nominator,
bouncer: self.roles.state_toggler,
},
}
}
}

/// This migration changes `PoolRoles` `state_toggler` property to `bouncer`.
pub struct MigrateToV4<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for MigrateToV4<T> {
fn on_runtime_upgrade() -> Weight {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

log!(
info,
"Running migration with current storage version {:?} / onchain {:?}",
current,
onchain
);

if current == 4 && onchain == 3 {
let mut translated = 0u64;
BondedPools::<T>::translate::<OldBondedPoolInner<T>, _>(|_key, old_value| {
translated.saturating_inc();
Some(old_value.migrate_to_v4())
});

current.put::<Pallet<T>>();
log!(info, "Upgraded {} pools, storage to version {:?}", translated, current);

// reads: translated + onchain version.
// writes: translated + current.put
T::DbWeight::get().reads_writes(translated + 1, translated + 1)
} else {
log!(info, "Migration did not execute. This probably should be removed");
T::DbWeight::get().reads(1)
}
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
ensure!(
Pallet::<T>::current_storage_version() > Pallet::<T>::on_chain_storage_version(),
"the on_chain version is equal or more than the current one"
);
Ok(Vec::new())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
// ensure all BondedPools items now contain an `inner.commission: Commission` field.
ensure!(
BondedPools::<T>::iter().all(|(_, inner)| inner.commission.current.is_none() &&
inner.commission.max.is_none() &&
inner.commission.change_rate.is_none() &&
inner.commission.throttle_from.is_none()),
"a commission value has been incorrectly set"
);
ensure!(Pallet::<T>::on_chain_storage_version() == 4, "wrong storage version");
Ok(())
}
}
}
Loading