1
// This file is part of Substrate.
2

            
3
// Copyright (C) Parity Technologies (UK) Ltd.
4
// SPDX-License-Identifier: Apache-2.0
5

            
6
// Licensed under the Apache License, Version 2.0 (the "License");
7
// you may not use this file except in compliance with the License.
8
// You may obtain a copy of the License at
9
//
10
// 	http://www.apache.org/licenses/LICENSE-2.0
11
//
12
// Unless required by applicable law or agreed to in writing, software
13
// distributed under the License is distributed on an "AS IS" BASIS,
14
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
// See the License for the specific language governing permissions and
16
// limitations under the License.
17

            
18
//! # Session Pallet
19
//!
20
//! The Session pallet allows validators to manage their session keys, provides a function for
21
//! changing the session length, and handles session rotation.
22
//!
23
//! - [`Config`]
24
//! - [`Call`]
25
//! - [`Pallet`]
26
//!
27
//! ## Overview
28
//!
29
//! ### Terminology
30
//! <!-- Original author of paragraph: @gavofyork -->
31
//!
32
//! - **Session:** A session is a period of time that has a constant set of validators. Validators
33
//!   can only join or exit the validator set at a session change. It is measured in block numbers.
34
//!   The block where a session is ended is determined by the `ShouldEndSession` trait. When the
35
//!   session is ending, a new validator set can be chosen by `OnSessionEnding` implementations.
36
//!
37
//! - **Session key:** A session key is actually several keys kept together that provide the various
38
//!   signing functions required by network authorities/validators in pursuit of their duties.
39
//! - **Validator ID:** Every account has an associated validator ID. For some simple staking
40
//!   systems, this may just be the same as the account ID. For staking systems using a
41
//!   stash/controller model, the validator ID would be the stash account ID of the controller.
42
//!
43
//! - **Session key configuration process:** Session keys are set using `set_keys` for use not in
44
//!   the next session, but the session after next. They are stored in `NextKeys`, a mapping between
45
//!   the caller's `ValidatorId` and the session keys provided. `set_keys` allows users to set their
46
//!   session key prior to being selected as validator. It is a public call since it uses
47
//!   `ensure_signed`, which checks that the origin is a signed account. As such, the account ID of
48
//!   the origin stored in `NextKeys` may not necessarily be associated with a block author or a
49
//!   validator. The session keys of accounts are removed once their account balance is zero.
50
//!
51
//! - **Session length:** This pallet does not assume anything about the length of each session.
52
//!   Rather, it relies on an implementation of `ShouldEndSession` to dictate a new session's start.
53
//!   This pallet provides the `PeriodicSessions` struct for simple periodic sessions.
54
//!
55
//! - **Session rotation configuration:** Configure as either a 'normal' (rewardable session where
56
//!   rewards are applied) or 'exceptional' (slashable) session rotation.
57
//!
58
//! - **Session rotation process:** At the beginning of each block, the `on_initialize` function
59
//!   queries the provided implementation of `ShouldEndSession`. If the session is to end the newly
60
//!   activated validator IDs and session keys are taken from storage and passed to the
61
//!   `SessionHandler`. The validator set supplied by `SessionManager::new_session` and the
62
//!   corresponding session keys, which may have been registered via `set_keys` during the previous
63
//!   session, are written to storage where they will wait one session before being passed to the
64
//!   `SessionHandler` themselves.
65
//!
66
//! ### Goals
67
//!
68
//! The Session pallet is designed to make the following possible:
69
//!
70
//! - Set session keys of the validator set for upcoming sessions.
71
//! - Control the length of sessions.
72
//! - Configure and switch between either normal or exceptional session rotations.
73
//!
74
//! ## Interface
75
//!
76
//! ### Dispatchable Functions
77
//!
78
//! - `set_keys` - Set a validator's session keys for upcoming sessions.
79
//!
80
//! ### Public Functions
81
//!
82
//! - `rotate_session` - Change to the next session. Register the new authority set. Queue changes
83
//!   for next session rotation.
84
//! - `disable_index` - Disable a validator by index.
85
//! - `disable` - Disable a validator by Validator ID
86
//!
87
//! ## Usage
88
//!
89
//! ### Example from the FRAME
90
//!
91
//! The [Staking pallet](../pallet_staking/index.html) uses the Session pallet to get the validator
92
//! set.
93
//!
94
//! ```
95
//! use pallet_session as session;
96
//!
97
//! fn validators<T: pallet_session::Config>() -> Vec<<T as pallet_session::Config>::ValidatorId> {
98
//! 	pallet_session::Validators::<T>::get()
99
//! }
100
//! # fn main(){}
101
//! ```
102
//!
103
//! ## Related Pallets
104
//!
105
//! - [Staking](../pallet_staking/index.html)
106

            
107
#![cfg_attr(not(feature = "std"), no_std)]
108

            
109
#[cfg(feature = "historical")]
110
pub mod historical;
111
pub mod migrations;
112
#[cfg(test)]
113
mod mock;
114
#[cfg(test)]
115
mod tests;
116
pub mod weights;
117

            
118
extern crate alloc;
119

            
120
use alloc::{boxed::Box, vec::Vec};
121
use codec::{Decode, MaxEncodedLen};
122
use core::{
123
	marker::PhantomData,
124
	ops::{Rem, Sub},
125
};
126
use frame_support::{
127
	dispatch::DispatchResult,
128
	ensure,
129
	traits::{
130
		EstimateNextNewSession, EstimateNextSessionRotation, FindAuthor, Get, OneSessionHandler,
131
		ValidatorRegistration, ValidatorSet,
132
	},
133
	weights::Weight,
134
	Parameter,
135
};
136
use frame_system::pallet_prelude::BlockNumberFor;
137
use sp_runtime::{
138
	traits::{AtLeast32BitUnsigned, Convert, Member, One, OpaqueKeys, Zero},
139
	ConsensusEngineId, DispatchError, KeyTypeId, Permill, RuntimeAppPublic,
140
};
141
use sp_staking::SessionIndex;
142

            
143
pub use pallet::*;
144
pub use weights::WeightInfo;
145

            
146
/// Decides whether the session should be ended.
147
pub trait ShouldEndSession<BlockNumber> {
148
	/// Return `true` if the session should be ended.
149
	fn should_end_session(now: BlockNumber) -> bool;
150
}
151

            
152
/// Ends the session after a fixed period of blocks.
153
///
154
/// The first session will have length of `Offset`, and
155
/// the following sessions will have length of `Period`.
156
/// This may prove nonsensical if `Offset` >= `Period`.
157
pub struct PeriodicSessions<Period, Offset>(PhantomData<(Period, Offset)>);
158

            
159
impl<
160
		BlockNumber: Rem<Output = BlockNumber> + Sub<Output = BlockNumber> + Zero + PartialOrd,
