referrerpolicy=no-referrer-when-downgrade

sp_consensus_slots/
lib.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//! Primitives for slots-based consensus engines.
19
20#![cfg_attr(not(feature = "std"), no_std)]
21
22use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
23use scale_info::TypeInfo;
24use sp_timestamp::Timestamp;
25
26/// Unit type wrapper that represents a slot.
27#[derive(
28	Debug,
29	Encode,
30	MaxEncodedLen,
31	Decode,
32	DecodeWithMemTracking,
33	Eq,
34	Clone,
35	Copy,
36	Default,
37	Ord,
38	Hash,
39	TypeInfo,
40)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
42#[repr(transparent)]
43pub struct Slot(u64);
44
45impl core::ops::Deref for Slot {
46	type Target = u64;
47
48	fn deref(&self) -> &u64 {
49		&self.0
50	}
51}
52
53impl core::ops::Add for Slot {
54	type Output = Self;
55
56	fn add(self, other: Self) -> Self {
57		Self(self.0 + other.0)
58	}
59}
60
61impl core::ops::Sub for Slot {
62	type Output = Self;
63
64	fn sub(self, other: Self) -> Self {
65		Self(self.0 - other.0)
66	}
67}
68
69impl core::ops::AddAssign for Slot {
70	fn add_assign(&mut self, rhs: Self) {
71		self.0 += rhs.0
72	}
73}
74
75impl core::ops::SubAssign for Slot {
76	fn sub_assign(&mut self, rhs: Self) {
77		self.0 -= rhs.0
78	}
79}
80
81impl core::ops::Add<u64> for Slot {
82	type Output = Self;
83
84	fn add(self, other: u64) -> Self {
85		Self(self.0 + other)
86	}
87}
88
89impl<T: Into<u64> + Copy> core::cmp::PartialEq<T> for Slot {
90	fn eq(&self, eq: &T) -> bool {
91		self.0 == (*eq).into()
92	}
93}
94
95impl<T: Into<u64> + Copy> core::cmp::PartialOrd<T> for Slot {
96	fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
97		self.0.partial_cmp(&(*other).into())
98	}
99}
100
101impl Slot {
102	/// Create a new slot by calculating it from the given timestamp and slot duration.
103	pub const fn from_timestamp(timestamp: Timestamp, slot_duration: SlotDuration) -> Self {
104		Slot(timestamp.as_millis() / slot_duration.as_millis())
105	}
106
107	/// Timestamp of the start of the slot.
108	///
109	/// Returns `None` if would overflow for given `SlotDuration`.
110	pub fn timestamp(&self, slot_duration: SlotDuration) -> Option<Timestamp> {
111		slot_duration.as_millis().checked_mul(self.0).map(Timestamp::new)
112	}
113
114	/// Saturating addition.
115	pub fn saturating_add<T: Into<u64>>(self, rhs: T) -> Self {
116		Self(self.0.saturating_add(rhs.into()))
117	}
118
119	/// Saturating subtraction.
120	pub fn saturating_sub<T: Into<u64>>(self, rhs: T) -> Self {
121		Self(self.0.saturating_sub(rhs.into()))
122	}
123}
124
125#[cfg(feature = "std")]
126impl std::fmt::Display for Slot {
127	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128		write!(f, "{}", self.0)
129	}
130}
131
132impl From<u64> for Slot {
133	fn from(slot: u64) -> Slot {
134		Slot(slot)
135	}
136}
137
138impl From<Slot> for u64 {
139	fn from(slot: Slot) -> u64 {
140		slot.0
141	}
142}
143
144/// A slot duration defined in milliseconds.
145#[derive(
146	Clone,
147	Copy,
148	Debug,
149	Encode,
150	Decode,
151	MaxEncodedLen,
152	Hash,
153	PartialOrd,
154	Ord,
155	PartialEq,
156	Eq,
157	TypeInfo,
158)]
159#[repr(transparent)]
160pub struct SlotDuration(u64);
161
162impl SlotDuration {
163	/// Initialize from the given milliseconds.
164	pub const fn from_millis(millis: u64) -> Self {
165		Self(millis)
166	}
167}
168
169impl SlotDuration {
170	/// Returns `self` as a `u64` representing the duration in milliseconds.
171	pub const fn as_millis(&self) -> u64 {
172		self.0
173	}
174}
175
176#[cfg(feature = "std")]
177impl SlotDuration {
178	/// Returns `self` as [`core::time::Duration`].
179	pub const fn as_duration(&self) -> core::time::Duration {
180		core::time::Duration::from_millis(self.0)
181	}
182}
183
184/// Represents an equivocation proof. An equivocation happens when a validator
185/// produces more than one block on the same slot. The proof of equivocation
186/// are the given distinct headers that were signed by the validator and which
187/// include the slot number.
188#[derive(Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, TypeInfo, Eq)]
189pub struct EquivocationProof<Header, Id> {
190	/// Returns the authority id of the equivocator.
191	pub offender: Id,
192	/// The slot at which the equivocation happened.
193	pub slot: Slot,
194	/// The first header involved in the equivocation.
195	pub first_header: Header,
196	/// The second header involved in the equivocation.
197	pub second_header: Header,
198}