mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 19:01:08 +00:00
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:
Generated
+1
@@ -1628,6 +1628,7 @@ dependencies = [
|
||||
"sp-inherents",
|
||||
"sp-io",
|
||||
"sp-runtime",
|
||||
"sp-staking",
|
||||
"sp-state-machine",
|
||||
"sp-std",
|
||||
"sp-tracing",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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(
|
||||
¤t_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(¤t_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(¤t_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(
|
||||
¤t_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();
|
||||
}
|
||||
|
||||
@@ -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},
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user