1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Cumulus.
3

            
4
// Cumulus is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Cumulus is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Cumulus timestamp related primitives.
18
//!
19
//! Provides a [`InherentDataProvider`] that should be used in the validation phase of the
20
//! parachain. It will be used to create the inherent data and that will be used to check the
21
//! inherents inside the parachain block (in this case the timestamp inherent). As we don't have
22
//! access to any clock from the runtime the timestamp is always passed as an inherent into the
23
//! runtime. To check this inherent when validating the block, we will use the relay chain slot. As
24
//! the relay chain slot is derived from a timestamp, we can easily convert it back to a timestamp
25
//! by multiplying it with the slot duration. By comparing the relay chain slot derived timestamp
26
//! with the timestamp we can ensure that the parachain timestamp is reasonable.
27

            
28
#![cfg_attr(not(feature = "std"), no_std)]
29

            
30
use core::time::Duration;
31
use cumulus_primitives_core::relay_chain::Slot;
32
use sp_inherents::{Error, InherentData};
33

            
34
pub use sp_timestamp::{InherentType, INHERENT_IDENTIFIER};
35

            
36
/// The inherent data provider for the timestamp.
37
///
38
/// This should be used in the runtime when checking the inherents in the validation phase of the
39
/// parachain.
40
pub struct InherentDataProvider {
41
	relay_chain_slot: Slot,
42
	relay_chain_slot_duration: Duration,
43
}
44

            
45
impl InherentDataProvider {
46
	/// Create `Self` from the given relay chain slot and slot duration.
47
	pub fn from_relay_chain_slot_and_duration(
48
		relay_chain_slot: Slot,
49
		relay_chain_slot_duration: Duration,
50
	) -> Self {
51
		Self { relay_chain_slot, relay_chain_slot_duration }
52
	}
53

            
54
	/// Create the inherent data.
55
	pub fn create_inherent_data(&self) -> Result<InherentData, Error> {
56
		let mut inherent_data = InherentData::new();
57
		self.provide_inherent_data(&mut inherent_data).map(|_| inherent_data)
58
	}
59

            
60
	/// Provide the inherent data into the given `inherent_data`.
61
	pub fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), Error> {
62
		// As the parachain starts building at around `relay_chain_slot + 1` we use that slot to
63
		// calculate the timestamp.
64
		let data: InherentType = ((*self.relay_chain_slot + 1) *
65
			self.relay_chain_slot_duration.as_millis() as u64)
66
			.into();
67

            
68
		inherent_data.put_data(INHERENT_IDENTIFIER, &data)
69
	}
70
}