161
		Period: Get<BlockNumber>,
162
		Offset: Get<BlockNumber>,
163
	> ShouldEndSession<BlockNumber> for PeriodicSessions<Period, Offset>
164
{
165
	fn should_end_session(now: BlockNumber) -> bool {
166
		let offset = Offset::get();
167
		now >= offset && ((now - offset) % Period::get()).is_zero()
168
	}
169
}
170

            
171
impl<
172
		BlockNumber: AtLeast32BitUnsigned + Clone,
173
		Period: Get<BlockNumber>,
174
		Offset: Get<BlockNumber>,
175
	> EstimateNextSessionRotation<BlockNumber> for PeriodicSessions<Period, Offset>
176
{
177
	fn average_session_length() -> BlockNumber {
178
		Period::get()
179
	}
180

            
181
	fn estimate_current_session_progress(now: BlockNumber) -> (Option<Permill>, Weight) {
182
		let offset = Offset::get();
183
		let period = Period::get();
184

            
185
		// NOTE: we add one since we assume that the current block has already elapsed,
186
		// i.e. when evaluating the last block in the session the progress should be 100%
187
		// (0% is never returned).
188
		let progress = if now >= offset {
189
			let current = (now - offset) % period.clone() + One::one();
190
			Some(Permill::from_rational(current, period))
191
		} else {
192
			Some(Permill::from_rational(now + One::one(), offset))
193
		};
194

            
195
		// Weight note: `estimate_current_session_progress` has no storage reads and trivial
196
		// computational overhead. There should be no risk to the chain having this weight value be
197
		// zero for now. However, this value of zero was not properly calculated, and so it would be
198
		// reasonable to come back here and properly calculate the weight of this function.
199
		(progress, Zero::zero())
200
	}
201

            
202
	fn estimate_next_session_rotation(now: BlockNumber) -> (Option<BlockNumber>, Weight) {
203
		let offset = Offset::get();
204
		let period = Period::get();
205

            
206
		let next_session = if now > offset {
207
			let block_after_last_session = (now.clone() - offset) % period.clone();
208
			if block_after_last_session > Zero::zero() {
209
				now.saturating_add(period.saturating_sub(block_after_last_session))
210
			} else {
211
				// this branch happens when the session is already rotated or will rotate in this
212
				// block (depending on being called before or after `session::on_initialize`). Here,
213
				// we assume the latter, namely that this is called after `session::on_initialize`,
214
				// and thus we add period to it as well.
215
				now + period
216
			}
217
		} else {
218
			offset
219
		};
220

            
221
		// Weight note: `estimate_next_session_rotation` has no storage reads and trivial
222
		// computational overhead. There should be no risk to the chain having this weight value be
223
		// zero for now. However, this value of zero was not properly calculated, and so it would be
224
		// reasonable to come back here and properly calculate the weight of this function.
225
		(Some(next_session), Zero::zero())
226
	}
227
}
228

            
229
/// A trait for managing creation of new validator set.
230
pub trait SessionManager<ValidatorId> {
231
	/// Plan a new session, and optionally provide the new validator set.
232
	///
233
	/// Even if the validator-set is the same as before, if any underlying economic conditions have
234
	/// changed (i.e. stake-weights), the new validator set must be returned. This is necessary for
235
	/// consensus engines making use of the session pallet to issue a validator-set change so
236
	/// misbehavior can be provably associated with the new economic conditions as opposed to the
237
	/// old. The returned validator set, if any, will not be applied until `new_index`. `new_index`
238
	/// is strictly greater than from previous call.
239
	///
240
	/// The first session start at index 0.
241
	///
242
	/// `new_session(session)` is guaranteed to be called before `end_session(session-1)`. In other
243
	/// words, a new session must always be planned before an ongoing one can be finished.
244
	fn new_session(new_index: SessionIndex) -> Option<Vec<ValidatorId>>;
245
	/// Same as `new_session`, but it this should only be called at genesis.
246
	///
247
	/// The session manager might decide to treat this in a different way. Default impl is simply
248
	/// using [`new_session`](Self::new_session).
249
	fn new_session_genesis(new_index: SessionIndex) -> Option<Vec<ValidatorId>> {
250
		Self::new_session(new_index)
251
	}
252
	/// End the session.
253
	///
254
	/// Because the session pallet can queue validator set the ending session can be lower than the
255
	/// last new session index.
256
	fn end_session(end_index: SessionIndex);
257
	/// Start an already planned session.
258
	///
259
	/// The session start to be used for validation.
260
	fn start_session(start_index: SessionIndex);
261
}
262

            
263
impl<A> SessionManager<A> for () {
264
	fn new_session(_: SessionIndex) -> Option<Vec<A>> {
265
		None
266
	}
267
	fn start_session(_: SessionIndex) {}
268
	fn end_session(_: SessionIndex) {}
269
}
270

            
271
/// Handler for session life cycle events.
272
pub trait SessionHandler<ValidatorId> {
273
	/// All the key type ids this session handler can process.
274
	///
275
	/// The order must be the same as it expects them in
276
	/// [`on_new_session`](Self::on_new_session<Ks>) and
277
	/// [`on_genesis_session`](Self::on_genesis_session<Ks>).
278
	const KEY_TYPE_IDS: &'static [KeyTypeId];
279

            
280
	/// The given validator set will be used for the genesis session.
281
	/// It is guaranteed that the given validator set will also be used
282
	/// for the second session, therefore the first call to `on_new_session`
283
	/// should provide the same validator set.
284
	fn on_genesis_session<Ks: OpaqueKeys>(validators: &[(ValidatorId, Ks)]);
285

            
286
	/// Session set has changed; act appropriately. Note that this can be called
287
	/// before initialization of your pallet.
288
	///
289
	/// `changed` is true whenever any of the session keys or underlying economic
290
	/// identities or weightings behind `validators` keys has changed. `queued_validators`
291
	/// could change without `validators` changing. Example of possible sequent calls:
292
	///     Session N: on_new_session(false, unchanged_validators, unchanged_queued_validators)
293
	///     Session N + 1: on_new_session(false, unchanged_validators, new_queued_validators)
294
	/// 	Session N + 2: on_new_session(true, new_queued_validators, new_queued_validators)
295
	fn on_new_session<Ks: OpaqueKeys>(
296
		changed: bool,
297
		validators: &[(ValidatorId, Ks)],
298
		queued_validators: &[(ValidatorId, Ks)],
299
	);
300

            
301
	/// A notification for end of the session.
302
	///
303
	/// Note it is triggered before any [`SessionManager::end_session`] handlers,
304
	/// so we can still affect the validator set.
305
	fn on_before_session_ending() {}
306

            
307
	/// A validator got disabled. Act accordingly until a new session begins.
308
	fn on_disabled(validator_index: u32);
309
}
310

            
311
#[impl_trait_for_tuples::impl_for_tuples(1, 30)]
312
#[tuple_types_custom_trait_bound(OneSessionHandler<AId>)]
313
impl<AId> SessionHandler<AId> for Tuple {
314
	for_tuples!(
315
		const KEY_TYPE_IDS: &'static [KeyTypeId] = &[ #( <Tuple::Key as RuntimeAppPublic>::ID ),* ];
316
	);
317

            
318
3
	fn on_genesis_session<Ks: OpaqueKeys>(validators: &[(AId, Ks)]) {
319
3
		for_tuples!(
320
3
			#(
321
3
				let our_keys: Box<dyn Iterator<Item=_>> = Box::new(validators.iter()
322
3
					.filter_map(|k|
323
3
						k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
324
3
					)
325
3
				);
326
3

            
327
3
				Tuple::on_genesis_session(our_keys);
328
3
			)*
329
3
		)
330
3
	}
