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
//! Substrate core types and inherents for timestamps.
19

            
20
#![cfg_attr(not(feature = "std"), no_std)]
21

            
22
use codec::{Decode, Encode};
23
use core::time::Duration;
24
use sp_inherents::{InherentData, InherentIdentifier, IsFatalError};
25

            
26
/// The identifier for the `timestamp` inherent.
27
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0";
28

            
29
/// The type of the inherent.
30
pub type InherentType = Timestamp;
31

            
32
/// Unit type wrapper that represents a timestamp.
33
///
34
/// Such a timestamp is the time since the UNIX_EPOCH in milliseconds at a given point in time.
35
#[derive(Debug, Encode, Decode, Eq, Clone, Copy, Default, Ord)]
36
pub struct Timestamp(u64);
37

            
38
impl Timestamp {
39
	/// Create new `Self`.
40
	pub const fn new(inner: u64) -> Self {
41
		Self(inner)
42
	}
43

            
44
	/// Returns `self` as [`Duration`].
45
	pub const fn as_duration(self) -> Duration {
46
		Duration::from_millis(self.0)
47
	}
48

            
49
	/// Returns `self` as a `u64` representing the elapsed time since the UNIX_EPOCH in
50
	/// milliseconds.
51
	pub const fn as_millis(&self) -> u64 {
52
		self.0
53
	}
54

            
55
	/// Checked subtraction that returns `None` on an underflow.
56
	pub fn checked_sub(self, other: Self) -> Option<Self> {
57
		self.0.checked_sub(other.0).map(Self)
58
	}
59

            
60
	/// The current timestamp using the system time.
61
	#[cfg(feature = "std")]
62
	pub fn current() -> Self {
63
		use std::time::SystemTime;
64

            
65
		let now = SystemTime::now();
66
		now.duration_since(SystemTime::UNIX_EPOCH)
67
			.expect("Current time is always after unix epoch; qed")
68
			.into()
69
	}
70
}
71

            
72
impl core::ops::Deref for Timestamp {
73
	type Target = u64;
74

            
75
	fn deref(&self) -> &Self::Target {
76
		&self.0
77
	}
78
}
79

            
80
impl core::ops::Add for Timestamp {
81
	type Output = Self;
82

            
83
	fn add(self, other: Self) -> Self {
84
		Self(self.0 + other.0)
85
	}
86
}
87

            
88
impl core::ops::Add<u64> for Timestamp {
89
	type Output = Self;
90

            
91
	fn add(self, other: u64) -> Self {
92
		Self(self.0 + other)
93
	}
94
}
95

            
96
impl<T: Into<u64> + Copy> core::cmp::PartialEq<T> for Timestamp {
97
	fn eq(&self, eq: &T) -> bool {
98
		self.0 == (*eq).into()
99
	}
100
}
101

            
102
impl<T: Into<u64> + Copy> core::cmp::PartialOrd<T> for Timestamp {
103
	fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
104
		self.0.partial_cmp(&(*other).into())
105
	}
106
}
107

            
108
#[cfg(feature = "std")]
109
impl std::fmt::Display for Timestamp {
110
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111
		write!(f, "{}", self.0)
112
	}
113
}
114

            
115
impl From<u64> for Timestamp {
116
	fn from(timestamp: u64) -> Self {
117
		Timestamp(timestamp)
118
	}
119
}
120

            
121
impl From<Timestamp> for u64 {
122
	fn from(timestamp: Timestamp) -> u64 {
123
		timestamp.0
124
	}
125
}
126

            
127
impl From<Duration> for Timestamp {
128
	fn from(duration: Duration) -> Self {
129
		Timestamp(duration.as_millis() as u64)
130
	}
131
}
132

            
133
/// Errors that can occur while checking the timestamp inherent.
134
#[derive(Encode, sp_runtime::RuntimeDebug)]
135
#[cfg_attr(feature = "std", derive(Decode, thiserror::Error))]
136
pub enum InherentError {
137
	/// The time between the blocks is too short.
138
	#[cfg_attr(
139
		feature = "std",
140
		error("The time since the last timestamp is lower than the minimum period.")
141
	)]
