mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 04:41:03 +00:00
Better Handling of Candidates Who Become Invulnerable (#2801)
* remove candidate when to invulnerable * fix * candidates to collators * make parameters consistent and more reasonable * add call to kick invulnerable candidates * factor removal into weight * fix: use accrue instead of add * make set_invulnerables non-atomic * benchmark add_invulnerable to account for candidate removal * don't remove from candidates with set_invulnerables * fix bounds on benchmarking * protect against zero min invulnerables underflow * extra event and tests * make candidates/invulnerables self-cleaning on session change * add integrity test * unused imports * make rococo-contracts have 1 collator
This commit is contained in:
@@ -25,7 +25,8 @@ use frame_benchmarking::{
|
||||
use frame_support::{
|
||||
assert_ok,
|
||||
codec::Decode,
|
||||
traits::{Currency, EnsureOrigin, Get},
|
||||
dispatch::DispatchResult,
|
||||
traits::{Currency, EnsureOrigin, Get, ReservableCurrency},
|
||||
};
|
||||
use frame_system::{EventRecord, RawOrigin};
|
||||
use pallet_authorship::EventHandler;
|
||||
@@ -106,6 +107,18 @@ fn register_candidates<T: Config>(count: u32) {
|
||||
}
|
||||
}
|
||||
|
||||
fn min_candidates<T: Config>() -> u32 {
|
||||
let min_collators = T::MinEligibleCollators::get();
|
||||
let invulnerable_length = <Invulnerables<T>>::get().len();
|
||||
min_collators.saturating_sub(invulnerable_length.try_into().unwrap())
|
||||
}
|
||||
|
||||
fn min_invulnerables<T: Config>() -> u32 {
|
||||
let min_collators = T::MinEligibleCollators::get();
|
||||
let candidates_length = <Candidates<T>>::get().len();
|
||||
min_collators.saturating_sub(candidates_length.try_into().unwrap())
|
||||
}
|
||||
|
||||
benchmarks! {
|
||||
where_clause { where T: pallet_authorship::Config + session::Config }
|
||||
|
||||
@@ -128,34 +141,67 @@ benchmarks! {
|
||||
}
|
||||
|
||||
add_invulnerable {
|
||||
let b in 1 .. T::MaxInvulnerables::get() - 1;
|
||||
let c in 1 .. T::MaxCandidates::get() - 1;
|
||||
|
||||
let origin =
|
||||
T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
// we're going to add one, so need one less than max set as invulnerables to start
|
||||
let b in 1 .. T::MaxInvulnerables::get() - 1;
|
||||
|
||||
// need to fill up candidates
|
||||
<CandidacyBond<T>>::put(T::Currency::minimum_balance());
|
||||
<DesiredCandidates<T>>::put(c);
|
||||
// get accounts and keys for the `c` candidates
|
||||
let mut candidates = (0..c).map(|cc| validator::<T>(cc)).collect::<Vec<_>>();
|
||||
// add one more to the list. should not be in `b` (invulnerables) because it's the account
|
||||
// we will _add_ to invulnerables. we want it to be in `candidates` because we need the
|
||||
// weight associated with removing it.
|
||||
let (new_invulnerable, new_invulnerable_keys) = validator::<T>(b.max(c) + 1);
|
||||
candidates.push((new_invulnerable.clone(), new_invulnerable_keys));
|
||||
// set their keys ...
|
||||
for (who, keys) in candidates.clone() {
|
||||
<session::Pallet<T>>::set_keys(RawOrigin::Signed(who).into(), keys, Vec::new()).unwrap();
|
||||
}
|
||||
// ... and register them.
|
||||
for (who, _) in candidates {
|
||||
let deposit = <CandidacyBond<T>>::get();
|
||||
T::Currency::make_free_balance_be(&who, deposit * 1000_u32.into());
|
||||
let incoming = CandidateInfo { who: who.clone(), deposit };
|
||||
<Candidates<T>>::try_mutate(|candidates| -> DispatchResult {
|
||||
if !candidates.iter().any(|candidate| candidate.who == who) {
|
||||
T::Currency::reserve(&who, deposit)?;
|
||||
candidates.try_push(incoming).expect("we've respected the bounded vec limit");
|
||||
<LastAuthoredBlock<T>>::insert(
|
||||
who.clone(),
|
||||
frame_system::Pallet::<T>::block_number() + T::KickThreshold::get(),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}).expect("only returns ok");
|
||||
}
|
||||
|
||||
// now we need to fill up invulnerables
|
||||
let mut invulnerables = register_validators::<T>(b);
|
||||
invulnerables.sort();
|
||||
let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> = frame_support::BoundedVec::try_from(invulnerables).unwrap();
|
||||
let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> =
|
||||
frame_support::BoundedVec::try_from(invulnerables).unwrap();
|
||||
<Invulnerables<T>>::put(invulnerables);
|
||||
|
||||
// now let's set up a new one to add
|
||||
let (new, keys) = validator::<T>(b + 1);
|
||||
<session::Pallet<T>>::set_keys(RawOrigin::Signed(new.clone()).into(), keys, Vec::new()).unwrap();
|
||||
}: {
|
||||
assert_ok!(
|
||||
<CollatorSelection<T>>::add_invulnerable(origin, new.clone())
|
||||
<CollatorSelection<T>>::add_invulnerable(origin, new_invulnerable.clone())
|
||||
);
|
||||
}
|
||||
verify {
|
||||
assert_last_event::<T>(Event::InvulnerableAdded{account_id: new}.into());
|
||||
assert_last_event::<T>(Event::InvulnerableAdded{account_id: new_invulnerable}.into());
|
||||
}
|
||||
|
||||
remove_invulnerable {
|
||||
let origin =
|
||||
T::UpdateOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
|
||||
let b in 1 .. T::MaxInvulnerables::get();
|
||||
let b in (min_invulnerables::<T>() + 1) .. T::MaxInvulnerables::get();
|
||||
let mut invulnerables = register_validators::<T>(b);
|
||||
invulnerables.sort();
|
||||
let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> = frame_support::BoundedVec::try_from(invulnerables).unwrap();
|
||||
let invulnerables: frame_support::BoundedVec<_, T::MaxInvulnerables> =
|
||||
frame_support::BoundedVec::try_from(invulnerables).unwrap();
|
||||
<Invulnerables<T>>::put(invulnerables);
|
||||
let to_remove = <Invulnerables<T>>::get().first().unwrap().clone();
|
||||
}: {
|
||||
@@ -221,7 +267,7 @@ benchmarks! {
|
||||
|
||||
// worse case is the last candidate leaving.
|
||||
leave_intent {
|
||||
let c in (T::MinCandidates::get() + 1) .. T::MaxCandidates::get();
|
||||
let c in (min_candidates::<T>() + 1) .. T::MaxCandidates::get();
|
||||
<CandidacyBond<T>>::put(T::Currency::minimum_balance());
|
||||
<DesiredCandidates<T>>::put(c);
|
||||
|
||||
@@ -286,6 +332,7 @@ benchmarks! {
|
||||
}
|
||||
}
|
||||
|
||||
let min_candidates = min_candidates::<T>();
|
||||
let pre_length = <Candidates<T>>::get().len();
|
||||
|
||||
frame_system::Pallet::<T>::set_block_number(new_block);
|
||||
@@ -294,11 +341,19 @@ benchmarks! {
|
||||
}: {
|
||||
<CollatorSelection<T> as SessionManager<_>>::new_session(0)
|
||||
} verify {
|
||||
if c > r && non_removals >= T::MinCandidates::get() {
|
||||
if c > r && non_removals >= min_candidates {
|
||||
// candidates > removals and remaining candidates > min candidates
|
||||
// => remaining candidates should be shorter than before removal, i.e. some were
|
||||
// actually removed.
|
||||
assert!(<Candidates<T>>::get().len() < pre_length);
|
||||
} else if c > r && non_removals < T::MinCandidates::get() {
|
||||
assert!(<Candidates<T>>::get().len() == T::MinCandidates::get() as usize);
|
||||
} else if c > r && non_removals < min_candidates {
|
||||
// candidates > removals and remaining candidates would be less than min candidates
|
||||
// => remaining candidates should equal min candidates, i.e. some were removed up to
|
||||
// the minimum, but then any more were "forced" to stay in candidates.
|
||||
assert!(<Candidates<T>>::get().len() == min_candidates as usize);
|
||||
} else {
|
||||
// removals >= candidates, non removals must == 0
|
||||
// can't remove more than exist
|
||||
assert!(<Candidates<T>>::get().len() == pre_length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,9 @@
|
||||
//! The current implementation resolves congestion of [`Candidates`] in a first-come-first-serve
|
||||
//! manner.
|
||||
//!
|
||||
//! Candidates will not be allowed to get kicked or leave_intent if the total number of candidates
|
||||
//! fall below MinCandidates. This is for potential disaster recovery scenarios.
|
||||
//! Candidates will not be allowed to get kicked or `leave_intent` if the total number of collators
|
||||
//! would fall below `MinEligibleCollators`. This is to ensure that some collators will always
|
||||
//! exist, i.e. someone is eligible to produce a block.
|
||||
//!
|
||||
//! ### Rewards
|
||||
//!
|
||||
@@ -53,7 +54,7 @@
|
||||
//! - Half the value of the transaction fees within the block. The other half of the transaction
|
||||
//! fees are deposited into the Pot.
|
||||
//!
|
||||
//! To initiate rewards an ED needs to be transferred to the pot address.
|
||||
//! To initiate rewards, an ED needs to be transferred to the pot address.
|
||||
//!
|
||||
//! Note: Eventually the Pot distribution may be modified as discussed in
|
||||
//! [this issue](https://github.com/paritytech/statemint/issues/21#issuecomment-810481073).
|
||||
@@ -128,17 +129,17 @@ pub mod pallet {
|
||||
/// Account Identifier from which the internal Pot is generated.
|
||||
type PotId: Get<PalletId>;
|
||||
|
||||
/// Maximum number of candidates that we should have. This is enforced in code.
|
||||
/// Maximum number of candidates that we should have.
|
||||
///
|
||||
/// This does not take into account the invulnerables.
|
||||
type MaxCandidates: Get<u32>;
|
||||
|
||||
/// Minimum number of candidates that we should have. This is used for disaster recovery.
|
||||
///
|
||||
/// This does not take into account the invulnerables.
|
||||
type MinCandidates: Get<u32>;
|
||||
/// Minimum number eligible collators. Should always be greater than zero. This includes
|
||||
/// Invulnerable collators. This ensures that there will always be one collator who can
|
||||
/// produce a block.
|
||||
type MinEligibleCollators: Get<u32>;
|
||||
|
||||
/// Maximum number of invulnerables. This is enforced in code.
|
||||
/// Maximum number of invulnerables.
|
||||
type MaxInvulnerables: Get<u32>;
|
||||
|
||||
// Will be kicked if block is not produced in threshold.
|
||||
@@ -180,7 +181,8 @@ pub mod pallet {
|
||||
pub type Invulnerables<T: Config> =
|
||||
StorageValue<_, BoundedVec<T::AccountId, T::MaxInvulnerables>, ValueQuery>;
|
||||
|
||||
/// The (community, limited) collation candidates.
|
||||
/// The (community, limited) collation candidates. `Candidates` and `Invulnerables` should be
|
||||
/// mutually exclusive.
|
||||
#[pallet::storage]
|
||||
#[pallet::getter(fn candidates)]
|
||||
pub type Candidates<T: Config> = StorageValue<
|
||||
@@ -262,6 +264,9 @@ pub mod pallet {
|
||||
CandidateAdded { account_id: T::AccountId, deposit: BalanceOf<T> },
|
||||
/// A candidate was removed.
|
||||
CandidateRemoved { account_id: T::AccountId },
|
||||
/// An account was unable to be added to the Invulnerables because they did not have keys
|
||||
/// registered. Other Invulnerables may have been set.
|
||||
InvalidInvulnerableSkipped { account_id: T::AccountId },
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
@@ -269,7 +274,7 @@ pub mod pallet {
|
||||
/// The pallet has too many candidates.
|
||||
TooManyCandidates,
|
||||
/// Leaving would result in too few candidates.
|
||||
TooFewCandidates,
|
||||
TooFewEligibleCollators,
|
||||
/// Account is already a candidate.
|
||||
AlreadyCandidate,
|
||||
/// Account is not a candidate.
|
||||
@@ -287,31 +292,81 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
#[pallet::hooks]
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
|
||||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
|
||||
fn integrity_test() {
|
||||
assert!(T::MinEligibleCollators::get() > 0, "chain must require at least one collator");
|
||||
}
|
||||
}
|
||||
|
||||
#[pallet::call]
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Set the list of invulnerable (fixed) collators.
|
||||
/// Set the list of invulnerable (fixed) collators. These collators must do some
|
||||
/// preparation, namely to have registered session keys.
|
||||
///
|
||||
/// The call will remove any accounts that have not registered keys from the set. That is,
|
||||
/// it is non-atomic; the caller accepts all `AccountId`s passed in `new` _individually_ as
|
||||
/// acceptable Invulnerables, and is not proposing a _set_ of new Invulnerables.
|
||||
///
|
||||
/// This call does not maintain mutual exclusivity of `Invulnerables` and `Candidates`. It
|
||||
/// is recommended to use a batch of `add_invulnerable` and `remove_invulnerable` instead.
|
||||
/// A `batch_all` can also be used to enforce atomicity. If any candidates are included in
|
||||
/// `new`, they should be removed with `remove_invulnerable_candidate` after execution.
|
||||
///
|
||||
/// Must be called by the `UpdateOrigin`.
|
||||
#[pallet::call_index(0)]
|
||||
#[pallet::weight(T::WeightInfo::set_invulnerables(new.len() as u32))]
|
||||
pub fn set_invulnerables(
|
||||
origin: OriginFor<T>,
|
||||
new: Vec<T::AccountId>,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
pub fn set_invulnerables(origin: OriginFor<T>, new: Vec<T::AccountId>) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin(origin)?;
|
||||
let mut bounded_invulnerables = BoundedVec::<_, T::MaxInvulnerables>::try_from(new)
|
||||
.map_err(|_| Error::<T>::TooManyInvulnerables)?;
|
||||
|
||||
// check if the invulnerables have associated validator keys before they are set
|
||||
for account_id in bounded_invulnerables.iter() {
|
||||
let validator_key = T::ValidatorIdOf::convert(account_id.clone())
|
||||
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
|
||||
// don't wipe out the collator set
|
||||
if new.is_empty() {
|
||||
ensure!(
|
||||
T::ValidatorRegistration::is_registered(&validator_key),
|
||||
Error::<T>::ValidatorNotRegistered
|
||||
Self::candidates().len() as u32 >= T::MinEligibleCollators::get(),
|
||||
Error::<T>::TooFewEligibleCollators
|
||||
);
|
||||
}
|
||||
|
||||
// Will need to check the length again when putting into a bounded vec, but this
|
||||
// prevents the iterator from having too many elements.
|
||||
ensure!(
|
||||
new.len() as u32 <= T::MaxInvulnerables::get(),
|
||||
Error::<T>::TooManyInvulnerables
|
||||
);
|
||||
|
||||
let mut new_with_keys = Vec::new();
|
||||
|
||||
// check if the invulnerables have associated validator keys before they are set
|
||||
for account_id in &new {
|
||||
// don't let one unprepared collator ruin things for everyone.
|
||||
let validator_key = T::ValidatorIdOf::convert(account_id.clone());
|
||||
match validator_key {
|
||||
Some(key) => {
|
||||
// key is not registered
|
||||
if !T::ValidatorRegistration::is_registered(&key) {
|
||||
Self::deposit_event(Event::InvalidInvulnerableSkipped {
|
||||
account_id: account_id.clone(),
|
||||
});
|
||||
continue
|
||||
}
|
||||
// else condition passes; key is registered
|
||||
},
|
||||
// key does not exist
|
||||
None => {
|
||||
Self::deposit_event(Event::InvalidInvulnerableSkipped {
|
||||
account_id: account_id.clone(),
|
||||
});
|
||||
continue
|
||||
},
|
||||
}
|
||||
|
||||
new_with_keys.push(account_id.clone());
|
||||
}
|
||||
|
||||
// should never fail since `new_with_keys` must be equal to or shorter than `new`
|
||||
let mut bounded_invulnerables =
|
||||
BoundedVec::<_, T::MaxInvulnerables>::try_from(new_with_keys)
|
||||
.map_err(|_| Error::<T>::TooManyInvulnerables)?;
|
||||
|
||||
// Invulnerables must be sorted for removal.
|
||||
bounded_invulnerables.sort();
|
||||
|
||||
@@ -319,12 +374,15 @@ pub mod pallet {
|
||||
Self::deposit_event(Event::NewInvulnerables {
|
||||
invulnerables: bounded_invulnerables.to_vec(),
|
||||
});
|
||||
Ok(().into())
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the ideal number of collators (not including the invulnerables).
|
||||
/// If lowering this number, then the number of running collators could be higher than this figure.
|
||||
/// Aside from that edge case, there should be no other way to have more collators than the desired number.
|
||||
/// Set the ideal number of non-invulnerable collators. If lowering this number, then the
|
||||
/// number of running collators could be higher than this figure. Aside from that edge case,
|
||||
/// there should be no other way to have more candidates than the desired number.
|
||||
///
|
||||
/// The origin for this call must be the `UpdateOrigin`.
|
||||
#[pallet::call_index(1)]
|
||||
#[pallet::weight(T::WeightInfo::set_desired_candidates())]
|
||||
pub fn set_desired_candidates(
|
||||
@@ -342,6 +400,8 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
/// Set the candidacy bond amount.
|
||||
///
|
||||
/// The origin for this call must be the `UpdateOrigin`.
|
||||
#[pallet::call_index(2)]
|
||||
#[pallet::weight(T::WeightInfo::set_candidacy_bond())]
|
||||
pub fn set_candidacy_bond(
|
||||
@@ -401,28 +461,35 @@ pub mod pallet {
|
||||
/// Deregister `origin` as a collator candidate. Note that the collator can only leave on
|
||||
/// session change. The `CandidacyBond` will be unreserved immediately.
|
||||
///
|
||||
/// This call will fail if the total number of candidates would drop below `MinCandidates`.
|
||||
///
|
||||
/// This call is not available to `Invulnerable` collators.
|
||||
/// This call will fail if the total number of candidates would drop below
|
||||
/// `MinEligibleCollators`.
|
||||
#[pallet::call_index(4)]
|
||||
#[pallet::weight(T::WeightInfo::leave_intent(T::MaxCandidates::get()))]
|
||||
pub fn leave_intent(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
|
||||
let who = ensure_signed(origin)?;
|
||||
ensure!(
|
||||
Self::candidates().len() as u32 > T::MinCandidates::get(),
|
||||
Error::<T>::TooFewCandidates
|
||||
Self::eligible_collators() > T::MinEligibleCollators::get(),
|
||||
Error::<T>::TooFewEligibleCollators
|
||||
);
|
||||
let current_count = Self::try_remove_candidate(&who)?;
|
||||
// Do remove their last authored block.
|
||||
let current_count = Self::try_remove_candidate(&who, true)?;
|
||||
|
||||
Ok(Some(T::WeightInfo::leave_intent(current_count as u32)).into())
|
||||
}
|
||||
|
||||
/// Add a new account `who` to the list of `Invulnerables` collators.
|
||||
/// Add a new account `who` to the list of `Invulnerables` collators. `who` must have
|
||||
/// registered session keys. If `who` is a candidate, they will be removed.
|
||||
///
|
||||
/// The origin for this call must be the `UpdateOrigin`.
|
||||
#[pallet::call_index(5)]
|
||||
#[pallet::weight(T::WeightInfo::add_invulnerable(T::MaxInvulnerables::get() - 1))]
|
||||
pub fn add_invulnerable(origin: OriginFor<T>, who: T::AccountId) -> DispatchResult {
|
||||
#[pallet::weight(T::WeightInfo::add_invulnerable(
|
||||
T::MaxInvulnerables::get().saturating_sub(1),
|
||||
T::MaxCandidates::get()
|
||||
))]
|
||||
pub fn add_invulnerable(
|
||||
origin: OriginFor<T>,
|
||||
who: T::AccountId,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
T::UpdateOrigin::ensure_origin(origin)?;
|
||||
|
||||
// ensure `who` has registered a validator key
|
||||
@@ -443,8 +510,21 @@ pub mod pallet {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Error just means `who` wasn't a candidate, which is the state we want anyway. Don't
|
||||
// remove their last authored block, as they are still a collator.
|
||||
let _ = Self::try_remove_candidate(&who, false);
|
||||
|
||||
Self::deposit_event(Event::InvulnerableAdded { account_id: who });
|
||||
Ok(())
|
||||
|
||||
let weight_used = T::WeightInfo::add_invulnerable(
|
||||
Self::invulnerables()
|
||||
.len()
|
||||
.try_into()
|
||||
.unwrap_or(T::MaxInvulnerables::get().saturating_sub(1)),
|
||||
Self::candidates().len().try_into().unwrap_or(T::MaxCandidates::get()),
|
||||
);
|
||||
|
||||
Ok(Some(weight_used).into())
|
||||
}
|
||||
|
||||
/// Remove an account `who` from the list of `Invulnerables` collators. `Invulnerables` must
|
||||
@@ -456,6 +536,11 @@ pub mod pallet {
|
||||
pub fn remove_invulnerable(origin: OriginFor<T>, who: T::AccountId) -> DispatchResult {
|
||||
T::UpdateOrigin::ensure_origin(origin)?;
|
||||
|
||||
ensure!(
|
||||
Self::eligible_collators() > T::MinEligibleCollators::get(),
|
||||
Error::<T>::TooFewEligibleCollators
|
||||
);
|
||||
|
||||
<Invulnerables<T>>::try_mutate(|invulnerables| -> DispatchResult {
|
||||
let pos =
|
||||
invulnerables.binary_search(&who).map_err(|_| Error::<T>::NotInvulnerable)?;
|
||||
@@ -469,13 +554,29 @@ pub mod pallet {
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
/// Get a unique, inaccessible account id from the `PotId`.
|
||||
/// Get a unique, inaccessible account ID from the `PotId`.
|
||||
pub fn account_id() -> T::AccountId {
|
||||
T::PotId::get().into_account_truncating()
|
||||
}
|
||||
|
||||
/// Removes a candidate if they exist and sends them back their deposit
|
||||
fn try_remove_candidate(who: &T::AccountId) -> Result<usize, DispatchError> {
|
||||
/// Return the total number of accounts that are eligible collators (candidates and
|
||||
/// invulnerables).
|
||||
fn eligible_collators() -> u32 {
|
||||
Self::candidates()
|
||||
.len()
|
||||
.saturating_add(Self::invulnerables().len())
|
||||
.try_into()
|
||||
// More-or-less guaranteed not to Err since it's hard to imagine candidates +
|
||||
// invulnerables being greater than (or for `usize` to be smaller than) `u32::MAX`,
|
||||
// but return something "reasonable" instead of panicking.
|
||||
.unwrap_or(T::MaxCandidates::get())
|
||||
}
|
||||
|
||||
/// Removes a candidate if they exist and sends them back their deposit.
|
||||
fn try_remove_candidate(
|
||||
who: &T::AccountId,
|
||||
remove_last_authored: bool,
|
||||
) -> Result<usize, DispatchError> {
|
||||
let current_count =
|
||||
<Candidates<T>>::try_mutate(|candidates| -> Result<usize, DispatchError> {
|
||||
let index = candidates
|
||||
@@ -484,7 +585,9 @@ pub mod pallet {
|
||||
.ok_or(Error::<T>::NotCandidate)?;
|
||||
let candidate = candidates.remove(index);
|
||||
T::Currency::unreserve(who, candidate.deposit);
|
||||
<LastAuthoredBlock<T>>::remove(who.clone());
|
||||
if remove_last_authored {
|
||||
<LastAuthoredBlock<T>>::remove(who.clone())
|
||||
};
|
||||
Ok(candidates.len())
|
||||
})?;
|
||||
Self::deposit_event(Event::CandidateRemoved { account_id: who.clone() });
|
||||
@@ -502,30 +605,40 @@ pub mod pallet {
|
||||
collators
|
||||
}
|
||||
|
||||
/// Kicks out candidates that did not produce a block in the kick threshold
|
||||
/// and refund their deposits.
|
||||
/// Kicks out candidates that did not produce a block in the kick threshold and refunds
|
||||
/// their deposits.
|
||||
pub fn kick_stale_candidates(
|
||||
candidates: BoundedVec<CandidateInfo<T::AccountId, BalanceOf<T>>, T::MaxCandidates>,
|
||||
) -> BoundedVec<T::AccountId, T::MaxCandidates> {
|
||||
let now = frame_system::Pallet::<T>::block_number();
|
||||
let kick_threshold = T::KickThreshold::get();
|
||||
let min_collators = T::MinEligibleCollators::get();
|
||||
candidates
|
||||
.into_iter()
|
||||
.filter_map(|c| {
|
||||
let last_block = <LastAuthoredBlock<T>>::get(c.who.clone());
|
||||
let since_last = now.saturating_sub(last_block);
|
||||
if since_last < kick_threshold ||
|
||||
Self::candidates().len() as u32 <= T::MinCandidates::get()
|
||||
{
|
||||
|
||||
let is_invulnerable = Self::invulnerables().contains(&c.who);
|
||||
let is_lazy = since_last >= kick_threshold;
|
||||
|
||||
if is_invulnerable {
|
||||
// They are invulnerable. No reason for them to be in Candidates also.
|
||||
// We don't even care about the min collators here, because an Account
|
||||
// should not be a collator twice.
|
||||
let _ = Self::try_remove_candidate(&c.who, false);
|
||||
None
|
||||
} else {
|
||||
if Self::eligible_collators() <= min_collators || !is_lazy {
|
||||
// Either this is a good collator (not lazy) or we are at the minimum
|
||||
// that the system needs. They get to stay.
|
||||
Some(c.who)
|
||||
} else {
|
||||
let outcome = Self::try_remove_candidate(&c.who);
|
||||
if let Err(why) = outcome {
|
||||
log::warn!("Failed to remove candidate {:?}", why);
|
||||
debug_assert!(false, "failed to remove candidate {:?}", why);
|
||||
}
|
||||
// This collator has not produced a block recently enough. Bye bye.
|
||||
let _ = Self::try_remove_candidate(&c.who, true);
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
|
||||
@@ -188,9 +188,6 @@ ord_parameter_types! {
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
pub const MaxCandidates: u32 = 20;
|
||||
pub const MaxInvulnerables: u32 = 20;
|
||||
pub const MinCandidates: u32 = 1;
|
||||
}
|
||||
|
||||
pub struct IsRegistered;
|
||||
@@ -205,9 +202,9 @@ impl Config for Test {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = EnsureSignedBy<RootAccount, u64>;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = MaxCandidates;
|
||||
type MinCandidates = MinCandidates;
|
||||
type MaxInvulnerables = MaxInvulnerables;
|
||||
type MaxCandidates = ConstU32<20>;
|
||||
type MinEligibleCollators = ConstU32<1>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
type ValidatorIdOf = IdentityCollator;
|
||||
|
||||
@@ -50,16 +50,22 @@ fn it_should_set_invulnerables() {
|
||||
CollatorSelection::set_invulnerables(RuntimeOrigin::signed(1), new_set),
|
||||
BadOrigin
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// cannot set invulnerables without associated validator keys
|
||||
let invulnerables = vec![42];
|
||||
assert_noop!(
|
||||
CollatorSelection::set_invulnerables(
|
||||
#[test]
|
||||
fn it_should_set_invulnerables_even_with_some_invalid() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
|
||||
let new_with_invalid = vec![1, 4, 3, 42, 2];
|
||||
|
||||
assert_ok!(CollatorSelection::set_invulnerables(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
invulnerables
|
||||
),
|
||||
Error::<Test>::ValidatorNotRegistered
|
||||
);
|
||||
new_with_invalid
|
||||
));
|
||||
|
||||
// should succeed and order them, but not include 42
|
||||
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2, 3, 4]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -190,6 +196,54 @@ fn remove_invulnerable_works() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn candidate_to_invulnerable_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
initialize_to_block(1);
|
||||
assert_eq!(CollatorSelection::desired_candidates(), 2);
|
||||
assert_eq!(CollatorSelection::candidacy_bond(), 10);
|
||||
assert_eq!(CollatorSelection::candidates(), Vec::new());
|
||||
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
|
||||
|
||||
assert_eq!(Balances::free_balance(3), 100);
|
||||
assert_eq!(Balances::free_balance(4), 100);
|
||||
|
||||
assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
|
||||
assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
|
||||
|
||||
assert_eq!(Balances::free_balance(3), 90);
|
||||
assert_eq!(Balances::free_balance(4), 90);
|
||||
|
||||
assert_ok!(CollatorSelection::add_invulnerable(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
3
|
||||
));
|
||||
System::assert_has_event(RuntimeEvent::CollatorSelection(crate::Event::CandidateRemoved {
|
||||
account_id: 3,
|
||||
}));
|
||||
System::assert_has_event(RuntimeEvent::CollatorSelection(
|
||||
crate::Event::InvulnerableAdded { account_id: 3 },
|
||||
));
|
||||
assert!(CollatorSelection::invulnerables().to_vec().contains(&3));
|
||||
assert_eq!(Balances::free_balance(3), 100);
|
||||
assert_eq!(CollatorSelection::candidates().len(), 1);
|
||||
|
||||
assert_ok!(CollatorSelection::add_invulnerable(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
4
|
||||
));
|
||||
System::assert_has_event(RuntimeEvent::CollatorSelection(crate::Event::CandidateRemoved {
|
||||
account_id: 4,
|
||||
}));
|
||||
System::assert_has_event(RuntimeEvent::CollatorSelection(
|
||||
crate::Event::InvulnerableAdded { account_id: 4 },
|
||||
));
|
||||
assert!(CollatorSelection::invulnerables().to_vec().contains(&4));
|
||||
assert_eq!(Balances::free_balance(4), 100);
|
||||
assert_eq!(CollatorSelection::candidates().len(), 0);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_desired_candidates_works() {
|
||||
new_test_ext().execute_with(|| {
|
||||
@@ -256,14 +310,31 @@ fn cannot_register_candidate_if_too_many() {
|
||||
#[test]
|
||||
fn cannot_unregister_candidate_if_too_few() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(CollatorSelection::candidates(), Vec::new());
|
||||
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
|
||||
assert_ok!(CollatorSelection::remove_invulnerable(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
1
|
||||
));
|
||||
assert_noop!(
|
||||
CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 2),
|
||||
Error::<Test>::TooFewEligibleCollators,
|
||||
);
|
||||
|
||||
// reset desired candidates:
|
||||
<crate::DesiredCandidates<Test>>::put(1);
|
||||
assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
|
||||
|
||||
// now we can remove `2`
|
||||
assert_ok!(CollatorSelection::remove_invulnerable(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
2
|
||||
));
|
||||
|
||||
// can not remove too few
|
||||
assert_noop!(
|
||||
CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),
|
||||
Error::<Test>::TooFewCandidates,
|
||||
Error::<Test>::TooFewEligibleCollators,
|
||||
);
|
||||
})
|
||||
}
|
||||
@@ -487,28 +558,71 @@ fn kick_mechanism() {
|
||||
#[test]
|
||||
fn should_not_kick_mechanism_too_few() {
|
||||
new_test_ext().execute_with(|| {
|
||||
// add a new collator
|
||||
// remove the invulnerables and add new collators 3 and 5
|
||||
assert_eq!(CollatorSelection::candidates(), Vec::new());
|
||||
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
|
||||
assert_ok!(CollatorSelection::remove_invulnerable(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
1
|
||||
));
|
||||
assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
|
||||
assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5)));
|
||||
assert_ok!(CollatorSelection::remove_invulnerable(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
2
|
||||
));
|
||||
|
||||
initialize_to_block(10);
|
||||
assert_eq!(CollatorSelection::candidates().len(), 2);
|
||||
|
||||
initialize_to_block(20);
|
||||
assert_eq!(SessionChangeBlock::get(), 20);
|
||||
// 4 authored this block, 5 gets to stay too few 3 was kicked
|
||||
// 4 authored this block, 3 is kicked, 5 stays because of too few collators
|
||||
assert_eq!(CollatorSelection::candidates().len(), 1);
|
||||
// 3 will be kicked after 1 session delay
|
||||
assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 5]);
|
||||
assert_eq!(SessionHandlerCollators::get(), vec![3, 5]);
|
||||
let collator = CandidateInfo { who: 5, deposit: 10 };
|
||||
assert_eq!(CollatorSelection::candidates(), vec![collator]);
|
||||
assert_eq!(CollatorSelection::last_authored_block(4), 20);
|
||||
|
||||
initialize_to_block(30);
|
||||
// 3 gets kicked after 1 session delay
|
||||
assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);
|
||||
assert_eq!(SessionHandlerCollators::get(), vec![5]);
|
||||
// kicked collator gets funds back
|
||||
assert_eq!(Balances::free_balance(3), 100);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_kick_invulnerables_from_candidates_on_session_change() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_eq!(CollatorSelection::candidates(), Vec::new());
|
||||
assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
|
||||
assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
|
||||
assert_eq!(Balances::free_balance(3), 90);
|
||||
assert_eq!(Balances::free_balance(4), 90);
|
||||
assert_ok!(CollatorSelection::set_invulnerables(
|
||||
RuntimeOrigin::signed(RootAccount::get()),
|
||||
vec![1, 2, 3]
|
||||
));
|
||||
|
||||
let collator_3 = CandidateInfo { who: 3, deposit: 10 };
|
||||
let collator_4 = CandidateInfo { who: 4, deposit: 10 };
|
||||
|
||||
assert_eq!(CollatorSelection::candidates(), vec![collator_3, collator_4.clone()]);
|
||||
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2, 3]);
|
||||
|
||||
// session change
|
||||
initialize_to_block(10);
|
||||
// 3 is removed from candidates
|
||||
assert_eq!(CollatorSelection::candidates(), vec![collator_4]);
|
||||
// but not from invulnerables
|
||||
assert_eq!(CollatorSelection::invulnerables(), vec![1, 2, 3]);
|
||||
// and it got its deposit back
|
||||
assert_eq!(Balances::free_balance(3), 100);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "duplicate invulnerables in genesis."]
|
||||
fn cannot_set_genesis_value_twice() {
|
||||
|
||||
@@ -27,7 +27,7 @@ use sp_std::marker::PhantomData;
|
||||
// The weight info trait for `pallet_collator_selection`.
|
||||
pub trait WeightInfo {
|
||||
fn set_invulnerables(_b: u32) -> Weight;
|
||||
fn add_invulnerable(_b: u32) -> Weight;
|
||||
fn add_invulnerable(_b: u32, _c: u32) -> Weight;
|
||||
fn remove_invulnerable(_b: u32) -> Weight;
|
||||
fn set_desired_candidates() -> Weight;
|
||||
fn set_candidacy_bond() -> Weight;
|
||||
@@ -82,23 +82,31 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64.saturating_mul(r as u64)))
|
||||
.saturating_add(T::DbWeight::get().writes(2_u64.saturating_mul(c as u64)))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
@@ -161,23 +169,31 @@ impl WeightInfo for () {
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64.saturating_mul(r as u64)))
|
||||
.saturating_add(RocksDbWeight::get().writes(2_u64.saturating_mul(c as u64)))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(2))
|
||||
.saturating_add(RocksDbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(RocksDbWeight::get().reads(4))
|
||||
.saturating_add(RocksDbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -433,10 +433,7 @@ impl pallet_aura::Config for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
pub const MaxCandidates: u32 = 1000;
|
||||
pub const MinCandidates: u32 = 5;
|
||||
pub const SessionLength: BlockNumber = 6 * HOURS;
|
||||
pub const MaxInvulnerables: u32 = 100;
|
||||
// StakingAdmin pluralistic body.
|
||||
pub const StakingAdminBodyId: BodyId = BodyId::Defense;
|
||||
}
|
||||
@@ -452,9 +449,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = MaxCandidates;
|
||||
type MinCandidates = MinCandidates;
|
||||
type MaxInvulnerables = MaxInvulnerables;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
@@ -222,9 +222,6 @@ mod tests {
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
pub const MaxCandidates: u32 = 20;
|
||||
pub const MaxInvulnerables: u32 = 20;
|
||||
pub const MinCandidates: u32 = 1;
|
||||
}
|
||||
|
||||
impl pallet_collator_selection::Config for Test {
|
||||
@@ -232,9 +229,9 @@ mod tests {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = EnsureRoot<AccountId>;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = MaxCandidates;
|
||||
type MinCandidates = MinCandidates;
|
||||
type MaxInvulnerables = MaxInvulnerables;
|
||||
type MaxCandidates = ConstU32<20>;
|
||||
type MinEligibleCollators = ConstU32<1>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
type ValidatorIdOf = IdentityCollator;
|
||||
type ValidatorRegistration = IsRegistered;
|
||||
|
||||
@@ -598,10 +598,7 @@ impl pallet_aura::Config for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
pub const MaxCandidates: u32 = 1000;
|
||||
pub const MinCandidates: u32 = 5;
|
||||
pub const SessionLength: BlockNumber = 6 * HOURS;
|
||||
pub const MaxInvulnerables: u32 = 100;
|
||||
// StakingAdmin pluralistic body.
|
||||
pub const StakingAdminBodyId: BodyId = BodyId::Defense;
|
||||
}
|
||||
@@ -617,9 +614,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = MaxCandidates;
|
||||
type MinCandidates = MinCandidates;
|
||||
type MaxInvulnerables = MaxInvulnerables;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
+21
-13
@@ -147,23 +147,31 @@ impl<T: frame_system::Config> pallet_collator_selection::WeightInfo for WeightIn
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, ) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -611,10 +611,7 @@ impl pallet_aura::Config for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
pub const MaxCandidates: u32 = 1000;
|
||||
pub const MinCandidates: u32 = 5;
|
||||
pub const SessionLength: BlockNumber = 6 * HOURS;
|
||||
pub const MaxInvulnerables: u32 = 100;
|
||||
// `StakingAdmin` pluralistic body.
|
||||
pub const StakingAdminBodyId: BodyId = BodyId::Defense;
|
||||
}
|
||||
@@ -630,9 +627,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = MaxCandidates;
|
||||
type MinCandidates = MinCandidates;
|
||||
type MaxInvulnerables = MaxInvulnerables;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
+21
-13
@@ -147,23 +147,31 @@ impl<T: frame_system::Config> pallet_collator_selection::WeightInfo for WeightIn
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, ) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -637,10 +637,7 @@ impl pallet_aura::Config for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
pub const MaxCandidates: u32 = 1000;
|
||||
pub const MinCandidates: u32 = 1;
|
||||
pub const SessionLength: BlockNumber = 6 * HOURS;
|
||||
pub const MaxInvulnerables: u32 = 100;
|
||||
}
|
||||
|
||||
pub type CollatorSelectionUpdateOrigin = EnsureRoot<AccountId>;
|
||||
@@ -650,9 +647,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = MaxCandidates;
|
||||
type MinCandidates = MinCandidates;
|
||||
type MaxInvulnerables = MaxInvulnerables;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
+21
-13
@@ -147,23 +147,31 @@ impl<T: frame_system::Config> pallet_collator_selection::WeightInfo for WeightIn
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, ) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -352,7 +352,7 @@ parameter_types! {
|
||||
pub const StakingAdminBodyId: BodyId = BodyId::Defense;
|
||||
}
|
||||
|
||||
/// We allow root, the StakingAdmin to execute privileged collator selection operations.
|
||||
/// We allow Root and the `StakingAdmin` to execute privileged collator selection operations.
|
||||
pub type CollatorSelectionUpdateOrigin = EitherOfDiverse<
|
||||
EnsureRoot<AccountId>,
|
||||
EnsureXcm<IsVoiceOfBody<GovernanceLocation, StakingAdminBodyId>>,
|
||||
@@ -363,9 +363,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<1000>;
|
||||
type MinCandidates = ConstU32<5>;
|
||||
type MaxInvulnerables = ConstU32<100>;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = ConstU32<PERIOD>;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
+21
-13
@@ -147,23 +147,31 @@ impl<T: frame_system::Config> pallet_collator_selection::WeightInfo for WeightIn
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, ) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -363,9 +363,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<1000>;
|
||||
type MinCandidates = ConstU32<5>;
|
||||
type MaxInvulnerables = ConstU32<100>;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = ConstU32<PERIOD>;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
+21
-13
@@ -147,23 +147,31 @@ impl<T: frame_system::Config> pallet_collator_selection::WeightInfo for WeightIn
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, ) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -361,9 +361,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<1000>;
|
||||
type MinCandidates = ConstU32<5>;
|
||||
type MaxInvulnerables = ConstU32<100>;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = ConstU32<PERIOD>;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
+21
-13
@@ -147,23 +147,31 @@ impl<T: frame_system::Config> pallet_collator_selection::WeightInfo for WeightIn
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, ) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -436,9 +436,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<1000>;
|
||||
type MinCandidates = ConstU32<5>;
|
||||
type MaxInvulnerables = ConstU32<100>;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = ConstU32<PERIOD>;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
+21
-13
@@ -147,23 +147,31 @@ impl<T: frame_system::Config> pallet_collator_selection::WeightInfo for WeightIn
|
||||
.saturating_add(T::DbWeight::get().reads(3))
|
||||
.saturating_add(T::DbWeight::get().writes(4))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
/// Storage: Session NextKeys (r:1 w:0)
|
||||
/// Proof Skipped: Session NextKeys (max_values: None, max_size: None, mode: Measured)
|
||||
/// The range of component `b` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, ) -> Weight {
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(641), added: 1136, mode: MaxEncodedLen)
|
||||
/// Storage: CollatorSelection Candidates (r:1 w:1)
|
||||
/// Proof: CollatorSelection Candidates (max_values: Some(1), max_size: Some(4802), added: 5297, mode: MaxEncodedLen)
|
||||
/// Storage: System Account (r:1 w:1)
|
||||
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
|
||||
/// The range of component `b` is `[1, 19]`.
|
||||
/// The range of component `c` is `[1, 99]`.
|
||||
fn add_invulnerable(b: u32, c: u32, ) -> Weight {
|
||||
// Proof Size summary in bytes:
|
||||
// Measured: `581 + b * (37 ±0)`
|
||||
// Estimated: `4687 + b * (37 ±0)`
|
||||
// Minimum execution time: 269_126_000 picoseconds.
|
||||
Weight::from_parts(286_711_880, 0)
|
||||
.saturating_add(Weight::from_parts(0, 4687))
|
||||
// Standard Error: 22_887
|
||||
.saturating_add(Weight::from_parts(813_399, 0).saturating_mul(b.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(2))
|
||||
.saturating_add(T::DbWeight::get().writes(1))
|
||||
// Measured: `757 + b * (32 ±0) + c * (53 ±0)`
|
||||
// Estimated: `6287 + b * (37 ±0) + c * (53 ±0)`
|
||||
// Minimum execution time: 52_720_000 picoseconds.
|
||||
Weight::from_parts(56_102_459, 0)
|
||||
.saturating_add(Weight::from_parts(0, 6287))
|
||||
// Standard Error: 12_957
|
||||
.saturating_add(Weight::from_parts(26_422, 0).saturating_mul(b.into()))
|
||||
// Standard Error: 2_456
|
||||
.saturating_add(Weight::from_parts(128_528, 0).saturating_mul(c.into()))
|
||||
.saturating_add(T::DbWeight::get().reads(4))
|
||||
.saturating_add(T::DbWeight::get().writes(3))
|
||||
.saturating_add(Weight::from_parts(0, 37).saturating_mul(b.into()))
|
||||
.saturating_add(Weight::from_parts(0, 53).saturating_mul(c.into()))
|
||||
}
|
||||
/// Storage: CollatorSelection Invulnerables (r:1 w:1)
|
||||
/// Proof: CollatorSelection Invulnerables (max_values: Some(1), max_size: Some(3202), added: 3697, mode: MaxEncodedLen)
|
||||
|
||||
@@ -318,9 +318,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = ConstU32<1000>;
|
||||
type MinCandidates = ConstU32<0>;
|
||||
type MaxInvulnerables = ConstU32<100>;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<1>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
@@ -511,10 +511,7 @@ impl pallet_aura::Config for Runtime {
|
||||
|
||||
parameter_types! {
|
||||
pub const PotId: PalletId = PalletId(*b"PotStake");
|
||||
pub const MaxCandidates: u32 = 1000;
|
||||
pub const MinCandidates: u32 = 5;
|
||||
pub const SessionLength: BlockNumber = 6 * HOURS;
|
||||
pub const MaxInvulnerables: u32 = 100;
|
||||
pub const ExecutiveBody: BodyId = BodyId::Executive;
|
||||
}
|
||||
|
||||
@@ -526,9 +523,9 @@ impl pallet_collator_selection::Config for Runtime {
|
||||
type Currency = Balances;
|
||||
type UpdateOrigin = CollatorSelectionUpdateOrigin;
|
||||
type PotId = PotId;
|
||||
type MaxCandidates = MaxCandidates;
|
||||
type MinCandidates = MinCandidates;
|
||||
type MaxInvulnerables = MaxInvulnerables;
|
||||
type MaxCandidates = ConstU32<100>;
|
||||
type MinEligibleCollators = ConstU32<4>;
|
||||
type MaxInvulnerables = ConstU32<20>;
|
||||
// should be a multiple of session or things will get inconsistent
|
||||
type KickThreshold = Period;
|
||||
type ValidatorId = <Self as frame_system::Config>::AccountId;
|
||||
|
||||
Reference in New Issue
Block a user