-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Bounded Validators / Authorities in New Sessions #8640
Changes from all commits
2ae0c01
fb14e40
fcf8809
0b21a93
530c4a7
3885e7a
41e9820
307e969
a8a68cd
6359f64
8f6ae0c
5d74819
7879998
5383e00
f9491e2
64bd953
a9ba4eb
f643584
ce8d0c3
8e96900
5514576
b7228bb
58756f5
3ac6283
c32d358
2ffa620
5e6a814
28ca319
b99849b
92083f3
575294f
dadc746
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,10 +37,14 @@ | |
|
||
#![cfg_attr(not(feature = "std"), no_std)] | ||
|
||
use sp_std::prelude::*; | ||
use sp_std::{ | ||
prelude::*, | ||
convert::TryInto, | ||
}; | ||
use codec::{Encode, Decode}; | ||
use frame_support::{ | ||
Parameter, traits::{Get, FindAuthor, OneSessionHandler, OnTimestampSet}, ConsensusEngineId, | ||
Parameter, BoundedVec, ConsensusEngineId, | ||
traits::{Get, FindAuthor, OneSessionHandler, OnTimestampSet}, | ||
}; | ||
use sp_runtime::{ | ||
RuntimeAppPublic, | ||
|
@@ -64,11 +68,21 @@ pub mod pallet { | |
pub trait Config: pallet_timestamp::Config + frame_system::Config { | ||
/// The identifier type for an authority. | ||
type AuthorityId: Member + Parameter + RuntimeAppPublic + Default + MaybeSerializeDeserialize; | ||
|
||
/// The maximum number of authorities that can be registered in this pallet. | ||
type MaxAuthorities: Get<u32>; | ||
} | ||
|
||
#[pallet::pallet] | ||
pub struct Pallet<T>(sp_std::marker::PhantomData<T>); | ||
|
||
// Errors inform users that something went wrong. | ||
#[pallet::error] | ||
pub enum Error<T> { | ||
/// You are trying to add more authorities than allowed in the pallet configuration. | ||
TooManyAuthorities, | ||
} | ||
|
||
#[pallet::hooks] | ||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> { | ||
fn on_initialize(_: T::BlockNumber) -> Weight { | ||
|
@@ -93,7 +107,11 @@ pub mod pallet { | |
/// The current authority set. | ||
#[pallet::storage] | ||
#[pallet::getter(fn authorities)] | ||
pub(super) type Authorities<T: Config> = StorageValue<_, Vec<T::AuthorityId>, ValueQuery>; | ||
pub(super) type Authorities<T: Config> = StorageValue< | ||
_, | ||
BoundedVec<T::AuthorityId, T::MaxAuthorities>, | ||
ValueQuery, | ||
>; | ||
|
||
/// The current slot of this block. | ||
/// | ||
|
@@ -123,20 +141,24 @@ pub mod pallet { | |
} | ||
|
||
impl<T: Config> Pallet<T> { | ||
fn change_authorities(new: Vec<T::AuthorityId>) { | ||
fn change_authorities(new: BoundedVec<T::AuthorityId, T::MaxAuthorities>) { | ||
<Authorities<T>>::put(&new); | ||
|
||
let log: DigestItem<T::Hash> = DigestItem::Consensus( | ||
AURA_ENGINE_ID, | ||
ConsensusLog::AuthoritiesChange(new).encode() | ||
ConsensusLog::AuthoritiesChange(new.to_vec()).encode() | ||
); | ||
<frame_system::Pallet<T>>::deposit_log(log.into()); | ||
} | ||
|
||
fn initialize_authorities(authorities: &[T::AuthorityId]) { | ||
if !authorities.is_empty() { | ||
assert!(<Authorities<T>>::get().is_empty(), "Authorities are already initialized!"); | ||
<Authorities<T>>::put(authorities); | ||
let bounded_authorities: BoundedVec<T::AuthorityId, T::MaxAuthorities> = authorities | ||
.to_vec() | ||
.try_into() | ||
.expect("Too many initial authorities!"); | ||
<Authorities<T>>::put(&bounded_authorities); | ||
} | ||
} | ||
|
||
|
@@ -165,7 +187,7 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> { | |
type Public = T::AuthorityId; | ||
} | ||
|
||
impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> { | ||
impl<T: Config> OneSessionHandler<T::AccountId, T::MaxAuthorities> for Pallet<T> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is very very good because now if babe implements There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But the missing point is:
I think we should prevent this at compile time but I don't it in the current state of the PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh no we have this guarantee as well, because of
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the point here is that there should be a single global config of Anything else would result in a compile error, which ensures that these systems are working together correctly. I dont think it would ever be that session and babe would have different max authorities, but maybe @andresilva could give insight There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, we should have an uniform number of authorities throughout the whole runtime. |
||
type Key = T::AuthorityId; | ||
|
||
fn on_genesis_session<'a, I: 'a>(validators: I) | ||
|
@@ -181,9 +203,15 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> { | |
// instant changes | ||
if changed { | ||
let next_authorities = validators.map(|(_, k)| k).collect::<Vec<_>>(); | ||
// Truncate any extra that would not fit into storage... | ||
let bounded_next_authorities = BoundedVec::<T::AuthorityId, T::MaxAuthorities>::truncating_from( | ||
next_authorities, | ||
Some("Aura New Session"), | ||
); | ||
|
||
let last_authorities = Self::authorities(); | ||
if next_authorities != last_authorities { | ||
Self::change_authorities(next_authorities); | ||
if bounded_next_authorities != last_authorities { | ||
Self::change_authorities(bounded_next_authorities); | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably we should document that this should be the upper bound of what
Staking::validator_count
is ever going to be.