331

            
332
135231
	fn on_new_session<Ks: OpaqueKeys>(
333
135231
		changed: bool,
334
135231
		validators: &[(AId, Ks)],
335
135231
		queued_validators: &[(AId, Ks)],
336
135231
	) {
337
135231
		for_tuples!(
338
135231
			#(
339
135231
				let our_keys: Box<dyn Iterator<Item=_>> = Box::new(validators.iter()
340
135231
					.filter_map(|k|
341
135231
						k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
342
135231
					));
343
135231
				let queued_keys: Box<dyn Iterator<Item=_>> = Box::new(queued_validators.iter()
344
135231
					.filter_map(|k|
345
135231
						k.1.get::<Tuple::Key>(<Tuple::Key as RuntimeAppPublic>::ID).map(|k1| (&k.0, k1))
346
135231
					));
347
135231
				Tuple::on_new_session(changed, our_keys, queued_keys);
348
135231
			)*
349
135231
		)
350
135231
	}
351

            
352
135231
	fn on_before_session_ending() {
353
135231
		for_tuples!( #( Tuple::on_before_session_ending(); )* )
354
135231
	}
355

            
356
	fn on_disabled(i: u32) {
357
		for_tuples!( #( Tuple::on_disabled(i); )* )
358
	}
359
}
360

            
361
/// `SessionHandler` for tests that use `UintAuthorityId` as `Keys`.
362
pub struct TestSessionHandler;
363
impl<AId> SessionHandler<AId> for TestSessionHandler {
364
	const KEY_TYPE_IDS: &'static [KeyTypeId] = &[sp_runtime::key_types::DUMMY];
365
	fn on_genesis_session<Ks: OpaqueKeys>(_: &[(AId, Ks)]) {}
366
	fn on_new_session<Ks: OpaqueKeys>(_: bool, _: &[(AId, Ks)], _: &[(AId, Ks)]) {}
367
	fn on_before_session_ending() {}
368
	fn on_disabled(_: u32) {}
369
}
370

            
371
3192
#[frame_support::pallet]
372
pub mod pallet {
373
	use super::*;
374
	use frame_support::pallet_prelude::*;
375
	use frame_system::pallet_prelude::*;
376

            
377
	/// The in-code storage version.
378
	const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);
379

            
380
1698
	#[pallet::pallet]
381
	#[pallet::storage_version(STORAGE_VERSION)]
382
	#[pallet::without_storage_info]
383
	pub struct Pallet<T>(_);
384

            
385
	#[pallet::config]
386
	pub trait Config: frame_system::Config {
387
		/// The overarching event type.
388
		type RuntimeEvent: From<Event> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
389

            
390
		/// A stable ID for a validator.
391
		type ValidatorId: Member
392
			+ Parameter
393
			+ MaybeSerializeDeserialize
394
			+ MaxEncodedLen
395
			+ TryFrom<Self::AccountId>;
396

            
397
		/// A conversion from account ID to validator ID.
398
		///
399
		/// Its cost must be at most one storage read.
400
		type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;
401

            
402
		/// Indicator for when to end the session.
403
		type ShouldEndSession: ShouldEndSession<BlockNumberFor<Self>>;
404

            
405
		/// Something that can predict the next session rotation. This should typically come from
406
		/// the same logical unit that provides [`ShouldEndSession`], yet, it gives a best effort
407
		/// estimate. It is helpful to implement [`EstimateNextNewSession`].
408
		type NextSessionRotation: EstimateNextSessionRotation<BlockNumberFor<Self>>;
409

            
410
		/// Handler for managing new session.
411
		type SessionManager: SessionManager<Self::ValidatorId>;
412

            
413
		/// Handler when a session has changed.
414
		type SessionHandler: SessionHandler<Self::ValidatorId>;
415

            
416
		/// The keys.
417
		type Keys: OpaqueKeys + Member + Parameter + MaybeSerializeDeserialize;
418

            
419
		/// Weight information for extrinsics in this pallet.
420
		type WeightInfo: WeightInfo;
421
	}
422

            
423
	#[pallet::genesis_config]
424
	#[derive(frame_support::DefaultNoBound)]
425
	pub struct GenesisConfig<T: Config> {
426
		/// Initial list of validator at genesis representing by their `(AccountId, ValidatorId,
427
		/// Keys)`. These keys will be considered authorities for the first two sessions and they
428
		/// will be valid at least until session 2
429
		pub keys: Vec<(T::AccountId, T::ValidatorId, T::Keys)>,
430
		/// List of (AccountId, ValidatorId, Keys) that will be registered at genesis, but not as
431
		/// active validators. These keys are set, together with `keys`, as authority candidates
432
		/// for future sessions (enactable from session 2 onwards)
433
		pub non_authority_keys: Vec<(T::AccountId, T::ValidatorId, T::Keys)>,
434
	}
435

            
436
	#[pallet::genesis_build]
437
	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
438
3
		fn build(&self) {
439
3
			if T::SessionHandler::KEY_TYPE_IDS.len() != T::Keys::key_ids().len() {
440
				panic!("Number of keys in session handler and session keys does not match");
441
3
			}
442
3

            
443
3
			T::SessionHandler::KEY_TYPE_IDS
444
3
				.iter()
445
3
				.zip(T::Keys::key_ids())
446
3
				.enumerate()
447
21
				.for_each(|(i, (sk, kk))| {
448
21
					if sk != kk {
449
						panic!(
450
							"Session handler and session key expect different key type at index: {}",
451
							i,
452
						);
453
21
					}
454
21
				});
455

            
456
12
			for (account, val, keys) in
457
3
				self.keys.iter().chain(self.non_authority_keys.iter()).cloned()
458
			{
459
12
				Pallet::<T>::inner_set_keys(&val, keys)
460
12
					.expect("genesis config must not contain duplicates; qed");
461
12
				if frame_system::Pallet::<T>::inc_consumers_without_limit(&account).is_err() {
462
					// This will leak a provider reference, however it only happens once (at
463
					// genesis) so it's really not a big deal and we assume that the user wants to
464
					// do this since it's the only way a non-endowed account can contain a session
465
					// key.
466
					frame_system::Pallet::<T>::inc_providers(&account);
467
12
				}
468
			}
469

            
470
3
			let initial_validators_0 =
471
3
				T::SessionManager::new_session_genesis(0).unwrap_or_else(|| {
472
					frame_support::print(
473
						"No initial validator provided by `SessionManager`, use \
474
						session config keys to generate initial validator set.",
475
					);
476
					self.keys.iter().map(|x| x.1.clone()).collect()
477
3
				});
478
3

            
479
3
			let initial_validators_1 = T::SessionManager::new_session_genesis(1)
480
3
				.unwrap_or_else(|| initial_validators_0.clone());
481
3

            
482
3
			let queued_keys: Vec<_> = initial_validators_1
483
3
				.into_iter()
484
3
				.filter_map(|v| Pallet::<T>::load_keys(&v).map(|k| (v, k)))
485
3
				.collect();
486
3

            
487
3
			// Tell everyone about the genesis session keys
488
3
			T::SessionHandler::on_genesis_session::<T::Keys>(&queued_keys);
489
3

            
490
3
			Validators::<T>::put(initial_validators_0);
491
3
			QueuedKeys::<T>::put(queued_keys);
492
3

            
493
3
			T::SessionManager::start_session(0);
494
3
		}
495
	}
