mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
past-session validator discovery APIs (#2009)
* guide: fix formatting for SessionInfo module * primitives: SessionInfo type * punt on approval keys * ah, revert the type alias * session info runtime module skeleton * update the guide * runtime/configuration: sync with the guide * runtime/configuration: setters for newly added fields * runtime/configuration: set codec indexes * runtime/configuration: update test * primitives: fix SessionInfo definition * runtime/session_info: initial impl * runtime/session_info: use initializer for session handling (wip) * runtime/session_info: mock authority discovery trait * guide: update the initializer's order * runtime/session_info: tests skeleton * runtime/session_info: store n_delay_tranches in Configuration * runtime/session_info: punt on approval keys * runtime/session_info: add some basic tests * Update primitives/src/v1.rs * small fixes * remove codec index annotation on structs * fix off-by-one error * validator_discovery: accept a session index * runtime: replace validator_discovery api with session_info * Update runtime/parachains/src/session_info.rs Co-authored-by: Sergei Shulepov <sergei@parity.io> * runtime/session_info: add a comment about missing entries * runtime/session_info: define the keys * util: expose connect_to_past_session_validators * util: allow session_info requests for jobs * runtime-api: add mock test for session_info * collator-protocol: add session_index to test state * util: fix error message for runtime error * fix compilation * fix tests after merge with master Co-authored-by: Sergei Shulepov <sergei@parity.io>
This commit is contained in:
@@ -19,9 +19,10 @@
|
||||
//! Configuration can change only at session boundaries and is buffered until then.
|
||||
|
||||
use sp_std::prelude::*;
|
||||
use primitives::v1::{Balance, ValidatorId};
|
||||
use primitives::v1::{Balance, ValidatorId, SessionIndex};
|
||||
use frame_support::{
|
||||
decl_storage, decl_module, decl_error,
|
||||
ensure,
|
||||
dispatch::DispatchResult,
|
||||
weights::{DispatchClass, Weight},
|
||||
};
|
||||
@@ -60,6 +61,21 @@ pub struct HostConfiguration<BlockNumber> {
|
||||
pub thread_availability_period: BlockNumber,
|
||||
/// The amount of blocks ahead to schedule parachains and parathreads.
|
||||
pub scheduling_lookahead: u32,
|
||||
/// The amount of sessions to keep for disputes.
|
||||
pub dispute_period: SessionIndex,
|
||||
/// The amount of consensus slots that must pass between submitting an assignment and
|
||||
/// submitting an approval vote before a validator is considered a no-show.
|
||||
/// Must be at least 1.
|
||||
pub no_show_slots: u32,
|
||||
/// The number of delay tranches in total.
|
||||
pub n_delay_tranches: u32,
|
||||
/// The width of the zeroth delay tranche for approval assignments. This many delay tranches
|
||||
/// beyond 0 are all consolidated to form a wide 0 tranche.
|
||||
pub zeroth_delay_tranche_width: u32,
|
||||
/// The number of validators needed to approve a block.
|
||||
pub needed_approvals: u32,
|
||||
/// The number of samples to do of the RelayVRFModulo approval assignment criterion.
|
||||
pub relay_vrf_modulo_samples: u32,
|
||||
/// Total number of individual messages allowed in the parachain -> relay-chain message queue.
|
||||
pub max_upward_queue_count: u32,
|
||||
/// Total size of messages allowed in the parachain -> relay-chain message queue before which
|
||||
@@ -255,6 +271,68 @@ decl_module! {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the dispute period, in number of sessions to keep for disputes.
|
||||
#[weight = (1_000, DispatchClass::Operational)]
|
||||
pub fn set_dispute_period(origin, new: SessionIndex) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
Self::update_config_member(|config| {
|
||||
sp_std::mem::replace(&mut config.dispute_period, new) != new
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the no show slots, in number of number of consensus slots.
|
||||
/// Must be at least 1.
|
||||
#[weight = (1_000, DispatchClass::Operational)]
|
||||
pub fn set_no_show_slots(origin, new: u32) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
ensure!(new >= 1, "no_show_slots must be at least 1");
|
||||
Self::update_config_member(|config| {
|
||||
sp_std::mem::replace(&mut config.no_show_slots, new) != new
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the total number of delay tranches.
|
||||
#[weight = (1_000, DispatchClass::Operational)]
|
||||
pub fn set_n_delay_tranches(origin, new: u32) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
Self::update_config_member(|config| {
|
||||
sp_std::mem::replace(&mut config.n_delay_tranches, new) != new
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the zeroth delay tranche width.
|
||||
#[weight = (1_000, DispatchClass::Operational)]
|
||||
pub fn set_zeroth_delay_tranche_width(origin, new: u32) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
Self::update_config_member(|config| {
|
||||
sp_std::mem::replace(&mut config.zeroth_delay_tranche_width, new) != new
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the number of validators needed to approve a block.
|
||||
#[weight = (1_000, DispatchClass::Operational)]
|
||||
pub fn set_needed_approvals(origin, new: u32) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
Self::update_config_member(|config| {
|
||||
sp_std::mem::replace(&mut config.needed_approvals, new) != new
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the number of samples to do of the RelayVRFModulo approval assignment criterion.
|
||||
#[weight = (1_000, DispatchClass::Operational)]
|
||||
pub fn set_relay_vrf_modulo_samples(origin, new: u32) -> DispatchResult {
|
||||
ensure_root(origin)?;
|
||||
Self::update_config_member(|config| {
|
||||
sp_std::mem::replace(&mut config.relay_vrf_modulo_samples, new) != new
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the maximum items that can present in a upward dispatch queue at once.
|
||||
#[weight = (1_000, DispatchClass::Operational)]
|
||||
pub fn set_max_upward_queue_count(origin, new: u32) -> DispatchResult {
|
||||
@@ -504,6 +582,12 @@ mod tests {
|
||||
chain_availability_period: 10,
|
||||
thread_availability_period: 8,
|
||||
scheduling_lookahead: 3,
|
||||
dispute_period: 239,
|
||||
no_show_slots: 240,
|
||||
n_delay_tranches: 241,
|
||||
zeroth_delay_tranche_width: 242,
|
||||
needed_approvals: 242,
|
||||
relay_vrf_modulo_samples: 243,
|
||||
max_upward_queue_count: 1337,
|
||||
max_upward_queue_size: 228,
|
||||
max_downward_message_size: 2048,
|
||||
@@ -561,6 +645,24 @@ mod tests {
|
||||
Configuration::set_scheduling_lookahead(
|
||||
Origin::root(), new_config.scheduling_lookahead,
|
||||
).unwrap();
|
||||
Configuration::set_dispute_period(
|
||||
Origin::root(), new_config.dispute_period,
|
||||
).unwrap();
|
||||
Configuration::set_no_show_slots(
|
||||
Origin::root(), new_config.no_show_slots,
|
||||
).unwrap();
|
||||
Configuration::set_n_delay_tranches(
|
||||
Origin::root(), new_config.n_delay_tranches,
|
||||
).unwrap();
|
||||
Configuration::set_zeroth_delay_tranche_width(
|
||||
Origin::root(), new_config.zeroth_delay_tranche_width,
|
||||
).unwrap();
|
||||
Configuration::set_needed_approvals(
|
||||
Origin::root(), new_config.needed_approvals,
|
||||
).unwrap();
|
||||
Configuration::set_relay_vrf_modulo_samples(
|
||||
Origin::root(), new_config.relay_vrf_modulo_samples,
|
||||
).unwrap();
|
||||
Configuration::set_max_upward_queue_count(
|
||||
Origin::root(), new_config.max_upward_queue_count,
|
||||
).unwrap();
|
||||
|
||||
@@ -29,7 +29,7 @@ use sp_runtime::traits::One;
|
||||
use parity_scale_codec::{Encode, Decode};
|
||||
use crate::{
|
||||
configuration::{self, HostConfiguration},
|
||||
paras, scheduler, inclusion, dmp, ump, hrmp,
|
||||
paras, scheduler, inclusion, session_info, dmp, ump, hrmp,
|
||||
};
|
||||
|
||||
/// Information about a session change that has just occurred.
|
||||
@@ -63,6 +63,7 @@ pub trait Trait:
|
||||
+ paras::Trait
|
||||
+ scheduler::Trait
|
||||
+ inclusion::Trait
|
||||
+ session_info::Trait
|
||||
+ dmp::Trait
|
||||
+ ump::Trait
|
||||
+ hrmp::Trait
|
||||
@@ -123,6 +124,7 @@ decl_module! {
|
||||
// - Paras
|
||||
// - Scheduler
|
||||
// - Inclusion
|
||||
// - SessionInfo
|
||||
// - Validity
|
||||
// - DMP
|
||||
// - UMP
|
||||
@@ -131,6 +133,7 @@ decl_module! {
|
||||
paras::Module::<T>::initializer_initialize(now) +
|
||||
scheduler::Module::<T>::initializer_initialize(now) +
|
||||
inclusion::Module::<T>::initializer_initialize(now) +
|
||||
session_info::Module::<T>::initializer_initialize(now) +
|
||||
dmp::Module::<T>::initializer_initialize(now) +
|
||||
ump::Module::<T>::initializer_initialize(now) +
|
||||
hrmp::Module::<T>::initializer_initialize(now);
|
||||
@@ -146,6 +149,7 @@ decl_module! {
|
||||
hrmp::Module::<T>::initializer_finalize();
|
||||
ump::Module::<T>::initializer_finalize();
|
||||
dmp::Module::<T>::initializer_finalize();
|
||||
session_info::Module::<T>::initializer_finalize();
|
||||
inclusion::Module::<T>::initializer_finalize();
|
||||
scheduler::Module::<T>::initializer_finalize();
|
||||
paras::Module::<T>::initializer_finalize();
|
||||
@@ -189,6 +193,7 @@ impl<T: Trait> Module<T> {
|
||||
paras::Module::<T>::initializer_on_new_session(¬ification);
|
||||
scheduler::Module::<T>::initializer_on_new_session(¬ification);
|
||||
inclusion::Module::<T>::initializer_on_new_session(¬ification);
|
||||
session_info::Module::<T>::initializer_on_new_session(¬ification);
|
||||
dmp::Module::<T>::initializer_on_new_session(¬ification);
|
||||
ump::Module::<T>::initializer_on_new_session(¬ification);
|
||||
hrmp::Module::<T>::initializer_on_new_session(¬ification);
|
||||
|
||||
@@ -28,6 +28,7 @@ pub mod inclusion_inherent;
|
||||
pub mod initializer;
|
||||
pub mod paras;
|
||||
pub mod scheduler;
|
||||
pub mod session_info;
|
||||
pub mod validity;
|
||||
pub mod origin;
|
||||
pub mod dmp;
|
||||
|
||||
@@ -24,7 +24,7 @@ use sp_runtime::{
|
||||
BlakeTwo256, IdentityLookup,
|
||||
},
|
||||
};
|
||||
use primitives::v1::{BlockNumber, Header};
|
||||
use primitives::v1::{AuthorityDiscoveryId, BlockNumber, Header};
|
||||
use frame_support::{
|
||||
impl_outer_origin, impl_outer_dispatch, impl_outer_event, parameter_types,
|
||||
weights::Weight, traits::Randomness as RandomnessT,
|
||||
@@ -124,6 +124,14 @@ impl crate::inclusion::Trait for Test {
|
||||
type Event = TestEvent;
|
||||
}
|
||||
|
||||
impl crate::session_info::Trait for Test { }
|
||||
|
||||
impl crate::session_info::AuthorityDiscoveryTrait for Test {
|
||||
fn authorities() -> Vec<AuthorityDiscoveryId> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub type System = frame_system::Module<Test>;
|
||||
|
||||
/// Mocked initializer.
|
||||
@@ -150,6 +158,9 @@ pub type Scheduler = crate::scheduler::Module<Test>;
|
||||
/// Mocked inclusion module.
|
||||
pub type Inclusion = crate::inclusion::Module<Test>;
|
||||
|
||||
/// Mocked session info module.
|
||||
pub type SessionInfo = crate::session_info::Module<Test>;
|
||||
|
||||
/// Create a new set of test externalities.
|
||||
pub fn new_test_ext(state: GenesisConfig) -> TestExternalities {
|
||||
let mut t = state.system.build_storage::<Test>().unwrap();
|
||||
|
||||
@@ -23,12 +23,12 @@ use primitives::v1::{
|
||||
ValidatorId, ValidatorIndex, GroupRotationInfo, CoreState, ValidationData,
|
||||
Id as ParaId, OccupiedCoreAssumption, SessionIndex, ValidationCode,
|
||||
CommittedCandidateReceipt, ScheduledCore, OccupiedCore, CoreOccupied, CoreIndex,
|
||||
GroupIndex, CandidateEvent, PersistedValidationData, AuthorityDiscoveryId,
|
||||
GroupIndex, CandidateEvent, PersistedValidationData, SessionInfo,
|
||||
InboundDownwardMessage, InboundHrmpMessage,
|
||||
};
|
||||
use sp_runtime::traits::Zero;
|
||||
use frame_support::debug;
|
||||
use crate::{initializer, inclusion, scheduler, configuration, paras, dmp, hrmp};
|
||||
use crate::{initializer, inclusion, scheduler, configuration, paras, session_info, dmp, hrmp};
|
||||
|
||||
/// Implementation for the `validators` function of the runtime API.
|
||||
pub fn validators<T: initializer::Trait>() -> Vec<ValidatorId> {
|
||||
@@ -285,28 +285,9 @@ where
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get the `AuthorityDiscoveryId`s corresponding to the given `ValidatorId`s.
|
||||
/// Currently this request is limited to validators in the current session.
|
||||
///
|
||||
/// We assume that every validator runs authority discovery,
|
||||
/// which would allow us to establish point-to-point connection to given validators.
|
||||
// FIXME: handle previous sessions:
|
||||
// https://github.com/paritytech/polkadot/issues/1461
|
||||
pub fn validator_discovery<T>(validators: Vec<ValidatorId>) -> Vec<Option<AuthorityDiscoveryId>>
|
||||
where
|
||||
T: initializer::Trait + pallet_authority_discovery::Trait,
|
||||
{
|
||||
// FIXME: the mapping might be invalid if a session change happens in between the calls
|
||||
// use SessionInfo from https://github.com/paritytech/polkadot/pull/1691
|
||||
let current_validators = <inclusion::Module<T>>::validators();
|
||||
let authorities = <pallet_authority_discovery::Module<T>>::authorities();
|
||||
// We assume the same ordering in authorities as in validators so we can do an index search
|
||||
validators.iter().map(|id| {
|
||||
// FIXME: linear search is slow O(n^2)
|
||||
// use SessionInfo from https://github.com/paritytech/polkadot/pull/1691
|
||||
let validator_index = current_validators.iter().position(|v| v == id);
|
||||
validator_index.and_then(|i| authorities.get(i).cloned())
|
||||
}).collect()
|
||||
/// Get the session info for the given session, if stored.
|
||||
pub fn session_info<T: session_info::Trait>(index: SessionIndex) -> Option<SessionInfo> {
|
||||
<session_info::Module<T>>::session_info(index)
|
||||
}
|
||||
|
||||
/// Implementation for the `dmq_contents` function of the runtime API.
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! The session info module provides information about validator sets
|
||||
//! from prior sessions needed for approvals and disputes.
|
||||
//!
|
||||
//! See https://w3f.github.io/parachain-implementers-guide/runtime/session_info.html.
|
||||
|
||||
use primitives::v1::{AuthorityDiscoveryId, SessionIndex, SessionInfo};
|
||||
use frame_support::{
|
||||
decl_storage, decl_module, decl_error,
|
||||
weights::Weight,
|
||||
};
|
||||
use crate::{configuration, paras, scheduler};
|
||||
use sp_std::{cmp, vec::Vec};
|
||||
|
||||
pub trait Trait:
|
||||
frame_system::Trait
|
||||
+ configuration::Trait
|
||||
+ paras::Trait
|
||||
+ scheduler::Trait
|
||||
+ AuthorityDiscoveryTrait
|
||||
{
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
trait Store for Module<T: Trait> as ParaSessionInfo {
|
||||
/// The earliest session for which previous session info is stored.
|
||||
EarliestStoredSession get(fn earliest_stored_session): SessionIndex;
|
||||
/// Session information in a rolling window.
|
||||
/// Should have an entry in range `EarliestStoredSession..=CurrentSessionIndex`.
|
||||
/// Does not have any entries before the session index in the first session change notification.
|
||||
Sessions get(fn session_info): map hasher(identity) SessionIndex => Option<SessionInfo>;
|
||||
}
|
||||
}
|
||||
|
||||
decl_error! {
|
||||
pub enum Error for Module<T: Trait> { }
|
||||
}
|
||||
|
||||
decl_module! {
|
||||
/// The session info module.
|
||||
pub struct Module<T: Trait> for enum Call where origin: <T as frame_system::Trait>::Origin {
|
||||
type Error = Error<T>;
|
||||
}
|
||||
}
|
||||
|
||||
/// An abstraction for the authority discovery pallet
|
||||
/// to help with mock testing.
|
||||
pub trait AuthorityDiscoveryTrait {
|
||||
/// Retrieve authority identifiers of the current and next authority set.
|
||||
fn authorities() -> Vec<AuthorityDiscoveryId>;
|
||||
}
|
||||
|
||||
impl<T: pallet_authority_discovery::Trait> AuthorityDiscoveryTrait for T {
|
||||
fn authorities() -> Vec<AuthorityDiscoveryId> {
|
||||
<pallet_authority_discovery::Module<T>>::authorities()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trait> Module<T> {
|
||||
/// Handle an incoming session change.
|
||||
pub(crate) fn initializer_on_new_session(
|
||||
notification: &crate::initializer::SessionChangeNotification<T::BlockNumber>
|
||||
) {
|
||||
let config = <configuration::Module<T>>::config();
|
||||
|
||||
let dispute_period = config.dispute_period;
|
||||
let n_parachains = <paras::Module<T>>::parachains().len() as u32;
|
||||
|
||||
let validators = notification.validators.clone();
|
||||
let discovery_keys = <T as AuthorityDiscoveryTrait>::authorities();
|
||||
// FIXME: once we store these keys: https://github.com/paritytech/polkadot/issues/1975
|
||||
let approval_keys = Default::default();
|
||||
let validator_groups = <scheduler::Module<T>>::validator_groups();
|
||||
let n_cores = n_parachains + config.parathread_cores;
|
||||
let zeroth_delay_tranche_width = config.zeroth_delay_tranche_width;
|
||||
let relay_vrf_modulo_samples = config.relay_vrf_modulo_samples;
|
||||
let n_delay_tranches = config.n_delay_tranches;
|
||||
let no_show_slots = config.no_show_slots;
|
||||
let needed_approvals = config.needed_approvals;
|
||||
|
||||
let new_session_index = notification.session_index;
|
||||
let old_earliest_stored_session = EarliestStoredSession::get();
|
||||
let dispute_period = cmp::max(1, dispute_period);
|
||||
let new_earliest_stored_session = new_session_index.checked_sub(dispute_period - 1).unwrap_or(0);
|
||||
let new_earliest_stored_session = cmp::max(new_earliest_stored_session, old_earliest_stored_session);
|
||||
// update `EarliestStoredSession` based on `config.dispute_period`
|
||||
EarliestStoredSession::set(new_earliest_stored_session);
|
||||
// remove all entries from `Sessions` from the previous value up to the new value
|
||||
for idx in old_earliest_stored_session..new_earliest_stored_session {
|
||||
Sessions::remove(&idx);
|
||||
}
|
||||
// create a new entry in `Sessions` with information about the current session
|
||||
let new_session_info = SessionInfo {
|
||||
validators,
|
||||
discovery_keys,
|
||||
approval_keys,
|
||||
validator_groups,
|
||||
n_cores,
|
||||
zeroth_delay_tranche_width,
|
||||
relay_vrf_modulo_samples,
|
||||
n_delay_tranches,
|
||||
no_show_slots,
|
||||
needed_approvals,
|
||||
};
|
||||
Sessions::insert(&new_session_index, &new_session_info);
|
||||
}
|
||||
|
||||
/// Called by the initializer to initialize the session info module.
|
||||
pub(crate) fn initializer_initialize(_now: T::BlockNumber) -> Weight {
|
||||
0
|
||||
}
|
||||
|
||||
/// Called by the initializer to finalize the session info module.
|
||||
pub(crate) fn initializer_finalize() {}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mock::{
|
||||
new_test_ext, Configuration, SessionInfo, System, GenesisConfig as MockGenesisConfig,
|
||||
Origin,
|
||||
};
|
||||
use crate::initializer::SessionChangeNotification;
|
||||
use crate::configuration::HostConfiguration;
|
||||
use frame_support::traits::{OnFinalize, OnInitialize};
|
||||
use primitives::v1::BlockNumber;
|
||||
|
||||
fn run_to_block(
|
||||
to: BlockNumber,
|
||||
new_session: impl Fn(BlockNumber) -> Option<SessionChangeNotification<BlockNumber>>,
|
||||
) {
|
||||
while System::block_number() < to {
|
||||
let b = System::block_number();
|
||||
|
||||
SessionInfo::initializer_finalize();
|
||||
Configuration::initializer_finalize();
|
||||
|
||||
System::on_finalize(b);
|
||||
|
||||
System::on_initialize(b + 1);
|
||||
System::set_block_number(b + 1);
|
||||
|
||||
if let Some(notification) = new_session(b + 1) {
|
||||
Configuration::initializer_on_new_session(¬ification.validators, ¬ification.queued);
|
||||
SessionInfo::initializer_on_new_session(¬ification);
|
||||
}
|
||||
|
||||
Configuration::initializer_initialize(b + 1);
|
||||
SessionInfo::initializer_initialize(b + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn default_config() -> HostConfiguration<BlockNumber> {
|
||||
HostConfiguration {
|
||||
parathread_cores: 1,
|
||||
dispute_period: 2,
|
||||
needed_approvals: 3,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn genesis_config() -> MockGenesisConfig {
|
||||
MockGenesisConfig {
|
||||
configuration: configuration::GenesisConfig {
|
||||
config: default_config(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn session_changes(n: BlockNumber) -> Option<SessionChangeNotification<BlockNumber>> {
|
||||
match n {
|
||||
100 => Some(SessionChangeNotification {
|
||||
session_index: 10,
|
||||
..Default::default()
|
||||
}),
|
||||
200 => Some(SessionChangeNotification {
|
||||
session_index: 20,
|
||||
..Default::default()
|
||||
}),
|
||||
300 => Some(SessionChangeNotification {
|
||||
session_index: 30,
|
||||
..Default::default()
|
||||
}),
|
||||
400 => Some(SessionChangeNotification {
|
||||
session_index: 40,
|
||||
..Default::default()
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_session_every_block(n: BlockNumber) -> Option<SessionChangeNotification<BlockNumber>> {
|
||||
Some(SessionChangeNotification{
|
||||
session_index: n,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_pruning_is_based_on_dispute_deriod() {
|
||||
new_test_ext(genesis_config()).execute_with(|| {
|
||||
run_to_block(100, session_changes);
|
||||
assert_eq!(EarliestStoredSession::get(), 9);
|
||||
|
||||
// changing dispute_period works
|
||||
let dispute_period = 5;
|
||||
Configuration::set_dispute_period(Origin::root(), dispute_period).unwrap();
|
||||
run_to_block(200, session_changes);
|
||||
assert_eq!(EarliestStoredSession::get(), 20 - dispute_period + 1);
|
||||
|
||||
// we don't have that many sessions stored
|
||||
let new_dispute_period = 16;
|
||||
Configuration::set_dispute_period(Origin::root(), new_dispute_period).unwrap();
|
||||
run_to_block(300, session_changes);
|
||||
assert_eq!(EarliestStoredSession::get(), 20 - dispute_period + 1);
|
||||
|
||||
// now we do
|
||||
run_to_block(400, session_changes);
|
||||
assert_eq!(EarliestStoredSession::get(), 40 - new_dispute_period + 1);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_info_is_based_on_config() {
|
||||
new_test_ext(genesis_config()).execute_with(|| {
|
||||
run_to_block(1, new_session_every_block);
|
||||
let session = Sessions::get(&1).unwrap();
|
||||
assert_eq!(session.needed_approvals, 3);
|
||||
|
||||
// change some param
|
||||
Configuration::set_needed_approvals(Origin::root(), 42).unwrap();
|
||||
run_to_block(2, new_session_every_block);
|
||||
let session = Sessions::get(&2).unwrap();
|
||||
assert_eq!(session.needed_approvals, 42);
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user