Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Authority Discovery to FRAME v2 #8620

Merged
5 commits merged into from
Apr 18, 2021
Merged
Changes from 3 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
116 changes: 85 additions & 31 deletions frame/authority-discovery/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,87 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! # Authority discovery module.
//! # Authority discovery pallet.
//!
//! This module is used by the `client/authority-discovery` and by polkadot's parachain logic
//! This pallet is used by the `client/authority-discovery` and by polkadot's parachain logic
//! to retrieve the current and the next set of authorities.

// Ensure we're `no_std` when compiling for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]

use sp_std::prelude::*;
use frame_support::{decl_module, decl_storage, traits::OneSessionHandler};
use frame_support::traits::OneSessionHandler;
#[cfg(feature = "std")]
use frame_support::traits::GenesisBuild;
use sp_authority_discovery::AuthorityId;

/// The module's config trait.
pub trait Config: frame_system::Config + pallet_session::Config {}
pub use pallet::*;

decl_storage! {
trait Store for Module<T: Config> as AuthorityDiscovery {
/// Keys of the current authority set.
Keys get(fn keys): Vec<AuthorityId>;
/// Keys of the next authority set.
NextKeys get(fn next_keys): Vec<AuthorityId>;
}
add_extra_genesis {
config(keys): Vec<AuthorityId>;
build(|config| Module::<T>::initialize_keys(&config.keys))
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use super::*;

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

#[pallet::config]
/// The pallet's config trait.
pub trait Config: frame_system::Config + pallet_session::Config {}

#[pallet::storage]
#[pallet::getter(fn keys)]
/// Keys of the current authority set.
pub(super) type Keys<T: Config> = StorageValue<
_,
Vec<AuthorityId>,
ValueQuery,
>;

#[pallet::storage]
#[pallet::getter(fn next_keys)]
/// Keys of the next authority set.
pub(super) type NextKeys<T: Config> = StorageValue<
_,
Vec<AuthorityId>,
ValueQuery,
>;

#[pallet::genesis_config]
pub struct GenesisConfig {
pub keys: Vec<AuthorityId>,
}
}

decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {
#[cfg(feature = "std")]
impl Default for GenesisConfig {
fn default() -> Self {
Self {
keys: Default::default(),
}
}
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
Pallet::<T>::initialize_keys(&self.keys)
}
}

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}

#[pallet::call]
impl<T: Config> Pallet<T> {}
}

impl<T: Config> Module<T> {
impl<T: Config> Pallet<T> {
/// Retrieve authority identifiers of the current and next authority set
/// sorted and deduplicated.
pub fn authorities() -> Vec<AuthorityId> {
let mut keys = Keys::get();
let next = NextKeys::get();
let mut keys = Keys::<T>::get();
let next = NextKeys::<T>::get();

keys.extend(next);
keys.sort();
Expand All @@ -64,28 +106,28 @@ impl<T: Config> Module<T> {

/// Retrieve authority identifiers of the current authority set in the original order.
pub fn current_authorities() -> Vec<AuthorityId> {
Keys::get()
Keys::<T>::get()
}

/// Retrieve authority identifiers of the next authority set in the original order.
pub fn next_authorities() -> Vec<AuthorityId> {
NextKeys::get()
NextKeys::<T>::get()
}

fn initialize_keys(keys: &[AuthorityId]) {
if !keys.is_empty() {
assert!(Keys::get().is_empty(), "Keys are already initialized!");
Keys::put(keys);
NextKeys::put(keys);
assert!(Keys::<T>::get().is_empty(), "Keys are already initialized!");
Keys::<T>::put(keys);
NextKeys::<T>::put(keys);
}
}
}

impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> {
type Public = AuthorityId;
}

impl<T: Config> OneSessionHandler<T::AccountId> for Module<T> {
impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
type Key = AuthorityId;

fn on_genesis_session<'a, I: 'a>(authorities: I)
Expand All @@ -102,9 +144,9 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Module<T> {
// Remember who the authorities are for the new and next session.
if changed {
let keys = validators.map(|x| x.1);
Keys::put(keys.collect::<Vec<_>>());
Keys::<T>::put(keys.collect::<Vec<_>>());
let next_keys = queued_validators.map(|x| x.1);
NextKeys::put(next_keys.collect::<Vec<_>>());
NextKeys::<T>::put(next_keys.collect::<Vec<_>>());
}
}

Expand All @@ -113,6 +155,18 @@ impl<T: Config> OneSessionHandler<T::AccountId> for Module<T> {
}
}

#[cfg(feature = "std")]
impl GenesisConfig {
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
/// Direct implementation of `GenesisBuild::assimilate_storage`.
#[deprecated(note = "use [`GenesisBuild::assimilate_storage`] instead")]
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
pub fn assimilate_storage<T: Config>(
&self,
storage: &mut sp_runtime::Storage
) -> Result<(), String> {
<Self as GenesisBuild<T>>::assimilate_storage(self, storage)
}
}

#[cfg(test)]
mod tests {
use crate as pallet_authority_discovery;
Expand Down Expand Up @@ -221,7 +275,7 @@ mod tests {

#[test]
fn authorities_returns_current_and_next_authority_set() {
// The whole authority discovery module ignores account ids, but we still need them for
// The whole authority discovery pallet ignores account ids, but we still need them for
// `pallet_session::OneSessionHandler::on_new_session`, thus its safe to use the same value
// everywhere.
let account_id = AuthorityPair::from_seed_slice(vec![10; 32].as_ref()).unwrap().public();
Expand Down