Migrate pallet-session to the new pallet macro (#9796)

* Migrate pallet-session to the new pallet macro

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Remove old macros

Signed-off-by: koushiro <koushiro.cqx@gmail.com>

* Fix

Signed-off-by: koushiro <koushiro.cqx@gmail.com>
This commit is contained in:
Qinxuan Chen
2021-09-28 11:12:57 +08:00
committed by GitHub
parent 6ec82c7a83
commit 7f550d6dd2
15 changed files with 314 additions and 266 deletions
+2 -1
View File
@@ -19,7 +19,8 @@ use std::vec;
use beefy_primitives::mmr::MmrLeafVersion;
use frame_support::{
construct_runtime, parameter_types, sp_io::TestExternalities, BasicExternalities,
construct_runtime, parameter_types, sp_io::TestExternalities, traits::GenesisBuild,
BasicExternalities,
};
use sp_core::{Hasher, H256};
use sp_runtime::{
+2 -1
View File
@@ -18,7 +18,8 @@
use std::vec;
use frame_support::{
construct_runtime, parameter_types, sp_io::TestExternalities, BasicExternalities,
construct_runtime, parameter_types, sp_io::TestExternalities, traits::GenesisBuild,
BasicExternalities,
};
use sp_core::H256;
use sp_runtime::{
+13 -11
View File
@@ -13,38 +13,40 @@ readme = "README.md"
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
"derive",
] }
log = { version = "0.4.0", default-features = false }
impl-trait-for-tuples = "0.2.1"
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
sp-std = { version = "4.0.0-dev", default-features = false, path = "../../primitives/std" }
sp-core = { version = "4.0.0-dev", default-features = false, path = "../../primitives/core" }
sp-io = { version = "4.0.0-dev", default-features = false, path = "../../primitives/io" }
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../primitives/runtime" }
sp-session = { version = "4.0.0-dev", default-features = false, path = "../../primitives/session" }
sp-staking = { version = "4.0.0-dev", default-features = false, path = "../../primitives/staking" }
sp-trie = { version = "4.0.0-dev", default-features = false, path = "../../primitives/trie", optional = true }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" }
pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../timestamp" }
sp-trie = { version = "4.0.0-dev", optional = true, default-features = false, path = "../../primitives/trie" }
log = { version = "0.4.0", default-features = false }
impl-trait-for-tuples = "0.2.1"
[features]
default = ["std", "historical"]
historical = ["sp-trie"]
std = [
"log/std",
"codec/std",
"scale-info/std",
"sp-std/std",
"sp-io/std",
"frame-support/std",
"sp-core/std",
"sp-io/std",
"sp-runtime/std",
"sp-session/std",
"sp-staking/std",
"pallet-timestamp/std",
"sp-trie/std",
"log/std",
"frame-support/std",
"frame-system/std",
"pallet-timestamp/std",
]
try-runtime = ["frame-support/try-runtime"]
+4 -4
View File
@@ -1,11 +1,11 @@
# Session Module
# Session Pallet
The Session module allows validators to manage their session keys, provides a function for changing
the session length, and handles session rotation.
- [`session::Trait`](https://docs.rs/pallet-session/latest/pallet_session/trait.Config.html)
- [`Call`](https://docs.rs/pallet-session/latest/pallet_session/enum.Call.html)
- [`Module`](https://docs.rs/pallet-session/latest/pallet_session/struct.Module.html)
- [`Pallet`](https://docs.rs/pallet-session/latest/pallet_session/struct.Pallet.html)
## Overview
@@ -72,11 +72,11 @@ The [Staking pallet](https://docs.rs/pallet-staking/latest/pallet_staking/) uses
use pallet_session as session;
fn validators<T: pallet_session::Config>() -> Vec<<T as pallet_session::Config>::ValidatorId> {
<pallet_session::Module<T>>::validators()
<pallet_session::Pallet<T>>::validators()
}
```
## Related Modules
## Related Pallets
- [Staking](https://docs.rs/pallet-staking/latest/pallet_staking/)
+16 -18
View File
@@ -13,39 +13,37 @@ readme = "README.md"
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" }
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
pallet-staking = { version = "4.0.0-dev", default-features = false, features = [
"runtime-benchmarks",
], path = "../../staking" }
pallet-session = { version = "4.0.0-dev", default-features = false, path = "../../session" }
rand = { version = "0.7.2", default-features = false }
sp-std = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/std" }
sp-runtime = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/runtime" }
sp-session = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/session" }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, path = "../../benchmarking" }
frame-support = { version = "4.0.0-dev", default-features = false, path = "../../support" }
frame-system = { version = "4.0.0-dev", default-features = false, path = "../../system" }
pallet-session = { version = "4.0.0-dev", default-features = false, path = "../../session" }
pallet-staking = { version = "4.0.0-dev", default-features = false, features = ["runtime-benchmarks"], path = "../../staking" }
[dev-dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", features = [
"derive",
] }
codec = { package = "parity-scale-codec", version = "2.0.0", features = ["derive"] }
scale-info = "1.0"
sp-core = { version = "4.0.0-dev", path = "../../../primitives/core" }
pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" }
sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" }
pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" }
pallet-balances = { version = "4.0.0-dev", path = "../../balances" }
pallet-timestamp = { version = "4.0.0-dev", path = "../../timestamp" }
pallet-staking-reward-curve = { version = "4.0.0-dev", path = "../../staking/reward-curve" }
frame-election-provider-support = { version = "4.0.0-dev", path = "../../election-provider-support" }
[features]
default = ["std"]
std = [
"sp-std/std",
"sp-session/std",
"sp-runtime/std",
"frame-system/std",
"sp-session/std",
"frame-benchmarking/std",
"frame-support/std",
"pallet-staking/std",
"frame-system/std",
"pallet-session/std",
"pallet-staking/std",
]
@@ -30,7 +30,7 @@ use frame_support::{
traits::{KeyOwnerProofSystem, OnInitialize},
};
use frame_system::RawOrigin;
use pallet_session::{historical::Module as Historical, Module as Session, *};
use pallet_session::{historical::Module as Historical, Pallet as Session, *};
use pallet_staking::{
benchmarking::create_validator_with_nominators, testing_utils::create_validators,
RewardDestination,
@@ -39,7 +39,7 @@ use sp_runtime::traits::{One, StaticLookup};
const MAX_VALIDATORS: u32 = 1000;
pub struct Pallet<T: Config>(pallet_session::Module<T>);
pub struct Pallet<T: Config>(pallet_session::Pallet<T>);
pub trait Config:
pallet_session::Config + pallet_session::historical::Config + pallet_staking::Config
{
@@ -47,7 +47,7 @@ pub trait Config:
impl<T: Config> OnInitialize<T::BlockNumber> for Pallet<T> {
fn on_initialize(n: T::BlockNumber) -> frame_support::weights::Weight {
pallet_session::Module::<T>::on_initialize(n)
pallet_session::Pallet::<T>::on_initialize(n)
}
}
@@ -26,7 +26,7 @@
//! These roots and proofs of inclusion can be generated at any time during the current session.
//! Afterwards, the proofs can be fed to a consensus module when reporting misbehavior.
use super::{Module as SessionModule, SessionIndex};
use super::{Pallet as SessionModule, SessionIndex};
use codec::{Decode, Encode};
use frame_support::{
decl_module, decl_storage, print,
@@ -114,11 +114,11 @@ impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
type ValidatorIdOf = T::ValidatorIdOf;
fn session_index() -> sp_staking::SessionIndex {
super::Module::<T>::current_index()
super::Pallet::<T>::current_index()
}
fn validators() -> Vec<Self::ValidatorId> {
super::Module::<T>::validators()
super::Pallet::<T>::validators()
}
}
@@ -366,11 +366,13 @@ pub(crate) mod tests {
use crate::mock::{
force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS,
};
use sp_runtime::{key_types::DUMMY, testing::UintAuthorityId};
use frame_support::{
traits::{KeyOwnerProofSystem, OnInitialize},
traits::{GenesisBuild, KeyOwnerProofSystem, OnInitialize},
BasicExternalities,
};
use sp_runtime::{key_types::DUMMY, testing::UintAuthorityId};
type Historical = Module<Test>;
@@ -30,15 +30,11 @@ use sp_runtime::{
KeyTypeId,
};
use sp_session::MembershipProof;
use super::{
super::{Pallet as SessionModule, SessionIndex},
Config, IdentificationTuple, ProvingTrie,
};
use super::shared;
use sp_std::prelude::*;
use super::{shared, Config, IdentificationTuple, ProvingTrie};
use crate::{Pallet as SessionModule, SessionIndex};
/// A set of validators, which was used for a fixed session index.
struct ValidatorSet<T: Config> {
validator_set: Vec<IdentificationTuple<T>>,
@@ -142,23 +138,24 @@ pub fn keep_newest<T: Config>(n_to_keep: usize) {
#[cfg(test)]
mod tests {
use super::{
super::{onchain, Module},
*,
};
use crate::mock::{
force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS,
use super::*;
use crate::{
historical::{onchain, Module},
mock::{force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS},
};
use codec::Encode;
use frame_support::traits::{KeyOwnerProofSystem, OnInitialize};
use sp_core::{
crypto::key_types::DUMMY,
offchain::{testing::TestOffchainExt, OffchainDbExt, OffchainWorkerExt, StorageKind},
};
use frame_support::BasicExternalities;
use sp_runtime::testing::UintAuthorityId;
use frame_support::{
traits::{GenesisBuild, KeyOwnerProofSystem, OnInitialize},
BasicExternalities,
};
type Historical = Module<Test>;
pub fn new_test_ext() -> sp_io::TestExternalities {
@@ -19,15 +19,11 @@
use codec::Encode;
use sp_runtime::traits::Convert;
use super::{
super::{Config as SessionConfig, Pallet as SessionModule, SessionIndex},
Config as HistoricalConfig,
};
use super::shared;
use sp_std::prelude::*;
use super::{shared, Config as HistoricalConfig};
use crate::{Config as SessionConfig, Pallet as SessionModule, SessionIndex};
/// Store the validator-set associated to the `session_index` to the off-chain database.
///
/// Further processing is then done [`off-chain side`](super::offchain).
@@ -18,8 +18,8 @@
//! Shared logic between on-chain and off-chain components used for slashing using an off-chain
//! worker.
use super::SessionIndex;
use codec::Encode;
use sp_staking::SessionIndex;
use sp_std::prelude::*;
pub(super) const PREFIX: &[u8] = b"session_historical";
+238 -191
View File
@@ -15,14 +15,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! # Session Module
//! # Session Pallet
//!
//! The Session module allows validators to manage their session keys, provides a function for
//! The Session pallet allows validators to manage their session keys, provides a function for
//! changing the session length, and handles session rotation.
//!
//! - [`Config`]
//! - [`Call`]
//! - [`Module`]
//! - [`Pallet`]
//!
//! ## Overview
//!
@@ -95,12 +95,12 @@
//! use pallet_session as session;
//!
//! fn validators<T: pallet_session::Config>() -> Vec<<T as pallet_session::Config>::ValidatorId> {
//! <pallet_session::Module<T>>::validators()
//! <pallet_session::Pallet<T>>::validators()
//! }
//! # fn main(){}
//! ```
//!
//! ## Related Modules
//! ## Related Pallets
//!
//! - [Staking](../pallet_staking/index.html)
@@ -114,22 +114,9 @@ mod mock;
mod tests;
pub mod weights;
use codec::{Decode, MaxEncodedLen};
use frame_support::{
decl_error, decl_event, decl_module, decl_storage,
dispatch::{self, DispatchError, DispatchResult},
ensure,
traits::{
EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get, OneSessionHandler,
ValidatorRegistration, ValidatorSet,
},
weights::Weight,
ConsensusEngineId, Parameter,
};
use frame_system::ensure_signed;
use sp_runtime::{
traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero},
KeyTypeId, Perbill, Permill, RuntimeAppPublic,
ConsensusEngineId, KeyTypeId, Perbill, Permill, RuntimeAppPublic,
};
use sp_staking::SessionIndex;
use sp_std::{
@@ -137,6 +124,20 @@ use sp_std::{
ops::{Rem, Sub},
prelude::*,
};
use frame_support::{
codec::{Decode, MaxEncodedLen},
dispatch::{DispatchError, DispatchResult},
ensure,
traits::{
EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get, OneSessionHandler,
StorageVersion, ValidatorRegistration, ValidatorSet,
},
weights::Weight,
Parameter,
};
pub use pallet::*;
pub use weights::WeightInfo;
/// Decides whether the session should be ended.
@@ -228,7 +229,7 @@ pub trait SessionManager<ValidatorId> {
///
/// Even if the validator-set is the same as before, if any underlying economic conditions have
/// changed (i.e. stake-weights), the new validator set must be returned. This is necessary for
/// consensus engines making use of the session module to issue a validator-set change so
/// consensus engines making use of the session pallet to issue a validator-set change so
/// misbehavior can be provably associated with the new economic conditions as opposed to the
/// old. The returned validator set, if any, will not be applied until `new_index`. `new_index`
/// is strictly greater than from previous call.
@@ -280,7 +281,7 @@ pub trait SessionHandler<ValidatorId> {
fn on_genesis_session<Ks: OpaqueKeys>(validators: &[(ValidatorId, Ks)]);
/// Session set has changed; act appropriately. Note that this can be called
/// before initialization of your module.
/// before initialization of your pallet.
///
/// `changed` is true whenever any of the session keys or underlying economic
/// identities or weightings behind those keys has changed.
@@ -356,86 +357,83 @@ impl<AId> SessionHandler<AId> for TestSessionHandler {
fn on_disabled(_: usize) {}
}
impl<T: Config> ValidatorRegistration<T::ValidatorId> for Module<T> {
fn is_registered(id: &T::ValidatorId) -> bool {
Self::load_keys(id).is_some()
}
}
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event> + Into<<Self as frame_system::Config>::Event>;
/// The current storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
/// A stable ID for a validator.
type ValidatorId: Member + Parameter + MaxEncodedLen;
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(_);
/// A conversion from account ID to validator ID.
///
/// Its cost must be at most one storage read.
type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;
#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event> + IsType<<Self as frame_system::Config>::Event>;
/// Indicator for when to end the session.
type ShouldEndSession: ShouldEndSession<Self::BlockNumber>;
/// A stable ID for a validator.
type ValidatorId: Member + Parameter + MaybeSerializeDeserialize + MaxEncodedLen;
/// Something that can predict the next session rotation. This should typically come from the
/// same logical unit that provides [`ShouldEndSession`], yet, it gives a best effort estimate.
/// It is helpful to implement [`EstimateNextNewSession`].
type NextSessionRotation: EstimateNextSessionRotation<Self::BlockNumber>;
/// Handler for managing new session.
type SessionManager: SessionManager<Self::ValidatorId>;
/// Handler when a session has changed.
type SessionHandler: SessionHandler<Self::ValidatorId>;
/// The keys.
type Keys: OpaqueKeys + Member + Parameter + Default;
/// The fraction of validators set that is safe to be disabled.
///
/// After the threshold is reached `disabled` method starts to return true,
/// which in combination with `pallet_staking` forces a new era.
type DisabledValidatorsThreshold: Get<Perbill>;
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}
decl_storage! {
trait Store for Module<T: Config> as Session {
/// The current set of validators.
Validators get(fn validators): Vec<T::ValidatorId>;
/// Current index of the session.
CurrentIndex get(fn current_index): SessionIndex;
/// True if the underlying economic identities or weighting behind the validators
/// has changed in the queued validator set.
QueuedChanged: bool;
/// The queued keys for the next session. When the next session begins, these keys
/// will be used to determine the validator's session keys.
QueuedKeys get(fn queued_keys): Vec<(T::ValidatorId, T::Keys)>;
/// Indices of disabled validators.
/// A conversion from account ID to validator ID.
///
/// The set is cleared when `on_session_ending` returns a new set of identities.
DisabledValidators get(fn disabled_validators): Vec<u32>;
/// Its cost must be at most one storage read.
type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;
/// The next session keys for a validator.
NextKeys: map hasher(twox_64_concat) T::ValidatorId => Option<T::Keys>;
/// Indicator for when to end the session.
type ShouldEndSession: ShouldEndSession<Self::BlockNumber>;
/// The owner of a key. The key is the `KeyTypeId` + the encoded key.
KeyOwner: map hasher(twox_64_concat) (KeyTypeId, Vec<u8>) => Option<T::ValidatorId>;
/// Something that can predict the next session rotation. This should typically come from
/// the same logical unit that provides [`ShouldEndSession`], yet, it gives a best effort
/// estimate. It is helpful to implement [`EstimateNextNewSession`].
type NextSessionRotation: EstimateNextSessionRotation<Self::BlockNumber>;
/// Handler for managing new session.
type SessionManager: SessionManager<Self::ValidatorId>;
/// Handler when a session has changed.
type SessionHandler: SessionHandler<Self::ValidatorId>;
/// The keys.
type Keys: OpaqueKeys + Member + Parameter + Default + MaybeSerializeDeserialize;
/// The fraction of validators set that is safe to be disabled.
///
/// After the threshold is reached `disabled` method starts to return true,
/// which in combination with `pallet_staking` forces a new era.
type DisabledValidatorsThreshold: Get<Perbill>;
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}
add_extra_genesis {
config(keys): Vec<(T::AccountId, T::ValidatorId, T::Keys)>;
build(|config: &GenesisConfig<T>| {
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub keys: Vec<(T::AccountId, T::ValidatorId, T::Keys)>,
}
#[cfg(feature = "std")]
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
Self { keys: Default::default() }
}
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
if T::SessionHandler::KEY_TYPE_IDS.len() != T::Keys::key_ids().len() {
panic!("Number of keys in session handler and session keys does not match");
}
T::SessionHandler::KEY_TYPE_IDS.iter().zip(T::Keys::key_ids()).enumerate()
T::SessionHandler::KEY_TYPE_IDS
.iter()
.zip(T::Keys::key_ids())
.enumerate()
.for_each(|(i, (sk, kk))| {
if sk != kk {
panic!(
@@ -445,8 +443,8 @@ decl_storage! {
}
});
for (account, val, keys) in config.keys.iter().cloned() {
<Module<T>>::inner_set_keys(&val, keys)
for (account, val, keys) in self.keys.iter().cloned() {
<Pallet<T>>::inner_set_keys(&val, keys)
.expect("genesis config must not contain duplicates; qed");
if frame_system::Pallet::<T>::inc_consumers(&account).is_err() {
// This will leak a provider reference, however it only happens once (at
@@ -457,25 +455,30 @@ decl_storage! {
}
}
let initial_validators_0 = T::SessionManager::new_session_genesis(0)
.unwrap_or_else(|| {
frame_support::print("No initial validator provided by `SessionManager`, use \
session config keys to generate initial validator set.");
config.keys.iter().map(|x| x.1.clone()).collect()
let initial_validators_0 =
T::SessionManager::new_session_genesis(0).unwrap_or_else(|| {
frame_support::print(
"No initial validator provided by `SessionManager`, use \
session config keys to generate initial validator set.",
);
self.keys.iter().map(|x| x.1.clone()).collect()
});
assert!(!initial_validators_0.is_empty(), "Empty validator set for session 0 in genesis block!");
assert!(
!initial_validators_0.is_empty(),
"Empty validator set for session 0 in genesis block!"
);
let initial_validators_1 = T::SessionManager::new_session_genesis(1)
.unwrap_or_else(|| initial_validators_0.clone());
assert!(!initial_validators_1.is_empty(), "Empty validator set for session 1 in genesis block!");
assert!(
!initial_validators_1.is_empty(),
"Empty validator set for session 1 in genesis block!"
);
let queued_keys: Vec<_> = initial_validators_1
.iter()
.cloned()
.map(|v| (
v.clone(),
<Module<T>>::load_keys(&v).unwrap_or_default(),
))
.map(|v| (v.clone(), <Pallet<T>>::load_keys(&v).unwrap_or_default()))
.collect();
// Tell everyone about the genesis session keys
@@ -485,21 +488,62 @@ decl_storage! {
<QueuedKeys<T>>::put(queued_keys);
T::SessionManager::start_session(0);
});
}
}
}
decl_event!(
/// The current set of validators.
#[pallet::storage]
#[pallet::getter(fn validators)]
pub type Validators<T: Config> = StorageValue<_, Vec<T::ValidatorId>, ValueQuery>;
/// Current index of the session.
#[pallet::storage]
#[pallet::getter(fn current_index)]
pub type CurrentIndex<T> = StorageValue<_, SessionIndex, ValueQuery>;
/// True if the underlying economic identities or weighting behind the validators
/// has changed in the queued validator set.
#[pallet::storage]
pub type QueuedChanged<T> = StorageValue<_, bool, ValueQuery>;
/// The queued keys for the next session. When the next session begins, these keys
/// will be used to determine the validator's session keys.
#[pallet::storage]
#[pallet::getter(fn queued_keys)]
pub type QueuedKeys<T: Config> = StorageValue<_, Vec<(T::ValidatorId, T::Keys)>, ValueQuery>;
/// Indices of disabled validators.
///
/// The set is cleared when `on_session_ending` returns a new set of identities.
#[pallet::storage]
#[pallet::getter(fn disabled_validators)]
pub type DisabledValidators<T> = StorageValue<_, Vec<u32>, ValueQuery>;
/// The next session keys for a validator.
#[pallet::storage]
pub type NextKeys<T: Config> =
StorageMap<_, Twox64Concat, T::ValidatorId, T::Keys, OptionQuery>;
/// The owner of a key. The key is the `KeyTypeId` + the encoded key.
#[pallet::storage]
pub type KeyOwner<T: Config> =
StorageMap<_, Twox64Concat, (KeyTypeId, Vec<u8>), T::ValidatorId, OptionQuery>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event {
/// New session has happened. Note that the argument is the \[session_index\], not the
/// block number as the type might suggest.
NewSession(SessionIndex),
}
);
decl_error! {
/// Error for the session module.
pub enum Error for Module<T: Config> {
/// Old name generated by `decl_event`.
#[deprecated(note = "use `Event` instead")]
pub type RawEvent = Event;
/// Error for the session pallet.
#[pallet::error]
pub enum Error<T> {
/// Invalid ownership proof.
InvalidProof,
/// No associated validator ID for account.
@@ -511,57 +555,9 @@ decl_error! {
/// Key setting account is not live, so it's impossible to associate keys.
NoAccount,
}
}
decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {
type Error = Error<T>;
fn deposit_event() = default;
/// Sets the session key(s) of the function caller to `keys`.
/// Allows an account to set its session key prior to becoming a validator.
/// This doesn't take effect until the next session.
///
/// The dispatch origin of this function must be signed.
///
/// # <weight>
/// - Complexity: `O(1)`
/// Actual cost depends on the number of length of `T::Keys::key_ids()` which is fixed.
/// - DbReads: `origin account`, `T::ValidatorIdOf`, `NextKeys`
/// - DbWrites: `origin account`, `NextKeys`
/// - DbReads per key id: `KeyOwner`
/// - DbWrites per key id: `KeyOwner`
/// # </weight>
#[weight = T::WeightInfo::set_keys()]
pub fn set_keys(origin, keys: T::Keys, proof: Vec<u8>) -> dispatch::DispatchResult {
let who = ensure_signed(origin)?;
ensure!(keys.ownership_proof_is_valid(&proof), Error::<T>::InvalidProof);
Self::do_set_keys(&who, keys)?;
Ok(())
}
/// Removes any session key(s) of the function caller.
/// This doesn't take effect until the next session.
///
/// The dispatch origin of this function must be signed.
///
/// # <weight>
/// - Complexity: `O(1)` in number of key types.
/// Actual cost depends on the number of length of `T::Keys::key_ids()` which is fixed.
/// - DbReads: `T::ValidatorIdOf`, `NextKeys`, `origin account`
/// - DbWrites: `NextKeys`, `origin account`
/// - DbWrites per key id: `KeyOwner`
/// # </weight>
#[weight = T::WeightInfo::purge_keys()]
pub fn purge_keys(origin) {
let who = ensure_signed(origin)?;
Self::do_purge_keys(&who)?;
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
/// Called when a block is initialized. Will rotate session if it is the last
/// block of the current session.
fn on_initialize(n: T::BlockNumber) -> Weight {
@@ -576,17 +572,62 @@ decl_module! {
}
}
}
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Sets the session key(s) of the function caller to `keys`.
/// Allows an account to set its session key prior to becoming a validator.
/// This doesn't take effect until the next session.
///
/// The dispatch origin of this function must be signed.
///
/// # <weight>
/// - Complexity: `O(1)`. Actual cost depends on the number of length of
/// `T::Keys::key_ids()` which is fixed.
/// - DbReads: `origin account`, `T::ValidatorIdOf`, `NextKeys`
/// - DbWrites: `origin account`, `NextKeys`
/// - DbReads per key id: `KeyOwner`
/// - DbWrites per key id: `KeyOwner`
/// # </weight>
#[pallet::weight(T::WeightInfo::set_keys())]
pub fn set_keys(origin: OriginFor<T>, keys: T::Keys, proof: Vec<u8>) -> DispatchResult {
let who = ensure_signed(origin)?;
ensure!(keys.ownership_proof_is_valid(&proof), Error::<T>::InvalidProof);
Self::do_set_keys(&who, keys)?;
Ok(())
}
/// Removes any session key(s) of the function caller.
/// This doesn't take effect until the next session.
///
/// The dispatch origin of this function must be signed.
///
/// # <weight>
/// - Complexity: `O(1)` in number of key types. Actual cost depends on the number of length
/// of `T::Keys::key_ids()` which is fixed.
/// - DbReads: `T::ValidatorIdOf`, `NextKeys`, `origin account`
/// - DbWrites: `NextKeys`, `origin account`
/// - DbWrites per key id: `KeyOwner`
/// # </weight>
#[pallet::weight(T::WeightInfo::purge_keys())]
pub fn purge_keys(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;
Self::do_purge_keys(&who)?;
Ok(())
}
}
}
impl<T: Config> Module<T> {
impl<T: Config> Pallet<T> {
/// Move on to next session. Register new validator set and session keys. Changes to the
/// validator set have a session of delay to take effect. This allows for equivocation
/// punishment after a fork.
pub fn rotate_session() {
let session_index = CurrentIndex::get();
let session_index = <CurrentIndex<T>>::get();
log::trace!(target: "runtime::session", "rotating session {:?}", session_index);
let changed = QueuedChanged::get();
let changed = <QueuedChanged<T>>::get();
// Inform the session handlers that a session is going to end.
T::SessionHandler::on_before_session_ending();
@@ -600,12 +641,12 @@ impl<T: Config> Module<T> {
if changed {
// reset disabled validators
DisabledValidators::take();
<DisabledValidators<T>>::take();
}
// Increment session index.
let session_index = session_index + 1;
CurrentIndex::put(session_index);
<CurrentIndex<T>>::put(session_index);
T::SessionManager::start_session(session_index);
@@ -655,7 +696,7 @@ impl<T: Config> Module<T> {
};
<QueuedKeys<T>>::put(queued_amalgamated.clone());
QueuedChanged::put(next_changed);
<QueuedChanged<T>>::put(next_changed);
// Record that this happened.
Self::deposit_event(Event::NewSession(session_index));
@@ -669,7 +710,7 @@ impl<T: Config> Module<T> {
/// Returns `true` if this causes a `DisabledValidatorsThreshold` of validators
/// to be already disabled.
pub fn disable_index(i: usize) -> bool {
let (fire_event, threshold_reached) = DisabledValidators::mutate(|disabled| {
let (fire_event, threshold_reached) = <DisabledValidators<T>>::mutate(|disabled| {
let i = i as u32;
if let Err(index) = disabled.binary_search(&i) {
let count = <Validators<T>>::decode_len().unwrap_or(0) as u32;
@@ -688,12 +729,12 @@ impl<T: Config> Module<T> {
threshold_reached
}
/// Disable the validator identified by `c`. (If using with the staking module,
/// Disable the validator identified by `c`. (If using with the staking pallet,
/// this would be their *stash* account.)
///
/// Returns `Ok(true)` if more than `DisabledValidatorsThreshold` validators in current
/// session is already disabled.
/// If used with the staking module it allows to force a new era in such case.
/// If used with the staking pallet it allows to force a new era in such case.
pub fn disable(c: &T::ValidatorId) -> sp_std::result::Result<bool, ()> {
Self::validators()
.iter()
@@ -711,7 +752,7 @@ impl<T: Config> Module<T> {
///
/// Care should be taken that the raw versions of the
/// added keys are unique for every `ValidatorId, KeyTypeId` combination.
/// This is an invariant that the session module typically maintains internally.
/// This is an invariant that the session pallet typically maintains internally.
///
/// As the actual values of the keys are typically not known at runtime upgrade,
/// it's recommended to initialize the keys to a (unique) dummy value with the expectation
@@ -756,7 +797,7 @@ impl<T: Config> Module<T> {
///
/// This ensures that the reference counter in system is incremented appropriately and as such
/// must accept an account ID, rather than a validator ID.
fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> dispatch::DispatchResult {
fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> DispatchResult {
let who = T::ValidatorIdOf::convert(account.clone())
.ok_or(Error::<T>::NoAssociatedValidatorId)?;
@@ -850,16 +891,40 @@ impl<T: Config> Module<T> {
}
}
impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
impl<T: Config> ValidatorRegistration<T::ValidatorId> for Pallet<T> {
fn is_registered(id: &T::ValidatorId) -> bool {
Self::load_keys(id).is_some()
}
}
impl<T: Config> ValidatorSet<T::AccountId> for Pallet<T> {
type ValidatorId = T::ValidatorId;
type ValidatorIdOf = T::ValidatorIdOf;
fn session_index() -> sp_staking::SessionIndex {
Module::<T>::current_index()
Pallet::<T>::current_index()
}
fn validators() -> Vec<Self::ValidatorId> {
Module::<T>::validators()
Pallet::<T>::validators()
}
}
impl<T: Config> EstimateNextNewSession<T::BlockNumber> for Pallet<T> {
fn average_session_length() -> T::BlockNumber {
T::NextSessionRotation::average_session_length()
}
/// This session pallet always calls new_session and next_session at the same time, hence we
/// do a simple proxy and pass the function to next rotation.
fn estimate_next_new_session(now: T::BlockNumber) -> (Option<T::BlockNumber>, Weight) {
T::NextSessionRotation::estimate_next_session_rotation(now)
}
}
impl<T: Config> frame_support::traits::DisabledValidators for Pallet<T> {
fn is_disabled(index: u32) -> bool {
<Pallet<T>>::disabled_validators().binary_search(&index).is_ok()
}
}
@@ -877,25 +942,7 @@ impl<T: Config, Inner: FindAuthor<u32>> FindAuthor<T::ValidatorId>
{
let i = Inner::find_author(digests)?;
let validators = <Module<T>>::validators();
let validators = <Pallet<T>>::validators();
validators.get(i as usize).map(|k| k.clone())
}
}
impl<T: Config> EstimateNextNewSession<T::BlockNumber> for Module<T> {
fn average_session_length() -> T::BlockNumber {
T::NextSessionRotation::average_session_length()
}
/// This session module always calls new_session and next_session at the same time, hence we
/// do a simple proxy and pass the function to next rotation.
fn estimate_next_new_session(now: T::BlockNumber) -> (Option<T::BlockNumber>, Weight) {
T::NextSessionRotation::estimate_next_session_rotation(now)
}
}
impl<T: Config> frame_support::traits::DisabledValidators for Module<T> {
fn is_disabled(index: u32) -> bool {
<Module<T>>::disabled_validators().binary_search(&index).is_ok()
}
}
+5 -2
View File
@@ -21,7 +21,9 @@ use super::*;
use crate as pallet_session;
#[cfg(feature = "historical")]
use crate::historical as pallet_session_historical;
use frame_support::{parameter_types, BasicExternalities};
use std::cell::RefCell;
use sp_core::{crypto::key_types::DUMMY, H256};
use sp_runtime::{
impl_opaque_keys,
@@ -30,7 +32,8 @@ use sp_runtime::{
Perbill,
};
use sp_staking::SessionIndex;
use std::cell::RefCell;
use frame_support::{parameter_types, traits::GenesisBuild, BasicExternalities};
impl_opaque_keys! {
pub struct MockSessionKeys {
+5 -3
View File
@@ -18,17 +18,19 @@
// Tests for the Session Pallet
use super::*;
use codec::Decode;
use frame_support::{assert_noop, assert_ok, traits::OnInitialize};
use mock::{
use crate::mock::{
authorities, before_session_end_called, force_new_session, new_test_ext,
reset_before_session_end_called, session_changed, set_next_validators, set_session_length,
Origin, PreUpgradeMockSessionKeys, Session, System, Test, SESSION_CHANGED,
TEST_SESSION_CHANGED,
};
use codec::Decode;
use sp_core::crypto::key_types::DUMMY;
use sp_runtime::testing::UintAuthorityId;
use frame_support::{assert_noop, assert_ok, traits::OnInitialize};
fn initialize_block(block: u64) {
SESSION_CHANGED.with(|l| *l.borrow_mut() = false);
System::set_block_number(block);
+1 -2
View File
@@ -22,8 +22,7 @@ use frame_election_provider_support::{onchain, SortedListProvider};
use frame_support::{
assert_ok, parameter_types,
traits::{
Currency, FindAuthor, GenesisBuild, Get, Hooks, Imbalance, OnInitialize, OnUnbalanced,
OneSessionHandler,
Currency, FindAuthor, GenesisBuild, Get, Hooks, Imbalance, OnUnbalanced, OneSessionHandler,
},
weights::constants::RocksDbWeight,
};
+1 -1
View File
@@ -23,7 +23,7 @@ use frame_support::{
assert_noop, assert_ok,
dispatch::WithPostDispatchInfo,
pallet_prelude::*,
traits::{Currency, Get, OnInitialize, ReservableCurrency},
traits::{Currency, Get, ReservableCurrency},
weights::{extract_actual_weight, GetDispatchInfo},
};
use mock::*;