496

            
497
	/// The current set of validators.
498
1439022
	#[pallet::storage]
499
	pub type Validators<T: Config> = StorageValue<_, Vec<T::ValidatorId>, ValueQuery>;
500

            
501
	/// Current index of the session.
502
2281896
	#[pallet::storage]
503
	pub type CurrentIndex<T> = StorageValue<_, SessionIndex, ValueQuery>;
504

            
505
	/// True if the underlying economic identities or weighting behind the validators
506
	/// has changed in the queued validator set.
507
540924
	#[pallet::storage]
508
	pub type QueuedChanged<T> = StorageValue<_, bool, ValueQuery>;
509

            
510
	/// The queued keys for the next session. When the next session begins, these keys
511
	/// will be used to determine the validator's session keys.
512
540930
	#[pallet::storage]
513
	pub type QueuedKeys<T: Config> = StorageValue<_, Vec<(T::ValidatorId, T::Keys)>, ValueQuery>;
514

            
515
	/// Indices of disabled validators.
516
	///
517
	/// The vec is always kept sorted so that we can find whether a given validator is
518
	/// disabled using binary search. It gets cleared when `on_session_ending` returns
519
	/// a new set of identities.
520
809874
	#[pallet::storage]
521
	pub type DisabledValidators<T> = StorageValue<_, Vec<u32>, ValueQuery>;
