diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 4f360c9580..387f269f0b 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -67,7 +67,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // to equal spec_version. If only runtime implementation changes and behavior does not, then // leave spec_version as is and increment impl_version. spec_version: 102, - impl_version: 103, + impl_version: 104, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/srml/session/src/lib.rs b/substrate/srml/session/src/lib.rs index 8dcc82d59b..4f3e1ce9f0 100644 --- a/substrate/srml/session/src/lib.rs +++ b/substrate/srml/session/src/lib.rs @@ -115,11 +115,11 @@ #![cfg_attr(not(feature = "std"), no_std)] -use rstd::{prelude::*, marker::PhantomData, ops::Rem}; +use rstd::{prelude::*, marker::PhantomData, ops::{Sub, Rem}}; #[cfg(not(feature = "std"))] use rstd::alloc::borrow::ToOwned; use parity_codec::Decode; -use primitives::traits::{Zero, Saturating, Member, OpaqueKeys}; +use primitives::traits::{Zero, Member, OpaqueKeys}; use srml_support::{ ConsensusEngineId, StorageValue, StorageMap, for_each_tuple, decl_module, decl_event, decl_storage, @@ -134,18 +134,24 @@ pub trait ShouldEndSession { fn should_end_session(now: BlockNumber) -> bool; } +/// Ends the session after a fixed period of blocks. +/// +/// The first session will have length of `Offset`, and +/// the following sessions will have length of `Period`. +/// This may prove nonsensical if `Offset` >= `Period`. pub struct PeriodicSessions< Period, Offset, >(PhantomData<(Period, Offset)>); impl< - BlockNumber: Rem + Saturating + Zero, + BlockNumber: Rem + Sub + Zero + PartialOrd, Period: Get, Offset: Get, > ShouldEndSession for PeriodicSessions { fn should_end_session(now: BlockNumber) -> bool { - ((now.saturating_sub(Offset::get())) % Period::get()).is_zero() + let offset = Offset::get(); + now >= offset && ((now - offset) % Period::get()).is_zero() } } @@ -590,4 +596,33 @@ mod tests { assert_eq!(authorities(), vec![UintAuthorityId(1), UintAuthorityId(5), UintAuthorityId(3)]); }); } + + #[test] + fn periodic_session_works() { + struct Period; + struct Offset; + + impl Get for Period { + fn get() -> u64 { 10 } + } + + impl Get for Offset { + fn get() -> u64 { 3 } + } + + + type P = PeriodicSessions; + + for i in 0..3 { + assert!(!P::should_end_session(i)); + } + + assert!(P::should_end_session(3)); + + for i in (1..10).map(|i| 3 + i) { + assert!(!P::should_end_session(i)); + } + + assert!(P::should_end_session(13)); + } }