frame_support/traits/validation.rs
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//! Traits for dealing with validation and validators.
19
20use crate::{dispatch::Parameter, weights::Weight};
21use alloc::{vec, vec::Vec};
22use codec::{Codec, Decode, MaxEncodedLen};
23use sp_runtime::{
24 traits::{Convert, Zero},
25 BoundToRuntimeAppPublic, ConsensusEngineId, Permill, RuntimeAppPublic,
26};
27use sp_staking::SessionIndex;
28
29/// A trait for online node inspection in a session.
30///
31/// Something that can give information about the current validator set.
32pub trait ValidatorSet<AccountId> {
33 /// Type for representing validator id in a session.
34 type ValidatorId: Parameter + MaxEncodedLen;
35 /// A type for converting `AccountId` to `ValidatorId`.
36 type ValidatorIdOf: Convert<AccountId, Option<Self::ValidatorId>>;
37
38 /// Returns current session index.
39 fn session_index() -> SessionIndex;
40
41 /// Returns the active set of validators.
42 fn validators() -> Vec<Self::ValidatorId>;
43}
44
45/// [`ValidatorSet`] combined with an identification.
46pub trait ValidatorSetWithIdentification<AccountId>: ValidatorSet<AccountId> {
47 /// Full identification of `ValidatorId`.
48 type Identification: Parameter;
49 /// A type for converting `ValidatorId` to `Identification`.
50 type IdentificationOf: Convert<Self::ValidatorId, Option<Self::Identification>>;
51}
52
53/// A trait for finding the author of a block header based on the `PreRuntime` digests contained
54/// within it.
55pub trait FindAuthor<Author> {
56 /// Find the author of a block based on the pre-runtime digests.
57 fn find_author<'a, I>(digests: I) -> Option<Author>
58 where
59 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>;
60}
61
62impl<A> FindAuthor<A> for () {
63 fn find_author<'a, I>(_: I) -> Option<A>
64 where
65 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
66 {
67 None
68 }
69}
70
71/// A trait for verifying the seal of a header and returning the author.
72pub trait VerifySeal<Header, Author> {
73 /// Verify a header and return the author, if any.
74 fn verify_seal(header: &Header) -> Result<Option<Author>, &'static str>;
75}
76
77/// A session handler for specific key type.
78pub trait OneSessionHandler<ValidatorId>: BoundToRuntimeAppPublic {
79 /// The key type expected.
80 type Key: Decode + RuntimeAppPublic;
81
82 /// The given validator set will be used for the genesis session.
83 /// It is guaranteed that the given validator set will also be used
84 /// for the second session, therefore the first call to `on_new_session`
85 /// should provide the same validator set.
86 fn on_genesis_session<'a, I: 'a>(validators: I)
87 where
88 I: Iterator<Item = (&'a ValidatorId, Self::Key)>,
89 ValidatorId: 'a;
90
91 /// Session set has changed; act appropriately. Note that this can be called
92 /// before initialization of your module.
93 ///
94 /// `changed` is true when at least one of the session keys
95 /// or the underlying economic identities/distribution behind one the
96 /// session keys has changed, false otherwise.
97 ///
98 /// The `validators` are the validators of the incoming session, and `queued_validators`
99 /// will follow.
100 fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued_validators: I)
101 where
102 I: Iterator<Item = (&'a ValidatorId, Self::Key)>,
103 ValidatorId: 'a;
104
105 /// A notification for end of the session.
106 ///
107 /// Note it is triggered before any `SessionManager::end_session` handlers,
108 /// so we can still affect the validator set.
109 fn on_before_session_ending() {}
110
111 /// A validator got disabled. Act accordingly until a new session begins.
112 fn on_disabled(_validator_index: u32);
113}
114
115/// Something that can estimate at which block the next session rotation will happen (i.e. a new
116/// session starts).
117///
118/// The accuracy of the estimates is dependent on the specific implementation, but in order to get
119/// the best estimate possible these methods should be called throughout the duration of the session
120/// (rather than calling once and storing the result).
121///
122/// This should be the same logical unit that dictates `ShouldEndSession` to the session module. No
123/// assumptions are made about the scheduling of the sessions.
124pub trait EstimateNextSessionRotation<BlockNumber> {
125 /// Return the average length of a session.
126 ///
127 /// This may or may not be accurate.
128 fn average_session_length() -> BlockNumber;
129
130 /// Return an estimate of the current session progress.
131 ///
132 /// None should be returned if the estimation fails to come to an answer.
133 fn estimate_current_session_progress(now: BlockNumber) -> (Option<Permill>, Weight);
134
135 /// Return the block number at which the next session rotation is estimated to happen.
136 ///
137 /// None should be returned if the estimation fails to come to an answer.
138 fn estimate_next_session_rotation(now: BlockNumber) -> (Option<BlockNumber>, Weight);
139}
140
141impl<BlockNumber: Zero> EstimateNextSessionRotation<BlockNumber> for () {
142 fn average_session_length() -> BlockNumber {
143 Zero::zero()
144 }
145
146 fn estimate_current_session_progress(_: BlockNumber) -> (Option<Permill>, Weight) {
147 (None, Zero::zero())
148 }
149
150 fn estimate_next_session_rotation(_: BlockNumber) -> (Option<BlockNumber>, Weight) {
151 (None, Zero::zero())
152 }
153}
154
155/// Something that can estimate at which block scheduling of the next session will happen (i.e when
156/// we will try to fetch new validators).
157///
158/// This only refers to the point when we fetch the next session details and not when we enact them
159/// (for enactment there's `EstimateNextSessionRotation`). With `pallet-session` this should be
160/// triggered whenever `SessionManager::new_session` is called.
161///
162/// For example, if we are using a staking module this would be the block when the session module
163/// would ask staking what the next validator set will be, as such this must always be implemented
164/// by the session module.
165pub trait EstimateNextNewSession<BlockNumber> {
166 /// Return the average length of a session.
167 ///
168 /// This may or may not be accurate.
169 fn average_session_length() -> BlockNumber;
170
171 /// Return the block number at which the next new session is estimated to happen.
172 ///
173 /// None should be returned if the estimation fails to come to an answer.
174 fn estimate_next_new_session(_: BlockNumber) -> (Option<BlockNumber>, Weight);
175}
176
177impl<BlockNumber: Zero> EstimateNextNewSession<BlockNumber> for () {
178 fn average_session_length() -> BlockNumber {
179 Zero::zero()
180 }
181
182 fn estimate_next_new_session(_: BlockNumber) -> (Option<BlockNumber>, Weight) {
183 (None, Zero::zero())
184 }
185}
186
187/// Something which can compute and check proofs of
188/// a historical key owner and return full identification data of that
189/// key owner.
190pub trait KeyOwnerProofSystem<Key> {
191 /// The proof of membership itself.
192 type Proof: Codec;
193 /// The full identification of a key owner and the stash account.
194 type IdentificationTuple: Codec;
195
196 /// Prove membership of a key owner in the current block-state.
197 ///
198 /// This should typically only be called off-chain, since it may be
199 /// computationally heavy.
200 ///
201 /// Returns `Some` iff the key owner referred to by the given `key` is a
202 /// member of the current set.
203 fn prove(key: Key) -> Option<Self::Proof>;
204
205 /// Check a proof of membership on-chain. Return `Some` iff the proof is
206 /// valid and recent enough to check.
207 fn check_proof(key: Key, proof: Self::Proof) -> Option<Self::IdentificationTuple>;
208}
209
210impl<Key> KeyOwnerProofSystem<Key> for () {
211 // The proof and identification tuples is any bottom type to guarantee that the methods of this
212 // implementation can never be called or return anything other than `None`.
213 type Proof = sp_core::Void;
214 type IdentificationTuple = sp_core::Void;
215
216 fn prove(_key: Key) -> Option<Self::Proof> {
217 None
218 }
219
220 fn check_proof(_key: Key, _proof: Self::Proof) -> Option<Self::IdentificationTuple> {
221 None
222 }
223}
224
225/// Trait to be used by block producing consensus engine modules to determine
226/// how late the current block is (e.g. in a slot-based proposal mechanism how
227/// many slots were skipped since the previous block).
228pub trait Lateness<N> {
229 /// Returns a generic measure of how late the current block is compared to
230 /// its parent.
231 fn lateness(&self) -> N;
232}
233
234impl<N: Zero> Lateness<N> for () {
235 fn lateness(&self) -> N {
236 Zero::zero()
237 }
238}
239
240/// Implementors of this trait provide information about whether or not some validator has
241/// been registered with them. The [Session module](../../pallet_session/index.html) is an
242/// implementor.
243pub trait ValidatorRegistration<ValidatorId> {
244 /// Returns true if the provided validator ID has been registered with the implementing runtime
245 /// module
246 fn is_registered(id: &ValidatorId) -> bool;
247}
248
249/// Trait used to check whether a given validator is currently disabled and should not be
250/// participating in consensus (e.g. because they equivocated).
251pub trait DisabledValidators {
252 /// Returns true if the given validator is disabled.
253 fn is_disabled(index: u32) -> bool;
254
255 /// Returns all disabled validators
256 fn disabled_validators() -> Vec<u32>;
257}
258
259impl DisabledValidators for () {
260 fn is_disabled(_index: u32) -> bool {
261 false
262 }
263
264 fn disabled_validators() -> Vec<u32> {
265 vec![]
266 }
267}