Decouple the session validators from im-online (#7127)

* Decouple the session validators from im-online

* .

* Add SessionInterface trait in im-online

Add ValidatorId in im-online Trait

Make im-online compile

Make substrate binary compile

* Fix merging issue

* Make all compile

* Fix tests

* Avoid using frame dep in primitives via pallet-session-common

* Merge ValidatorSet into SessionInterface trait

Wrap a few too long lines

Add some docs

* Move pallet-sesion-common into pallet-session

* Move SessionInterface to sp-session and impl it in session pallet

Ref https://github.com/paritytech/substrate/pull/7127#discussion_r494892472

* Split put historical::FullValidatorIdentification trait

* Fix line width

* Fix staking mock

* Fix session doc test

* Simplify <T as ValidatorIdentification<AccountId>>::ValidatorId as ValidatorId<T>

* Nits

* Clean up.

* Make it compile by commenting out report_offence_im_online bench

* Tests

* Nits

* Move OneSessionHandler to sp-session

* Fix tests

* Add some docs

* .

* Fix typo

* Rename to ValidatorSet::session_index()

* Add some more docs

* .

* Remove extra empty line

* Fix line width check

.

* Apply suggestions from code review

* Cleaup Cargo.toml

* Aura has migrated to Pallet now

Co-authored-by: Tomasz Drwięga <tomasz@parity.io>
This commit is contained in:
Liu-Cheng Xu
2021-02-03 00:38:37 +08:00
committed by GitHub
parent 38b6182fb8
commit 9904267e23
18 changed files with 204 additions and 84 deletions
+1
View File
@@ -1628,6 +1628,7 @@ dependencies = [
"sp-inherents",
"sp-io",
"sp-runtime",
"sp-staking",
"sp-state-machine",
"sp-std",
"sp-tracing",
+1
View File
@@ -830,6 +830,7 @@ impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime where
impl pallet_im_online::Config for Runtime {
type AuthorityId = ImOnlineId;
type Event = Event;
type ValidatorSet = Historical;
type SessionDuration = SessionDuration;
type ReportUnresponsiveness = Offences;
type UnsignedPriority = ImOnlineUnsignedPriority;
+2 -2
View File
@@ -46,7 +46,7 @@
use sp_std::{result, prelude::*};
use codec::{Encode, Decode};
use frame_support::{Parameter, traits::{Get, FindAuthor}, ConsensusEngineId};
use frame_support::{Parameter, traits::{Get, FindAuthor, OneSessionHandler}, ConsensusEngineId};
use sp_runtime::{
RuntimeAppPublic,
traits::{SaturatedConversion, Saturating, Zero, Member, IsMember}, generic::DigestItem,
@@ -144,7 +144,7 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> {
type Public = T::AuthorityId;
}
impl<T: Config> pallet_session::OneSessionHandler<T::AccountId> for Pallet<T> {
impl<T: Config> OneSessionHandler<T::AccountId> for Pallet<T> {
type Key = T::AuthorityId;
fn on_genesis_session<'a, I: 'a>(validators: I)
@@ -24,7 +24,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
use sp_std::prelude::*;
use frame_support::{decl_module, decl_storage};
use frame_support::{decl_module, decl_storage, traits::OneSessionHandler};
use sp_authority_discovery::AuthorityId;
/// The module's config trait.
@@ -85,7 +85,7 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
type Public = AuthorityId;
}
impl<T: Config> pallet_session::OneSessionHandler<T::AccountId> for Module<T> {
impl<T: Config> OneSessionHandler<T::AccountId> for Module<T> {
type Key = AuthorityId;
fn on_genesis_session<'a, I: 'a>(authorities: I)
@@ -265,7 +265,7 @@ mod tests {
let mut externalities = TestExternalities::new(t);
externalities.execute_with(|| {
use pallet_session::OneSessionHandler;
use frame_support::traits::OneSessionHandler;
AuthorityDiscovery::on_genesis_session(
first_authorities.iter().map(|id| (id, id.clone()))
+2 -2
View File
@@ -25,7 +25,7 @@ use codec::{Decode, Encode};
use frame_support::{
decl_error, decl_module, decl_storage,
dispatch::DispatchResultWithPostInfo,
traits::{FindAuthor, Get, KeyOwnerProofSystem, Randomness as RandomnessT},
traits::{FindAuthor, Get, KeyOwnerProofSystem, OneSessionHandler, Randomness as RandomnessT},
weights::{Pays, Weight},
Parameter,
};
@@ -769,7 +769,7 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
type Public = AuthorityId;
}
impl<T: Config> pallet_session::OneSessionHandler<T::AccountId> for Module<T> {
impl<T: Config> OneSessionHandler<T::AccountId> for Module<T> {
type Key = AuthorityId;
fn on_genesis_session<'a, I: 'a>(validators: I)
+2 -2
View File
@@ -41,7 +41,7 @@ use fg_primitives::{
};
use frame_support::{
decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResultWithPostInfo,
storage, traits::KeyOwnerProofSystem, weights::{Pays, Weight}, Parameter,
storage, traits::{OneSessionHandler, KeyOwnerProofSystem}, weights::{Pays, Weight}, Parameter,
};
use frame_system::{ensure_none, ensure_root, ensure_signed};
use sp_runtime::{
@@ -587,7 +587,7 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
type Public = AuthorityId;
}
impl<T: Config> pallet_session::OneSessionHandler<T::AccountId> for Module<T>
impl<T: Config> OneSessionHandler<T::AccountId> for Module<T>
where T: pallet_session::Config
{
type Key = AuthorityId;
+1 -2
View File
@@ -25,11 +25,10 @@ use codec::{Decode, Encode};
use fg_primitives::ScheduledChange;
use frame_support::{
assert_err, assert_ok,
traits::{Currency, OnFinalize},
traits::{Currency, OnFinalize, OneSessionHandler},
weights::{GetDispatchInfo, Pays},
};
use frame_system::{EventRecord, Phase};
use pallet_session::OneSessionHandler;
use sp_core::H256;
use sp_keyring::Ed25519Keyring;
use sp_runtime::testing::Digest;
+4 -3
View File
@@ -19,7 +19,6 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features =
sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" }
sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" }
serde = { version = "1.0.101", optional = true }
pallet-session = { version = "2.0.0", default-features = false, path = "../session" }
sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" }
sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" }
sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" }
@@ -28,8 +27,11 @@ frame-system = { version = "2.0.0", default-features = false, path = "../system"
frame-benchmarking = { version = "2.0.0", default-features = false, path = "../benchmarking", optional = true }
[dev-dependencies]
pallet-session = { version = "2.0.0", path = "../session" }
[features]
default = ["std", "pallet-session/historical"]
default = ["std"]
std = [
"sp-application-crypto/std",
"pallet-authorship/std",
@@ -37,7 +39,6 @@ std = [
"sp-core/std",
"sp-std/std",
"serde",
"pallet-session/std",
"sp-io/std",
"sp-runtime/std",
"sp-staking/std",
+43 -24
View File
@@ -79,7 +79,6 @@ use codec::{Encode, Decode};
use sp_core::offchain::OpaqueNetworkState;
use sp_std::prelude::*;
use sp_std::convert::TryInto;
use pallet_session::historical::IdentificationTuple;
use sp_runtime::{
offchain::storage::StorageValueRef,
RuntimeDebug,
@@ -95,7 +94,7 @@ use sp_staking::{
};
use frame_support::{
decl_module, decl_event, decl_storage, Parameter, debug, decl_error,
traits::Get,
traits::{Get, ValidatorSet, ValidatorSetWithIdentification, OneSessionHandler},
};
use frame_system::ensure_none;
use frame_system::offchain::{
@@ -227,7 +226,19 @@ pub struct Heartbeat<BlockNumber>
pub validators_len: u32,
}
pub trait Config: SendTransactionTypes<Call<Self>> + pallet_session::historical::Config {
/// A type for representing the validator id in a session.
pub type ValidatorId<T> = <
<T as Config>::ValidatorSet as ValidatorSet<<T as frame_system::Config>::AccountId>
>::ValidatorId;
/// A tuple of (ValidatorId, Identification) where `Identification` is the full identification of `ValidatorId`.
pub type IdentificationTuple<T> = (
ValidatorId<T>,
<<T as Config>::ValidatorSet as
ValidatorSetWithIdentification<<T as frame_system::Config>::AccountId>>::Identification,
);
pub trait Config: SendTransactionTypes<Call<Self>> + frame_system::Config {
/// The identifier type for an authority.
type AuthorityId: Member + Parameter + RuntimeAppPublic + Default + Ord;
@@ -242,6 +253,9 @@ pub trait Config: SendTransactionTypes<Call<Self>> + pallet_session::historical:
/// there is a chance the authority will produce a block and they won't be necessary.
type SessionDuration: Get<Self::BlockNumber>;
/// A type for retrieving the validators supposed to be online in a session.
type ValidatorSet: ValidatorSetWithIdentification<Self::AccountId>;
/// A type that gives us the ability to submit unresponsiveness offence reports.
type ReportUnresponsiveness:
ReportOffence<
@@ -293,10 +307,10 @@ decl_storage! {
double_map hasher(twox_64_concat) SessionIndex, hasher(twox_64_concat) AuthIndex
=> Option<Vec<u8>>;
/// For each session index, we keep a mapping of `T::ValidatorId` to the
/// For each session index, we keep a mapping of `ValidatorId<T>` to the
/// number of blocks authored by the given authority.
AuthoredBlocks get(fn authored_blocks):
double_map hasher(twox_64_concat) SessionIndex, hasher(twox_64_concat) T::ValidatorId
double_map hasher(twox_64_concat) SessionIndex, hasher(twox_64_concat) ValidatorId<T>
=> u32;
}
add_extra_genesis {
@@ -345,7 +359,7 @@ decl_module! {
) {
ensure_none(origin)?;
let current_session = <pallet_session::Module<T>>::current_index();
let current_session = T::ValidatorSet::session_index();
let exists = <ReceivedHeartbeats>::contains_key(
&current_session,
&heartbeat.authority_index
@@ -397,12 +411,15 @@ type OffchainResult<T, A> = Result<A, OffchainErr<<T as frame_system::Config>::B
/// Keep track of number of authored blocks per authority, uncles are counted as
/// well since they're a valid proof of being online.
impl<T: Config + pallet_authorship::Config> pallet_authorship::EventHandler<T::ValidatorId, T::BlockNumber> for Module<T> {
fn note_author(author: T::ValidatorId) {
impl<
T: Config + pallet_authorship::Config,
> pallet_authorship::EventHandler<ValidatorId<T>, T::BlockNumber> for Module<T>
{
fn note_author(author: ValidatorId<T>) {
Self::note_authorship(author);
}
fn note_uncle(author: T::ValidatorId, _age: T::BlockNumber) {
fn note_uncle(author: ValidatorId<T>, _age: T::BlockNumber) {
Self::note_authorship(author);
}
}
@@ -413,7 +430,7 @@ impl<T: Config> Module<T> {
/// authored at least one block, during the current session. Otherwise
/// `false`.
pub fn is_online(authority_index: AuthIndex) -> bool {
let current_validators = <pallet_session::Module<T>>::validators();
let current_validators = T::ValidatorSet::validators();
if authority_index >= current_validators.len() as u32 {
return false;
@@ -424,8 +441,8 @@ impl<T: Config> Module<T> {
Self::is_online_aux(authority_index, authority)
}
fn is_online_aux(authority_index: AuthIndex, authority: &T::ValidatorId) -> bool {
let current_session = <pallet_session::Module<T>>::current_index();
fn is_online_aux(authority_index: AuthIndex, authority: &ValidatorId<T>) -> bool {
let current_session = T::ValidatorSet::session_index();
<ReceivedHeartbeats>::contains_key(&current_session, &authority_index) ||
<AuthoredBlocks<T>>::get(
@@ -437,13 +454,13 @@ impl<T: Config> Module<T> {
/// Returns `true` if a heartbeat has been received for the authority at `authority_index` in
/// the authorities series, during the current session. Otherwise `false`.
pub fn received_heartbeat_in_current_session(authority_index: AuthIndex) -> bool {
let current_session = <pallet_session::Module<T>>::current_index();
let current_session = T::ValidatorSet::session_index();
<ReceivedHeartbeats>::contains_key(&current_session, &authority_index)
}
/// Note that the given authority has authored a block in the current session.
fn note_authorship(author: T::ValidatorId) {
let current_session = <pallet_session::Module<T>>::current_index();
fn note_authorship(author: ValidatorId<T>) {
let current_session = T::ValidatorSet::session_index();
<AuthoredBlocks<T>>::mutate(
&current_session,
@@ -460,8 +477,8 @@ impl<T: Config> Module<T> {
return Err(OffchainErr::TooEarly(heartbeat_after))
}
let session_index = <pallet_session::Module<T>>::current_index();
let validators_len = <pallet_session::Module<T>>::validators().len() as u32;
let session_index = T::ValidatorSet::session_index();
let validators_len = Keys::<T>::decode_len().unwrap_or_default() as u32;
Ok(Self::local_authority_keys()
.map(move |(authority_index, key)|
@@ -614,7 +631,7 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
type Public = T::AuthorityId;
}
impl<T: Config> pallet_session::OneSessionHandler<T::AccountId> for Module<T> {
impl<T: Config> OneSessionHandler<T::AccountId> for Module<T> {
type Key = T::AuthorityId;
fn on_genesis_session<'a, I: 'a>(validators: I)
@@ -639,22 +656,24 @@ impl<T: Config> pallet_session::OneSessionHandler<T::AccountId> for Module<T> {
}
fn on_before_session_ending() {
let session_index = <pallet_session::Module<T>>::current_index();
let session_index = T::ValidatorSet::session_index();
let keys = Keys::<T>::get();
let current_validators = <pallet_session::Module<T>>::validators();
let current_validators = T::ValidatorSet::validators();
let offenders = current_validators.into_iter().enumerate()
.filter(|(index, id)|
!Self::is_online_aux(*index as u32, id)
).filter_map(|(_, id)|
T::FullIdentificationOf::convert(id.clone()).map(|full_id| (id, full_id))
<T::ValidatorSet as ValidatorSetWithIdentification<T::AccountId>>::IdentificationOf::convert(
id.clone()
).map(|full_id| (id, full_id))
).collect::<Vec<IdentificationTuple<T>>>();
// Remove all received heartbeats and number of authored blocks from the
// current session, they have already been processed and won't be needed
// anymore.
<ReceivedHeartbeats>::remove_prefix(&<pallet_session::Module<T>>::current_index());
<AuthoredBlocks<T>>::remove_prefix(&<pallet_session::Module<T>>::current_index());
<ReceivedHeartbeats>::remove_prefix(&T::ValidatorSet::session_index());
<AuthoredBlocks<T>>::remove_prefix(&T::ValidatorSet::session_index());
if offenders.is_empty() {
Self::deposit_event(RawEvent::AllGood);
@@ -691,7 +710,7 @@ impl<T: Config> frame_support::unsigned::ValidateUnsigned for Module<T> {
}
// check if session index from heartbeat is recent
let current_session = <pallet_session::Module<T>>::current_index();
let current_session = T::ValidatorSet::session_index();
if heartbeat.session_index != current_session {
return InvalidTransaction::Stale.into();
}
+2
View File
@@ -179,6 +179,7 @@ impl Config for Runtime {
type AuthorityId = UintAuthorityId;
type Event = ();
type ReportUnresponsiveness = OffenceHandler;
type ValidatorSet = Historical;
type SessionDuration = Period;
type UnsignedPriority = UnsignedPriority;
type WeightInfo = ();
@@ -195,6 +196,7 @@ impl<LocalCall> frame_system::offchain::SendTransactionTypes<LocalCall> for Runt
pub type ImOnline = Module<Runtime>;
pub type System = frame_system::Module<Runtime>;
pub type Session = pallet_session::Module<Runtime>;
pub type Historical = pallet_session::historical::Module<Runtime>;
pub fn advance_session() {
let now = System::block_number().max(1);
@@ -26,7 +26,7 @@ use sp_std::vec;
use frame_system::{RawOrigin, Module as System, Config as SystemConfig};
use frame_benchmarking::{benchmarks, account};
use frame_support::traits::{Currency, OnInitialize};
use frame_support::traits::{Currency, OnInitialize, ValidatorSet, ValidatorSetWithIdentification};
use sp_runtime::{Perbill, traits::{Convert, StaticLookup, Saturating, UniqueSaturatedInto}};
use sp_staking::offence::{ReportOffence, Offence, OffenceDetails};
@@ -176,6 +176,34 @@ fn make_offenders<T: Config>(num_offenders: u32, num_nominators: u32) -> Result<
Ok((id_tuples, offenders))
}
fn make_offenders_im_online<T: Config>(num_offenders: u32, num_nominators: u32) -> Result<
(Vec<pallet_im_online::IdentificationTuple<T>>, Vec<Offender<T>>),
&'static str
> {
Staking::<T>::new_session(0);
let mut offenders = vec![];
for i in 0 .. num_offenders {
let offender = create_offender::<T>(i + 1, num_nominators)?;
offenders.push(offender);
}
Staking::<T>::start_session(0);
let id_tuples = offenders.iter()
.map(|offender| <
<T as ImOnlineConfig>::ValidatorSet as ValidatorSet<T::AccountId>
>::ValidatorIdOf::convert(offender.controller.clone())
.expect("failed to get validator id from account id"))
.map(|validator_id| <
<T as ImOnlineConfig>::ValidatorSet as ValidatorSetWithIdentification<T::AccountId>
>::IdentificationOf::convert(validator_id.clone())
.map(|full_id| (validator_id, full_id))
.expect("failed to convert validator id to full identification"))
.collect::<Vec<pallet_im_online::IdentificationTuple<T>>>();
Ok((id_tuples, offenders))
}
#[cfg(test)]
fn check_events<T: Config, I: Iterator<Item = <T as SystemConfig>::Event>>(expected: I) {
let events = System::<T>::events() .into_iter()
@@ -220,7 +248,7 @@ benchmarks! {
// make sure reporters actually get rewarded
Staking::<T>::set_slash_reward_fraction(Perbill::one());
let (offenders, raw_offenders) = make_offenders::<T>(o, n)?;
let (offenders, raw_offenders) = make_offenders_im_online::<T>(o, n)?;
let keys = ImOnline::<T>::keys();
let validator_set_count = keys.len() as u32;
@@ -29,7 +29,7 @@ use sp_runtime::{
traits::IdentityLookup,
testing::{Header, UintAuthorityId},
};
use pallet_session::historical as pallet_session_historical;
type AccountId = u64;
type AccountIndex = u32;
@@ -130,6 +130,7 @@ impl pallet_session::Config for Test {
type DisabledValidatorsThreshold = ();
type WeightInfo = ();
}
pallet_staking_reward_curve::build! {
const I_NPOS: sp_runtime::curve::PiecewiseLinear<'static> = curve!(
min_inflation: 0_025_000,
@@ -175,6 +176,7 @@ impl pallet_staking::Config for Test {
impl pallet_im_online::Config for Test {
type AuthorityId = UintAuthorityId;
type Event = Event;
type ValidatorSet = Historical;
type SessionDuration = Period;
type ReportUnresponsiveness = Offences;
type UnsignedPriority = ();
@@ -214,6 +216,7 @@ frame_support::construct_runtime!(
Session: pallet_session::{Module, Call, Storage, Event, Config<T>},
ImOnline: pallet_im_online::{Module, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
Offences: pallet_offences::{Module, Call, Storage, Event},
Historical: pallet_session_historical::{Module},
}
);
+22 -2
View File
@@ -31,8 +31,10 @@ use codec::{Encode, Decode};
use sp_runtime::KeyTypeId;
use sp_runtime::traits::{Convert, OpaqueKeys};
use sp_session::{MembershipProof, ValidatorCount};
use frame_support::{decl_module, decl_storage};
use frame_support::{Parameter, print};
use frame_support::{
decl_module, decl_storage, Parameter, print,
traits::{ValidatorSet, ValidatorSetWithIdentification},
};
use sp_trie::{MemoryDB, Trie, TrieMut, Recorder, EMPTY_PREFIX};
use sp_trie::trie_types::{TrieDBMut, TrieDB};
use super::{SessionIndex, Module as SessionModule};
@@ -102,6 +104,24 @@ impl<T: Config> Module<T> {
}
}
impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
type ValidatorId = T::ValidatorId;
type ValidatorIdOf = T::ValidatorIdOf;
fn session_index() -> sp_staking::SessionIndex {
super::Module::<T>::current_index()
}
fn validators() -> Vec<Self::ValidatorId> {
super::Module::<T>::validators()
}
}
impl<T: Config> ValidatorSetWithIdentification<T::AccountId> for Module<T> {
type Identification = T::FullIdentification;
type IdentificationOf = T::FullIdentificationOf;
}
/// Specialization of the crate-level `SessionManager` which returns the set of full identification
/// when creating a new session.
pub trait SessionManager<ValidatorId, FullIdentification>: crate::SessionManager<ValidatorId> {
+15 -35
View File
@@ -116,13 +116,14 @@ pub mod weights;
use sp_std::{prelude::*, marker::PhantomData, ops::{Sub, Rem}};
use codec::Decode;
use sp_runtime::{KeyTypeId, Perbill, RuntimeAppPublic, BoundToRuntimeAppPublic};
use sp_runtime::{KeyTypeId, Perbill, RuntimeAppPublic};
use sp_runtime::traits::{Convert, Zero, Member, OpaqueKeys, Saturating};
use sp_staking::SessionIndex;
use frame_support::{
ensure, decl_module, decl_event, decl_storage, decl_error, ConsensusEngineId, Parameter,
traits::{
Get, FindAuthor, ValidatorRegistration, EstimateNextSessionRotation, EstimateNextNewSession,
OneSessionHandler, ValidatorSet,
},
dispatch::{self, DispatchResult, DispatchError},
weights::Weight,
@@ -256,40 +257,6 @@ pub trait SessionHandler<ValidatorId> {
fn on_disabled(validator_index: usize);
}
/// A session handler for specific key type.
pub trait OneSessionHandler<ValidatorId>: BoundToRuntimeAppPublic {
/// The key type expected.
type Key: Decode + Default + RuntimeAppPublic;
fn on_genesis_session<'a, I: 'a>(validators: I)
where I: Iterator<Item=(&'a ValidatorId, Self::Key)>, ValidatorId: 'a;
/// Session set has changed; act appropriately. Note that this can be called
/// before initialization of your module.
///
/// `changed` is true when at least one of the session keys
/// or the underlying economic identities/distribution behind one the
/// session keys has changed, false otherwise.
///
/// The `validators` are the validators of the incoming session, and `queued_validators`
/// will follow.
fn on_new_session<'a, I: 'a>(
changed: bool,
validators: I,
queued_validators: I,
) where I: Iterator<Item=(&'a ValidatorId, Self::Key)>, ValidatorId: 'a;
/// A notification for end of the session.
///
/// Note it is triggered before any `SessionManager::end_session` handlers,
/// so we can still affect the validator set.
fn on_before_session_ending() {}
/// A validator got disabled. Act accordingly until a new session begins.
fn on_disabled(_validator_index: usize);
}
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
#[tuple_types_no_default_trait_bound]
impl<AId> SessionHandler<AId> for Tuple {
@@ -830,6 +797,19 @@ impl<T: Config> Module<T> {
}
}
impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
type ValidatorId = T::ValidatorId;
type ValidatorIdOf = T::ValidatorIdOf;
fn session_index() -> sp_staking::SessionIndex {
Module::<T>::current_index()
}
fn validators() -> Vec<Self::ValidatorId> {
Module::<T>::validators()
}
}
/// Wraps the author-scraping logic for consensus engines that can recover
/// the canonical index of an author. This then transforms it into the
/// registering account-ID of that session key index.
+1
View File
@@ -18,6 +18,7 @@
// Tests for the Session Pallet
use super::*;
use codec::Decode;
use frame_support::{traits::OnInitialize, assert_ok};
use sp_core::crypto::key_types::DUMMY;
use sp_runtime::testing::UintAuthorityId;
+2 -2
View File
@@ -21,7 +21,7 @@ use crate::*;
use crate as staking;
use frame_support::{
assert_ok, parameter_types,
traits::{Currency, FindAuthor, Get, OnFinalize, OnInitialize},
traits::{Currency, FindAuthor, Get, OnFinalize, OnInitialize, OneSessionHandler},
weights::{constants::RocksDbWeight, Weight},
IterableStorageMap, StorageDoubleMap, StorageMap, StorageValue,
};
@@ -53,7 +53,7 @@ thread_local! {
/// Another session handler struct to test on_disabled.
pub struct OtherSessionHandler;
impl pallet_session::OneSessionHandler<AccountId> for OtherSessionHandler {
impl OneSessionHandler<AccountId> for OtherSessionHandler {
type Key = UintAuthorityId;
fn on_genesis_session<'a, I: 'a>(_: I)
+2
View File
@@ -24,6 +24,7 @@ sp-tracing = { version = "2.0.0", default-features = false, path = "../../primit
sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" }
sp-arithmetic = { version = "2.0.0", default-features = false, path = "../../primitives/arithmetic" }
sp-inherents = { version = "2.0.0", default-features = false, path = "../../primitives/inherents" }
sp-staking = { version = "2.0.0", default-features = false, path = "../../primitives/staking" }
frame-support-procedural = { version = "2.0.1", default-features = false, path = "./procedural" }
paste = "0.1.6"
once_cell = { version = "1", default-features = false, optional = true }
@@ -52,6 +53,7 @@ std = [
"sp-arithmetic/std",
"frame-metadata/std",
"sp-inherents/std",
"sp-staking/std",
"sp-state-machine",
"frame-support-procedural/std",
]
+67 -4
View File
@@ -23,13 +23,15 @@ use sp_std::{prelude::*, result, marker::PhantomData, ops::Div, fmt::Debug};
use codec::{FullCodec, Codec, Encode, Decode, EncodeLike};
use sp_core::u32_trait::Value as U32;
use sp_runtime::{
RuntimeDebug, ConsensusEngineId, DispatchResult, DispatchError,
RuntimeAppPublic, RuntimeDebug, BoundToRuntimeAppPublic,
ConsensusEngineId, DispatchResult, DispatchError,
traits::{
MaybeSerializeDeserialize, AtLeast32Bit, Saturating, TrailingZeroInput, Bounded, Zero,
BadOrigin, AtLeast32BitUnsigned, UniqueSaturatedFrom, UniqueSaturatedInto,
SaturatedConversion, StoredMapError,
MaybeSerializeDeserialize, AtLeast32Bit, Saturating, TrailingZeroInput, Bounded, Zero,
BadOrigin, AtLeast32BitUnsigned, Convert, UniqueSaturatedFrom, UniqueSaturatedInto,
SaturatedConversion, StoredMapError,
},
};
use sp_staking::SessionIndex;
use crate::dispatch::Parameter;
use crate::storage::StorageMap;
use crate::weights::Weight;
@@ -40,6 +42,67 @@ use impl_trait_for_tuples::impl_for_tuples;
#[doc(hidden)]
pub use sp_std::{mem::{swap, take}, cell::RefCell, vec::Vec, boxed::Box};
/// A trait for online node inspection in a session.
///
/// Something that can give information about the current validator set.
pub trait ValidatorSet<AccountId> {
/// Type for representing validator id in a session.
type ValidatorId: Parameter;
/// A type for converting `AccountId` to `ValidatorId`.
type ValidatorIdOf: Convert<AccountId, Option<Self::ValidatorId>>;
/// Returns current session index.
fn session_index() -> SessionIndex;
/// Returns the active set of validators.
fn validators() -> Vec<Self::ValidatorId>;
}
/// [`ValidatorSet`] combined with an identification.
pub trait ValidatorSetWithIdentification<AccountId>: ValidatorSet<AccountId> {
/// Full identification of `ValidatorId`.
type Identification: Parameter;
/// A type for converting `ValidatorId` to `Identification`.
type IdentificationOf: Convert<Self::ValidatorId, Option<Self::Identification>>;
}
/// A session handler for specific key type.
pub trait OneSessionHandler<ValidatorId>: BoundToRuntimeAppPublic {
/// The key type expected.
type Key: Decode + Default + RuntimeAppPublic;
/// The given validator set will be used for the genesis session.
/// It is guaranteed that the given validator set will also be used
/// for the second session, therefore the first call to `on_new_session`
/// should provide the same validator set.
fn on_genesis_session<'a, I: 'a>(validators: I)
where I: Iterator<Item=(&'a ValidatorId, Self::Key)>, ValidatorId: 'a;
/// Session set has changed; act appropriately. Note that this can be called
/// before initialization of your module.
///
/// `changed` is true when at least one of the session keys
/// or the underlying economic identities/distribution behind one the
/// session keys has changed, false otherwise.
///
/// The `validators` are the validators of the incoming session, and `queued_validators`
/// will follow.
fn on_new_session<'a, I: 'a>(
changed: bool,
validators: I,
queued_validators: I,
) where I: Iterator<Item=(&'a ValidatorId, Self::Key)>, ValidatorId: 'a;
/// A notification for end of the session.
///
/// Note it is triggered before any `SessionManager::end_session` handlers,
/// so we can still affect the validator set.
fn on_before_session_ending() {}
/// A validator got disabled. Act accordingly until a new session begins.
fn on_disabled(_validator_index: usize);
}
/// Simple trait for providing a filter over a reference to some type.
pub trait Filter<T> {
/// Determine if a given value should be allowed through the filter (returns `true`) or not.