522

            
523
	/// The next session keys for a validator.
524
545604
	#[pallet::storage]
525
	pub type NextKeys<T: Config> =
526
		StorageMap<_, Twox64Concat, T::ValidatorId, T::Keys, OptionQuery>;
527

            
528
	/// The owner of a key. The key is the `KeyTypeId` + the encoded key.
529
31254
	#[pallet::storage]
530
	pub type KeyOwner<T: Config> =
531
		StorageMap<_, Twox64Concat, (KeyTypeId, Vec<u8>), T::ValidatorId, OptionQuery>;
532

            
533
	#[pallet::event]
534
135231
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
535
	pub enum Event {
536
		/// New session has happened. Note that the argument is the session index, not the
537
		/// block number as the type might suggest.
538
		NewSession { session_index: SessionIndex },
539
	}
540

            
541
	/// Error for the session pallet.
542
1896
	#[pallet::error]
543
	pub enum Error<T> {
544
		/// Invalid ownership proof.
545
		InvalidProof,
546
		/// No associated validator ID for account.
547
		NoAssociatedValidatorId,
548
		/// Registered duplicate key.
549
		DuplicatedKey,
550
		/// No keys are associated with this account.
551
		NoKeys,
552
		/// Key setting account is not live, so it's impossible to associate keys.
553
		NoAccount,
554
	}
555

            
556
554367
	#[pallet::hooks]
557
	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
558
		/// Called when a block is initialized. Will rotate session if it is the last
559
		/// block of the current session.
560
194763
		fn on_initialize(n: BlockNumberFor<T>) -> Weight {
561
194763
			if T::ShouldEndSession::should_end_session(n) {
562
135231
				Self::rotate_session();
563
135231
				T::BlockWeights::get().max_block
564
			} else {
565
				// NOTE: the non-database part of the weight for `should_end_session(n)` is
566
				// included as weight for empty block, the database part is expected to be in
567
				// cache.
568
59532
				Weight::zero()
569
			}
570
194763
		}
571
	}
572

            
573
11847
	#[pallet::call]
574
	impl<T: Config> Pallet<T> {
575
		/// Sets the session key(s) of the function caller to `keys`.
576
		/// Allows an account to set its session key prior to becoming a validator.
577
		/// This doesn't take effect until the next session.
578
		///
579
		/// The dispatch origin of this function must be signed.
580
		///
581
		/// ## Complexity
582
		/// - `O(1)`. Actual cost depends on the number of length of `T::Keys::key_ids()` which is
583
		///   fixed.
584
		#[pallet::call_index(0)]
585
		#[pallet::weight(T::WeightInfo::set_keys())]
586
1806
		pub fn set_keys(origin: OriginFor<T>, keys: T::Keys, proof: Vec<u8>) -> DispatchResult {
587
1806
			let who = ensure_signed(origin)?;
588
1806
			ensure!(keys.ownership_proof_is_valid(&proof), Error::<T>::InvalidProof);
589

            
590
1806
			Self::do_set_keys(&who, keys)?;
591
1488
			Ok(())
592
		}
593

            
594
		/// Removes any session key(s) of the function caller.
595
		///
596
		/// This doesn't take effect until the next session.
597
		///
598
		/// The dispatch origin of this function must be Signed and the account must be either be
599
		/// convertible to a validator ID using the chain's typical addressing system (this usually
600
		/// means being a controller account) or directly convertible into a validator ID (which
601
		/// usually means being a stash account).
602
		///
603
		/// ## Complexity
604
		/// - `O(1)` in number of key types. Actual cost depends on the number of length of
605
		///   `T::Keys::key_ids()` which is fixed.
606
		#[pallet::call_index(1)]
607
		#[pallet::weight(T::WeightInfo::purge_keys())]
608
1380
		pub fn purge_keys(origin: OriginFor<T>) -> DispatchResult {
609
1380
			let who = ensure_signed(origin)?;
610
1380
			Self::do_purge_keys(&who)?;
611
750
			Ok(())
612
		}
613
	}
