Crate pallet_timestamp
source ·Expand description
Made with Substrate, for Polkadot.
§Timestamp Pallet
A pallet that provides a way for consensus systems to set and check the onchain time.
§Pallet API
See the pallet
module for more information about the interfaces this pallet exposes,
including its configuration trait, dispatchables, storage items, events and errors.
§Overview
The Timestamp pallet is designed to create a consensus-based time source. This helps ensure that nodes maintain a synchronized view of time that all network participants can agree on.
It defines an acceptable range using a configurable constant to specify how much time must pass before setting the new timestamp. Validator nodes in the network must verify that the timestamp falls within this acceptable range and reject blocks that do not.
Note: The timestamp set by this pallet is the recommended way to query the onchain time instead of using block numbers alone. Measuring time with block numbers can cause cumulative calculation errors if depended upon in time critical operations and hence should generally be avoided.
§Example
To get the current time for the current block in another pallet:
use pallet_timestamp::{self as timestamp};
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
#[pallet::pallet]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: frame_system::Config + timestamp::Config {}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(0)]
pub fn get_time(origin: OriginFor<T>) -> DispatchResult {
let _sender = ensure_signed(origin)?;
let _now = timestamp::Pallet::<T>::get();
Ok(())
}
}
}
If Pallet::get
is called prior to setting the timestamp, it will return the timestamp of
the previous block.
§Low Level / Implementation Details
A timestamp is added to the chain using an inherent extrinsic that only a block author can submit. Inherents are a special type of extrinsic in Substrate chains that will always be included in a block.
To provide inherent data to the runtime, this pallet implements
ProvideInherent
. It will only create an inherent
if the Call::set
dispatchable is called, using the
inherent
macro which enables validator nodes to call
into the runtime to check that the timestamp provided is valid.
The implementation of ProvideInherent
specifies a
constant called MAX_TIMESTAMP_DRIFT_MILLIS
which is used to determine the acceptable range for
a valid timestamp. If a block author sets a timestamp to anything that is more than this
constant, a validator node will reject the block.
The pallet also ensures that a timestamp is set at the start of each block by running an
assertion in the on_finalize
runtime hook. See [frame_support::traits::Hooks
] for more
information about how hooks work.
Because inherents are applied to a block in the order they appear in the runtime
construction, the index of this pallet in
construct_runtime
must always be less than any other
pallet that depends on it.
The Config::OnTimestampSet
configuration trait can be set to another pallet we want to
notify that the timestamp has been updated, as long as it implements [OnTimestampSet
].
Examples are the Babe and Aura pallets.
This pallet also implements [Time
] and [UnixTime
] so it can be used to configure other
pallets that require these types (e.g. in Staking pallet).
§Panics
There are 3 cases where this pallet could cause the runtime to panic.
-
If no timestamp is set at the end of a block.
-
If a timestamp is set more than once per block:
#[test]
#[should_panic(expected = "Timestamp must be updated only once in the block")]
fn double_timestamp_should_fail() {
new_test_ext().execute_with(|| {
Timestamp::set_timestamp(42);
assert_ok!(Timestamp::set(RuntimeOrigin::none(), 69));
});
}
- If a timestamp is set before the
Config::MinimumPeriod
is elapsed:
#[test]
#[should_panic(
expected = "Timestamp must increment by at least <MinimumPeriod> between sequential blocks"
)]
fn block_period_minimum_enforced() {
new_test_ext().execute_with(|| {
crate::Now::<Test>::put(44);
let _ = Timestamp::set(RuntimeOrigin::none(), 46);
});
}
Re-exports§
pub use weights::WeightInfo;
pub use pallet::*;
Modules§
- The
pallet
module in each FRAME pallet hosts the most important items needed to construct this pallet. - Autogenerated weights for
pallet_timestamp