Staking: Add deprecate_controller_batch AdminOrigin call (#2589)

Partially Addresses #2500

Adds a `deprecate_controller_batch` call to the staking pallet that is
callable by `Root` and `StakingAdmin`. To be used for controller account
deprecation and removed thereafter. Adds
`MaxControllersDeprecationBatch` pallet constant that defines max
possible deprecations per call.

- [x] Add `deprecate_controller_batch` call, and
`MaxControllersInDeprecationBatch` constant.
- [x] Add tests, benchmark, weights. Tests that weight is only consumed
if unique pair.
- [x] Adds `StakingAdmin` origin to staking's `AdminOrigin` type in
westend runtime.
- [x] Determined that worst case 5,900 deprecations does fit into
`maxBlock` `proofSize` and `refTime` in both normal and operational
thresholds, meaning we can deprecate all controllers for each network in
one call.

## Block Weights

By querying `consts.system.blockWeights` we can see that the
`deprecate_controller_batch` weights fit within the `normal` threshold
on Polkadot.

#### `controller_deprecation_batch` where i = 5900:
#### Ref time: 69,933,325,300
#### Proof size: 21,040,390

### Polkadot 

```
// consts.query.blockWeights

maxBlock: {
        refTime: 2,000,000,000,000
        proofSize: 18,446,744,073,709,551,615
}
normal: {
 maxExtrinsic: {
	refTime: 1,479,873,955,000
	proofSize: 13,650,590,614,545,068,195
 }
 maxTotal: {
	refTime: 1,500,000,000,000
	proofSize: 13,835,058,055,282,163,711
 }
}
```

### Kusama

```
// consts.query.blockWeights

  maxBlock: {
    refTime: 2,000,000,000,000
    proofSize: 18,446,744,073,709,551,615
  }
    normal: {
      maxExtrinsic: {
        refTime: 1,479,875,294,000
        proofSize: 13,650,590,614,545,068,195
      }
      maxTotal: {
        refTime: 1,500,000,000,000
        proofSize: 13,835,058,055,282,163,711
      }
}
```

---------

Co-authored-by: command-bot <>
Co-authored-by: Gonçalo Pestana <g6pestana@gmail.com>
This commit is contained in:
Ross Bulat
2023-12-12 13:23:02 +07:00
committed by GitHub
parent c2d45e7e47
commit 048a9c2744
19 changed files with 624 additions and 285 deletions
+53 -3
View File
@@ -269,6 +269,9 @@ pub mod pallet {
#[pallet::constant]
type MaxUnlockingChunks: Get<u32>;
/// The maximum amount of controller accounts that can be deprecated in one call.
type MaxControllersInDeprecationBatch: Get<u32>;
/// Something that listens to staking updates and performs actions based on the data it
/// receives.
///
@@ -1323,7 +1326,7 @@ pub mod pallet {
pub fn set_controller(origin: OriginFor<T>) -> DispatchResult {
let stash = ensure_signed(origin)?;
// the bonded map and ledger are mutated directly as this extrinsic is related to a
// The bonded map and ledger are mutated directly as this extrinsic is related to a
// (temporary) passive migration.
Self::ledger(StakingAccount::Stash(stash.clone())).map(|ledger| {
let controller = ledger.controller()
@@ -1331,10 +1334,9 @@ pub mod pallet {
.ok_or(Error::<T>::NotController)?;
if controller == stash {
// stash is already its own controller.
// Stash is already its own controller.
return Err(Error::<T>::AlreadyPaired.into())
}
// update bond and ledger.
<Ledger<T>>::remove(controller);
<Bonded<T>>::insert(&stash, &stash);
<Ledger<T>>::insert(&stash, ledger);
@@ -1920,6 +1922,54 @@ pub mod pallet {
Ok(Pays::No.into())
}
/// Updates a batch of controller accounts to their corresponding stash account if they are
/// not the same. Ignores any controller accounts that do not exist, and does not operate if
/// the stash and controller are already the same.
///
/// Effects will be felt instantly (as soon as this function is completed successfully).
///
/// The dispatch origin must be `T::AdminOrigin`.
#[pallet::call_index(28)]
#[pallet::weight(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32))]
pub fn deprecate_controller_batch(
origin: OriginFor<T>,
controllers: BoundedVec<T::AccountId, T::MaxControllersInDeprecationBatch>,
) -> DispatchResultWithPostInfo {
T::AdminOrigin::ensure_origin(origin)?;
// Ignore controllers that do not exist or are already the same as stash.
let filtered_batch_with_ledger: Vec<_> = controllers
.iter()
.filter_map(|controller| {
let ledger = Self::ledger(StakingAccount::Controller(controller.clone()));
ledger.ok().map_or(None, |ledger| {
// If the controller `RewardDestination` is still the deprecated
// `Controller` variant, skip deprecating this account.
let payee_deprecated = Payee::<T>::get(&ledger.stash) == {
#[allow(deprecated)]
RewardDestination::Controller
};
if ledger.stash != *controller && !payee_deprecated {
Some((controller.clone(), ledger))
} else {
None
}
})
})
.collect();
// Update unique pairs.
for (controller, ledger) in filtered_batch_with_ledger {
let stash = ledger.stash.clone();
<Bonded<T>>::insert(&stash, &stash);
<Ledger<T>>::remove(controller);
<Ledger<T>>::insert(stash, ledger);
}
Ok(Some(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32)).into())
}
}
}