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