142
	TooEarly,
143
	/// The block timestamp is too far in the future.
144
	#[cfg_attr(feature = "std", error("The timestamp of the block is too far in the future."))]
145
	TooFarInFuture,
146
}
147

            
148
impl IsFatalError for InherentError {
149
	fn is_fatal_error(&self) -> bool {
150
		match self {
151
			InherentError::TooEarly => true,
152
			InherentError::TooFarInFuture => true,
153
		}
154
	}
155
}
156

            
157
impl InherentError {
158
	/// Try to create an instance ouf of the given identifier and data.
159
	#[cfg(feature = "std")]
160
	pub fn try_from(id: &InherentIdentifier, mut data: &[u8]) -> Option<Self> {
161
		if id == &INHERENT_IDENTIFIER {
162
			<InherentError as codec::Decode>::decode(&mut data).ok()
163
		} else {
164
			None
165
		}
166
	}
167
}
168

            
169
/// Auxiliary trait to extract timestamp inherent data.
170
pub trait TimestampInherentData {
171
	/// Get timestamp inherent data.
172
	fn timestamp_inherent_data(&self) -> Result<Option<InherentType>, sp_inherents::Error>;
173
}
174

            
175
impl TimestampInherentData for InherentData {
176
	fn timestamp_inherent_data(&self) -> Result<Option<InherentType>, sp_inherents::Error> {
177
		self.get_data(&INHERENT_IDENTIFIER)
178
	}
179
}
180

            
181
/// Provide duration since unix epoch in millisecond for timestamp inherent.
182
#[cfg(feature = "std")]
183
pub struct InherentDataProvider {
184
	max_drift: InherentType,
185
	timestamp: InherentType,
186
}
187

            
188
#[cfg(feature = "std")]
189
impl InherentDataProvider {
190
	/// Create `Self` while using the system time to get the timestamp.
191
	pub fn from_system_time() -> Self {
192
		Self {
193
			max_drift: std::time::Duration::from_secs(60).into(),
194
			timestamp: Timestamp::current(),
195
		}
196
	}
197

            
198
	/// Create `Self` using the given `timestamp`.
199
	pub fn new(timestamp: InherentType) -> Self {
200
		Self { max_drift: std::time::Duration::from_secs(60).into(), timestamp }
201
	}
202

            
203
	/// With the given maximum drift.
204
	///
205
	/// By default the maximum drift is 60 seconds.
206
	///
207
	/// The maximum drift is used when checking the inherents of a runtime. If the current timestamp
208
	/// plus the maximum drift is smaller than the timestamp in the block, the block will be
209
	/// rejected as being too far in the future.
210
	pub fn with_max_drift(mut self, max_drift: std::time::Duration) -> Self {
211
		self.max_drift = max_drift.into();
212
		self
213
	}
214

            
215
	/// Returns the timestamp of this inherent data provider.
216
	pub fn timestamp(&self) -> InherentType {
217
		self.timestamp
218
	}
219
}
220

            
221
#[cfg(feature = "std")]
222
impl core::ops::Deref for InherentDataProvider {
223
	type Target = InherentType;
224

            
225
	fn deref(&self) -> &Self::Target {
226
		&self.timestamp
227
	}
228
}
229

            
230
#[cfg(feature = "std")]
231
#[async_trait::async_trait]
232
impl sp_inherents::InherentDataProvider for InherentDataProvider {
233
	async fn provide_inherent_data(
234
		&self,
235
		inherent_data: &mut InherentData,
236
	) -> Result<(), sp_inherents::Error> {
237
		inherent_data.put_data(INHERENT_IDENTIFIER, &self.timestamp)
238
	}
239

            
240
	async fn try_handle_error(
241
		&self,
242
		identifier: &InherentIdentifier,
243
		error: &[u8],
244
	) -> Option<Result<(), sp_inherents::Error>> {
245
		Some(Err(sp_inherents::Error::Application(Box::from(InherentError::try_from(
246
			identifier, error,
247
		)?))))
248
	}
249
}