mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 18:41:03 +00:00
Bounded collator selection pallet (#1337)
* Bounded collator selection pallet * Update pallets/collator-selection/src/lib.rs Co-authored-by: Squirrel <gilescope@gmail.com> Co-authored-by: Squirrel <gilescope@gmail.com>
This commit is contained in:
@@ -89,7 +89,7 @@ pub mod pallet {
|
|||||||
ValidatorRegistration,
|
ValidatorRegistration,
|
||||||
},
|
},
|
||||||
weights::DispatchClass,
|
weights::DispatchClass,
|
||||||
PalletId,
|
BoundedVec, PalletId,
|
||||||
};
|
};
|
||||||
use frame_system::{pallet_prelude::*, Config as SystemConfig};
|
use frame_system::{pallet_prelude::*, Config as SystemConfig};
|
||||||
use pallet_session::SessionManager;
|
use pallet_session::SessionManager;
|
||||||
@@ -123,8 +123,7 @@ pub mod pallet {
|
|||||||
/// Account Identifier from which the internal Pot is generated.
|
/// Account Identifier from which the internal Pot is generated.
|
||||||
type PotId: Get<PalletId>;
|
type PotId: Get<PalletId>;
|
||||||
|
|
||||||
/// Maximum number of candidates that we should have. This is used for benchmarking and is not
|
/// Maximum number of candidates that we should have. This is enforced in code.
|
||||||
/// enforced.
|
|
||||||
///
|
///
|
||||||
/// This does not take into account the invulnerables.
|
/// This does not take into account the invulnerables.
|
||||||
type MaxCandidates: Get<u32>;
|
type MaxCandidates: Get<u32>;
|
||||||
@@ -134,9 +133,7 @@ pub mod pallet {
|
|||||||
/// This does not take into account the invulnerables.
|
/// This does not take into account the invulnerables.
|
||||||
type MinCandidates: Get<u32>;
|
type MinCandidates: Get<u32>;
|
||||||
|
|
||||||
/// Maximum number of invulnerables.
|
/// Maximum number of invulnerables. This is enforced in code.
|
||||||
///
|
|
||||||
/// Used only for benchmarking.
|
|
||||||
type MaxInvulnerables: Get<u32>;
|
type MaxInvulnerables: Get<u32>;
|
||||||
|
|
||||||
// Will be kicked if block is not produced in threshold.
|
// Will be kicked if block is not produced in threshold.
|
||||||
@@ -158,7 +155,9 @@ pub mod pallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Basic information about a collation candidate.
|
/// Basic information about a collation candidate.
|
||||||
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
|
#[derive(
|
||||||
|
PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen,
|
||||||
|
)]
|
||||||
pub struct CandidateInfo<AccountId, Balance> {
|
pub struct CandidateInfo<AccountId, Balance> {
|
||||||
/// Account identifier.
|
/// Account identifier.
|
||||||
pub who: AccountId,
|
pub who: AccountId,
|
||||||
@@ -168,19 +167,22 @@ pub mod pallet {
|
|||||||
|
|
||||||
#[pallet::pallet]
|
#[pallet::pallet]
|
||||||
#[pallet::generate_store(pub(super) trait Store)]
|
#[pallet::generate_store(pub(super) trait Store)]
|
||||||
#[pallet::without_storage_info]
|
|
||||||
pub struct Pallet<T>(_);
|
pub struct Pallet<T>(_);
|
||||||
|
|
||||||
/// The invulnerable, fixed collators.
|
/// The invulnerable, fixed collators.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn invulnerables)]
|
#[pallet::getter(fn invulnerables)]
|
||||||
pub type Invulnerables<T: Config> = StorageValue<_, Vec<T::AccountId>, ValueQuery>;
|
pub type Invulnerables<T: Config> =
|
||||||
|
StorageValue<_, BoundedVec<T::AccountId, T::MaxInvulnerables>, ValueQuery>;
|
||||||
|
|
||||||
/// The (community, limited) collation candidates.
|
/// The (community, limited) collation candidates.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn candidates)]
|
#[pallet::getter(fn candidates)]
|
||||||
pub type Candidates<T: Config> =
|
pub type Candidates<T: Config> = StorageValue<
|
||||||
StorageValue<_, Vec<CandidateInfo<T::AccountId, BalanceOf<T>>>, ValueQuery>;
|
_,
|
||||||
|
BoundedVec<CandidateInfo<T::AccountId, BalanceOf<T>>, T::MaxCandidates>,
|
||||||
|
ValueQuery,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Last block authored by collator.
|
/// Last block authored by collator.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
@@ -230,10 +232,9 @@ pub mod pallet {
|
|||||||
"duplicate invulnerables in genesis."
|
"duplicate invulnerables in genesis."
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(
|
let bounded_invulnerables =
|
||||||
T::MaxInvulnerables::get() >= (self.invulnerables.len() as u32),
|
BoundedVec::<_, T::MaxInvulnerables>::try_from(self.invulnerables.clone())
|
||||||
"genesis invulnerables are more than T::MaxInvulnerables",
|
.expect("genesis invulnerables are more than T::MaxInvulnerables");
|
||||||
);
|
|
||||||
assert!(
|
assert!(
|
||||||
T::MaxCandidates::get() >= self.desired_candidates,
|
T::MaxCandidates::get() >= self.desired_candidates,
|
||||||
"genesis desired_candidates are more than T::MaxCandidates",
|
"genesis desired_candidates are more than T::MaxCandidates",
|
||||||
@@ -241,7 +242,7 @@ pub mod pallet {
|
|||||||
|
|
||||||
<DesiredCandidates<T>>::put(&self.desired_candidates);
|
<DesiredCandidates<T>>::put(&self.desired_candidates);
|
||||||
<CandidacyBond<T>>::put(&self.candidacy_bond);
|
<CandidacyBond<T>>::put(&self.candidacy_bond);
|
||||||
<Invulnerables<T>>::put(&self.invulnerables);
|
<Invulnerables<T>>::put(bounded_invulnerables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +271,8 @@ pub mod pallet {
|
|||||||
AlreadyCandidate,
|
AlreadyCandidate,
|
||||||
/// User is not a candidate
|
/// User is not a candidate
|
||||||
NotCandidate,
|
NotCandidate,
|
||||||
|
/// Too many invulnerables
|
||||||
|
TooManyInvulnerables,
|
||||||
/// User is already an Invulnerable
|
/// User is already an Invulnerable
|
||||||
AlreadyInvulnerable,
|
AlreadyInvulnerable,
|
||||||
/// Account has no associated validator ID
|
/// Account has no associated validator ID
|
||||||
@@ -290,15 +293,11 @@ pub mod pallet {
|
|||||||
new: Vec<T::AccountId>,
|
new: Vec<T::AccountId>,
|
||||||
) -> DispatchResultWithPostInfo {
|
) -> DispatchResultWithPostInfo {
|
||||||
T::UpdateOrigin::ensure_origin(origin)?;
|
T::UpdateOrigin::ensure_origin(origin)?;
|
||||||
// we trust origin calls, this is just a for more accurate benchmarking
|
let bounded_invulnerables = BoundedVec::<_, T::MaxInvulnerables>::try_from(new)
|
||||||
if (new.len() as u32) > T::MaxInvulnerables::get() {
|
.map_err(|_| Error::<T>::TooManyInvulnerables)?;
|
||||||
log::warn!(
|
|
||||||
"invulnerables > T::MaxInvulnerables; you might need to run benchmarks again"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the invulnerables have associated validator keys before they are set
|
// check if the invulnerables have associated validator keys before they are set
|
||||||
for account_id in &new {
|
for account_id in bounded_invulnerables.iter() {
|
||||||
let validator_key = T::ValidatorIdOf::convert(account_id.clone())
|
let validator_key = T::ValidatorIdOf::convert(account_id.clone())
|
||||||
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
|
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
|
||||||
ensure!(
|
ensure!(
|
||||||
@@ -307,8 +306,10 @@ pub mod pallet {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
<Invulnerables<T>>::put(&new);
|
<Invulnerables<T>>::put(&bounded_invulnerables);
|
||||||
Self::deposit_event(Event::NewInvulnerables { invulnerables: new });
|
Self::deposit_event(Event::NewInvulnerables {
|
||||||
|
invulnerables: bounded_invulnerables.to_vec(),
|
||||||
|
});
|
||||||
Ok(().into())
|
Ok(().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +373,7 @@ pub mod pallet {
|
|||||||
Err(Error::<T>::AlreadyCandidate)?
|
Err(Error::<T>::AlreadyCandidate)?
|
||||||
} else {
|
} else {
|
||||||
T::Currency::reserve(&who, deposit)?;
|
T::Currency::reserve(&who, deposit)?;
|
||||||
candidates.push(incoming);
|
candidates.try_push(incoming).map_err(|_| Error::<T>::TooManyCandidates)?;
|
||||||
<LastAuthoredBlock<T>>::insert(
|
<LastAuthoredBlock<T>>::insert(
|
||||||
who.clone(),
|
who.clone(),
|
||||||
frame_system::Pallet::<T>::block_number() + T::KickThreshold::get(),
|
frame_system::Pallet::<T>::block_number() + T::KickThreshold::get(),
|
||||||
@@ -430,8 +431,10 @@ pub mod pallet {
|
|||||||
/// Assemble the current set of candidates and invulnerables into the next collator set.
|
/// Assemble the current set of candidates and invulnerables into the next collator set.
|
||||||
///
|
///
|
||||||
/// This is done on the fly, as frequent as we are told to do so, as the session manager.
|
/// This is done on the fly, as frequent as we are told to do so, as the session manager.
|
||||||
pub fn assemble_collators(candidates: Vec<T::AccountId>) -> Vec<T::AccountId> {
|
pub fn assemble_collators(
|
||||||
let mut collators = Self::invulnerables();
|
candidates: BoundedVec<T::AccountId, T::MaxCandidates>,
|
||||||
|
) -> Vec<T::AccountId> {
|
||||||
|
let mut collators = Self::invulnerables().to_vec();
|
||||||
collators.extend(candidates);
|
collators.extend(candidates);
|
||||||
collators
|
collators
|
||||||
}
|
}
|
||||||
@@ -439,8 +442,8 @@ pub mod pallet {
|
|||||||
/// Kicks out candidates that did not produce a block in the kick threshold
|
/// Kicks out candidates that did not produce a block in the kick threshold
|
||||||
/// and refund their deposits.
|
/// and refund their deposits.
|
||||||
pub fn kick_stale_candidates(
|
pub fn kick_stale_candidates(
|
||||||
candidates: Vec<CandidateInfo<T::AccountId, BalanceOf<T>>>,
|
candidates: BoundedVec<CandidateInfo<T::AccountId, BalanceOf<T>>, T::MaxCandidates>,
|
||||||
) -> Vec<T::AccountId> {
|
) -> BoundedVec<T::AccountId, T::MaxCandidates> {
|
||||||
let now = frame_system::Pallet::<T>::block_number();
|
let now = frame_system::Pallet::<T>::block_number();
|
||||||
let kick_threshold = T::KickThreshold::get();
|
let kick_threshold = T::KickThreshold::get();
|
||||||
candidates
|
candidates
|
||||||
@@ -461,7 +464,9 @@ pub mod pallet {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect::<Vec<_>>()
|
||||||
|
.try_into()
|
||||||
|
.expect("filter_map operation can't result in a bounded vec larger than its original; qed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user