1#![cfg_attr(not(feature = "std"), no_std)]
21
22use codec::{Decode, Encode};
23use core::time::Duration;
24use sp_inherents::{InherentData, InherentIdentifier, IsFatalError};
25
26pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0";
28
29pub type InherentType = Timestamp;
31
32#[derive(Debug, Encode, Decode, Eq, Clone, Copy, Default, Ord)]
36pub struct Timestamp(u64);
37
38impl Timestamp {
39 pub const fn new(inner: u64) -> Self {
41 Self(inner)
42 }
43
44 pub const fn as_duration(self) -> Duration {
46 Duration::from_millis(self.0)
47 }
48
49 pub const fn as_millis(&self) -> u64 {
52 self.0
53 }
54
55 pub fn checked_sub(self, other: Self) -> Option<Self> {
57 self.0.checked_sub(other.0).map(Self)
58 }
59
60 #[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
72impl core::ops::Deref for Timestamp {
73 type Target = u64;
74
75 fn deref(&self) -> &Self::Target {
76 &self.0
77 }
78}
79
80impl 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
88impl 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
96impl<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
102impl<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")]
109impl 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
115impl From<u64> for Timestamp {
116 fn from(timestamp: u64) -> Self {
117 Timestamp(timestamp)
118 }
119}
120
121impl From<Timestamp> for u64 {
122 fn from(timestamp: Timestamp) -> u64 {
123 timestamp.0
124 }
125}
126
127impl From<Duration> for Timestamp {
128 fn from(duration: Duration) -> Self {
129 Timestamp(duration.as_millis() as u64)
130 }
131}
132
133#[derive(Encode, sp_runtime::RuntimeDebug)]
135#[cfg_attr(feature = "std", derive(Decode, thiserror::Error))]
136pub enum InherentError {
137 #[cfg_attr(
139 feature = "std",
140 error("The time since the last timestamp is lower than the minimum period.")
141 )]
142 TooEarly,
143 #[cfg_attr(feature = "std", error("The timestamp of the block is too far in the future."))]
145 TooFarInFuture,
146}
147
148impl 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
157impl InherentError {
158 #[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
169pub trait TimestampInherentData {
171 fn timestamp_inherent_data(&self) -> Result<Option<InherentType>, sp_inherents::Error>;
173}
174
175impl 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#[cfg(feature = "std")]
183pub struct InherentDataProvider {
184 max_drift: InherentType,
185 timestamp: InherentType,
186}
187
188#[cfg(feature = "std")]
189impl InherentDataProvider {
190 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 pub fn new(timestamp: InherentType) -> Self {
200 Self { max_drift: std::time::Duration::from_secs(60).into(), timestamp }
201 }
202
203 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 pub fn timestamp(&self) -> InherentType {
217 self.timestamp
218 }
219}
220
221#[cfg(feature = "std")]
222impl 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]
232impl 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}