614
}
615

            
616
impl<T: Config> Pallet<T> {
617
	/// Public function to access the current set of validators.
618
270783
	pub fn validators() -> Vec<T::ValidatorId> {
619
270783
		Validators::<T>::get()
620
270783
	}
621

            
622
	/// Public function to access the current session index.
623
870486
	pub fn current_index() -> SessionIndex {
624
870486
		CurrentIndex::<T>::get()
625
870486
	}
626

            
627
	/// Public function to access the queued keys.
628
	pub fn queued_keys() -> Vec<(T::ValidatorId, T::Keys)> {
629
		QueuedKeys::<T>::get()
630
	}
631

            
632
	/// Public function to access the disabled validators.
633
	pub fn disabled_validators() -> Vec<u32> {
634
		DisabledValidators::<T>::get()
635
	}
636

            
637
	/// Move on to next session. Register new validator set and session keys. Changes to the
638
	/// validator set have a session of delay to take effect. This allows for equivocation
639
	/// punishment after a fork.
640
135231
	pub fn rotate_session() {
641
135231
		let session_index = CurrentIndex::<T>::get();
642
135231
		log::trace!(target: "runtime::session", "rotating session {:?}", session_index);
643

            
644
135231
		let changed = QueuedChanged::<T>::get();
645
135231

            
646
135231
		// Inform the session handlers that a session is going to end.
647
135231
		T::SessionHandler::on_before_session_ending();
648
135231
		T::SessionManager::end_session(session_index);
649
135231

            
650
135231
		// Get queued session keys and validators.
651
135231
		let session_keys = QueuedKeys::<T>::get();
652
135231
		let validators =
653
135231
			session_keys.iter().map(|(validator, _)| validator.clone()).collect::<Vec<_>>();
654
135231
		Validators::<T>::put(&validators);
655
135231

            
656
135231
		if changed {
657
15411
			// reset disabled validators if active set was changed
658
15411
			DisabledValidators::<T>::take();
659
119820
		}
660

            
661
		// Increment session index.
662
135231
		let session_index = session_index + 1;
663
135231
		CurrentIndex::<T>::put(session_index);
664
135231

            
665
135231
		T::SessionManager::start_session(session_index);
666
135231

            
667
135231
		// Get next validator set.
668
135231
		let maybe_next_validators = T::SessionManager::new_session(session_index + 1);
669
135231
		let (next_validators, next_identities_changed) =
670
135231
			if let Some(validators) = maybe_next_validators {
671
				// NOTE: as per the documentation on `OnSessionEnding`, we consider
672
				// the validator set as having changed even if the validators are the
673
				// same as before, as underlying economic conditions may have changed.
674
16500
				(validators, true)
675
			} else {
676
118731
				(Validators::<T>::get(), false)
677
			};
678

            
679
		// Queue next session keys.
680
135231
		let (queued_amalgamated, next_changed) = {
681
135231
			// until we are certain there has been a change, iterate the prior
682
135231
			// validators along with the current and check for changes
683
135231
			let mut changed = next_identities_changed;
684
135231

            
685
135231
			let mut now_session_keys = session_keys.iter();
686
135231
			let mut check_next_changed = |keys: &T::Keys| {
687
				if changed {
688
					return;
689
				}
690
				// since a new validator set always leads to `changed` starting
691
				// as true, we can ensure that `now_session_keys` and `next_validators`
692
				// have the same length. this function is called once per iteration.
693
				if let Some((_, old_keys)) = now_session_keys.next() {
694
					if old_keys != keys {
695
						changed = true;
696
					}
697
				}
698
135231
			};
699
135231
			let queued_amalgamated = next_validators
700
135231
				.into_iter()
701
135231
				.filter_map(|a| {
702
					let k = Self::load_keys(&a)?;
703
					check_next_changed(&k);
704
					Some((a, k))
705
135231
				})
706
135231
				.collect::<Vec<_>>();
707
135231

            
708
135231
			(queued_amalgamated, changed)
709
135231
		};
710
135231

            
711
135231
		QueuedKeys::<T>::put(queued_amalgamated.clone());
712
135231
		QueuedChanged::<T>::put(next_changed);
713
135231

            
714
135231
		// Record that this happened.
715
135231
		Self::deposit_event(Event::NewSession { session_index });
716
135231

            
717
135231
		// Tell everyone about the new session keys.
718
135231
		T::SessionHandler::on_new_session::<T::Keys>(changed, &session_keys, &queued_amalgamated);
719
135231
	}
720

            
721
	/// Disable the validator of index `i`, returns `false` if the validator was already disabled.
722
	pub fn disable_index(i: u32) -> bool {
723
		if i >= Validators::<T>::decode_len().unwrap_or(0) as u32 {
724
			return false
725
		}
726

            
727
		DisabledValidators::<T>::mutate(|disabled| {
728
			if let Err(index) = disabled.binary_search(&i) {
729
				disabled.insert(index, i);
730
				T::SessionHandler::on_disabled(i);
731
				return true
732
			}
733

            
734
			false
735
		})
736
	}
737

            
738
	/// Disable the validator identified by `c`. (If using with the staking pallet,
739
	/// this would be their *stash* account.)
740
	///
741
	/// Returns `false` either if the validator could not be found or it was already
742
	/// disabled.
743
	pub fn disable(c: &T::ValidatorId) -> bool {
744
		Validators::<T>::get()
745
			.iter()
746
			.position(|i| i == c)
747
			.map(|i| Self::disable_index(i as u32))
748
			.unwrap_or(false)
749
	}
750

            
751
	/// Upgrade the key type from some old type to a new type. Supports adding
752
	/// and removing key types.
753
	///
754
	/// This function should be used with extreme care and only during an
755
	/// `on_runtime_upgrade` block. Misuse of this function can put your blockchain
756
	/// into an unrecoverable state.
757
	///
758
	/// Care should be taken that the raw versions of the
759
	/// added keys are unique for every `ValidatorId, KeyTypeId` combination.
760
	/// This is an invariant that the session pallet typically maintains internally.
761
	///
762
	/// As the actual values of the keys are typically not known at runtime upgrade,
763
	/// it's recommended to initialize the keys to a (unique) dummy value with the expectation
764
	/// that all validators should invoke `set_keys` before those keys are actually
765
	/// required.
766
	pub fn upgrade_keys<Old, F>(upgrade: F)
767
	where
768
		Old: OpaqueKeys + Member + Decode,
769
		F: Fn(T::ValidatorId, Old) -> T::Keys,
770
	{
771
		let old_ids = Old::key_ids();
772
		let new_ids = T::Keys::key_ids();
773

            
774
		// Translate NextKeys, and key ownership relations at the same time.
775
		NextKeys::<T>::translate::<Old, _>(|val, old_keys| {
776
			// Clear all key ownership relations. Typically the overlap should
777
			// stay the same, but no guarantees by the upgrade function.
778
			for i in old_ids.iter() {
779
				Self::clear_key_owner(*i, old_keys.get_raw(*i));
780
			}
781

            
782
			let new_keys = upgrade(val.clone(), old_keys);
783

            
784
			// And now set the new ones.
785
			for i in new_ids.iter() {
786
				Self::put_key_owner(*i, new_keys.get_raw(*i), &val);
787
			}
788

            
789
			Some(new_keys)
790
		});
791

            
792
		let _ = QueuedKeys::<T>::translate::<Vec<(T::ValidatorId, Old)>, _>(|k| {
793
			k.map(|k| {
794
				k.into_iter()
795
					.map(|(val, old_keys)| (val.clone(), upgrade(val, old_keys)))
796
					.collect::<Vec<_>>()
797
			})
798
		});
799
	}
800

            
801
	/// Perform the set_key operation, checking for duplicates. Does not set `Changed`.
802
	///
803
	/// This ensures that the reference counter in system is incremented appropriately and as such
804
	/// must accept an account ID, rather than a validator ID.
805
1806
	fn do_set_keys(account: &T::AccountId, keys: T::Keys) -> DispatchResult {
806
1806
		let who = T::ValidatorIdOf::convert(account.clone())
807
1806
			.ok_or(Error::<T>::NoAssociatedValidatorId)?;
808

            
809
1806
		ensure!(frame_system::Pallet::<T>::can_inc_consumer(account), Error::<T>::NoAccount);
810
1776
		let old_keys = Self::inner_set_keys(&who, keys)?;
811
1488
		if old_keys.is_none() {
812
528
			let assertion = frame_system::Pallet::<T>::inc_consumers(account).is_ok();
813
528
			debug_assert!(assertion, "can_inc_consumer() returned true; no change since; qed");
814
960
		}
815

            
816
1488
		Ok(())
817
1806
	}
818

            
819
	/// Perform the set_key operation, checking for duplicates. Does not set `Changed`.
820
	///
821
	/// The old keys for this validator are returned, or `None` if there were none.
822
	///
823
	/// This does not ensure that the reference counter in system is incremented appropriately, it
824
	/// must be done by the caller or the keys will be leaked in storage.
825
1788
	fn inner_set_keys(
826
1788
		who: &T::ValidatorId,
827
1788
		keys: T::Keys,
828
1788
	) -> Result<Option<T::Keys>, DispatchError> {
829
1788
		let old_keys = Self::load_keys(who);
830

            
831
13116
		for id in T::Keys::key_ids() {
832
11616
			let key = keys.get_raw(*id);
833
11616

            
834
11616
			// ensure keys are without duplication.
835
11616
			ensure!(
836
11616
				Self::key_owner(*id, key).map_or(true, |owner| &owner == who),
837
288
				Error::<T>::DuplicatedKey,
838
			);
839
		}
840

            
841
12000
		for id in T::Keys::key_ids() {
842
10500
			let key = keys.get_raw(*id);
843

            
844
10500
			if let Some(old) = old_keys.as_ref().map(|k| k.get_raw(*id)) {
845
6720
				if key == old {
846
1416
					continue
847
5304
				}
848
5304

            
849
5304
				Self::clear_key_owner(*id, old);
850
3780
			}
851

            
852
9084
			Self::put_key_owner(*id, key, who);
853
		}
854

            
855
1500
		Self::put_keys(who, &keys);
856
1500
		Ok(old_keys)
857
1788
	}
858

            
859
1380
	fn do_purge_keys(account: &T::AccountId) -> DispatchResult {
860
1380
		let who = T::ValidatorIdOf::convert(account.clone())
861
1380
			// `purge_keys` may not have a controller-stash pair any more. If so then we expect the
862
1380
			// stash account to be passed in directly and convert that to a `ValidatorId` using the
863
1380
			// `TryFrom` trait if supported.
864
1380
			.or_else(|| T::ValidatorId::try_from(account.clone()).ok())
865
1380
			.ok_or(Error::<T>::NoAssociatedValidatorId)?;
866

            
867
1380
		let old_keys = Self::take_keys(&who).ok_or(Error::<T>::NoKeys)?;
868
6000
		for id in T::Keys::key_ids() {
869
5250
			let key_data = old_keys.get_raw(*id);
870
5250
			Self::clear_key_owner(*id, key_data);
871
5250
		}
872
750
		frame_system::Pallet::<T>::dec_consumers(account);
873
750

            
874
750
		Ok(())
875
1380
	}
876

            
877
1788
	fn load_keys(v: &T::ValidatorId) -> Option<T::Keys> {
878
1788
		NextKeys::<T>::get(v)
879
1788
	}
880

            
881
1380
	fn take_keys(v: &T::ValidatorId) -> Option<T::Keys> {
882
1380
		NextKeys::<T>::take(v)
883
1380
	}
884

            
885
1500
	fn put_keys(v: &T::ValidatorId, keys: &T::Keys) {
886
1500
		NextKeys::<T>::insert(v, keys);
887
1500
	}
888

            
889
	/// Query the owner of a session key by returning the owner's validator ID.
890
11616
	pub fn key_owner(id: KeyTypeId, key_data: &[u8]) -> Option<T::ValidatorId> {
891
11616
		KeyOwner::<T>::get((id, key_data))
892
11616
	}
893

            
894
9084
	fn put_key_owner(id: KeyTypeId, key_data: &[u8], v: &T::ValidatorId) {
895
9084
		KeyOwner::<T>::insert((id, key_data), v)
896
9084
	}
897

            
898
10554
	fn clear_key_owner(id: KeyTypeId, key_data: &[u8]) {
899
10554
		KeyOwner::<T>::remove((id, key_data));
900
10554
	}
901
}
902

            
903
impl<T: Config> ValidatorRegistration<T::ValidatorId> for Pallet<T> {
904
	fn is_registered(id: &T::ValidatorId) -> bool {
905
		Self::load_keys(id).is_some()
906
	}
907
}
908

            
909
impl<T: Config> ValidatorSet<T::AccountId> for Pallet<T> {
910
	type ValidatorId = T::ValidatorId;
911
	type ValidatorIdOf = T::ValidatorIdOf;
912

            
913
	fn session_index() -> sp_staking::SessionIndex {
914
		CurrentIndex::<T>::get()
915
	}
916

            
917
	fn validators() -> Vec<Self::ValidatorId> {
918
		Validators::<T>::get()
919
	}
920
}
921

            
922
impl<T: Config> EstimateNextNewSession<BlockNumberFor<T>> for Pallet<T> {
923
	fn average_session_length() -> BlockNumberFor<T> {
924
		T::NextSessionRotation::average_session_length()
925
	}
926

            
927
	/// This session pallet always calls new_session and next_session at the same time, hence we
928
	/// do a simple proxy and pass the function to next rotation.
929
	fn estimate_next_new_session(now: BlockNumberFor<T>) -> (Option<BlockNumberFor<T>>, Weight) {
930
		T::NextSessionRotation::estimate_next_session_rotation(now)
931
	}
932
}
933

            
934
impl<T: Config> frame_support::traits::DisabledValidators for Pallet<T> {
935
194763
	fn is_disabled(index: u32) -> bool {
936
194763
		DisabledValidators::<T>::get().binary_search(&index).is_ok()
937
194763
	}
938

            
939
194763
	fn disabled_validators() -> Vec<u32> {
940
194763
		DisabledValidators::<T>::get()
941
194763
	}
942
}
943

            
944
/// Wraps the author-scraping logic for consensus engines that can recover
945
/// the canonical index of an author. This then transforms it into the
946
/// registering account-ID of that session key index.
947
pub struct FindAccountFromAuthorIndex<T, Inner>(core::marker::PhantomData<(T, Inner)>);
948

            
949
impl<T: Config, Inner: FindAuthor<u32>> FindAuthor<T::ValidatorId>
950
	for FindAccountFromAuthorIndex<T, Inner>
951
{
952
194763
	fn find_author<'a, I>(digests: I) -> Option<T::ValidatorId>
953
194763
	where
954
194763
		I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
955
194763
	{
956
194763
		let i = Inner::find_author(digests)?;
957

            
958
194763
		let validators = Validators::<T>::get();
959
194763
		validators.get(i as usize).cloned()
960
194763
	}
961
}