From 679ec035347dc052f98cf02cae41162a1bbe117d Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Tue, 5 Mar 2019 17:44:44 +0100 Subject: [PATCH 01/12] docs for timestamp module --- srml/timestamp/readme.md | 81 +++++++++++++++++++++++++++++++++++++++ srml/timestamp/src/lib.rs | 23 +++++++++++ 2 files changed, 104 insertions(+) create mode 100644 srml/timestamp/readme.md diff --git a/srml/timestamp/readme.md b/srml/timestamp/readme.md new file mode 100644 index 0000000000000..dd2dcd64c157f --- /dev/null +++ b/srml/timestamp/readme.md @@ -0,0 +1,81 @@ +# Timestamp Module + +The timestamp module provides functionality to get and set the on-chain time. + +## Overview + +The timestamp module allows the validators to set and validate a timestamp with each block. It uses timestamp data as inherent data which is provided by the block author and validated/verified by other validators. + +The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. + +## Public Interface + +### Supported origins + +* `inherent` - Used to set the timestamp for the current block + +### Types + +* `Moment` - Represents the current timestamp. Generally implemented as a `u64`. + +### Storage Items + +* `Now`: `Moment` - The current timestamp. A `u64` having the timestamps as **total seconds from the unix epoch**. +* `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. Also represented as `Moment`. +* `DidUpdate`: `bool` - Private flag to check if the timestamp was updated for the current block. + +### Public Inspection functions - Immutable (getters) + +#### get() + +Get the current time for the current block. If this function is called prior the setting the timestamp, it will return the timestamp of the previous block. + +Returns the timestamp as `Moment`. + +### Public Mutable functions (changing state) + +#### set(origin, now: T::Moment) + +Sets the current time. Extrinsic with this call should be placed at the specific position in the each block (specified by the Trait::TIMESTAMP_SET_POSITION) typically at the start of the each block. This call should be invoked exactly once per block. It will panic at the finalization phase, if this call hasn't been invoked by that time. +The timestamp should be greater than the previous one by the amount specified by `block_period`. + +##### Errors: + +* Timestamp must be updated only once in the block +* Timestamp must increment by at least between sequential blocks + +### Inherent Data + +The timestamp module manages the block timestamp using InherentData. To identify the timestamp inherent, it defines an `InherentIdentifier`. + +The timestamp module defines and implements the trait `TimestampInherentData` for `InherentData` to query the timestamp inherent using the timestamp `InherentIdentifier`. + +## Usage + +The following example show how to use the timestamp module in your custom module to query the current timestamp. + +1. Import the `timestamp` module and derive your module configuration trait with the timestamp trait. + +``` +use {timestamp}; + +pub trait Trait: timestamp::Trait { } +``` + +2. In your module call the timestamp module's get function to get the current timestamp, + +``` +let now = >::get(); +``` + +## Implementation Details + +### Module configuration trait + +The module configuration trait of the timestamp module derives from the system module and it defines the `Moment` type to represent a timestamp. + +### Other implemented traits + +As mentioned above, the timestamp module manages the block timestamp using InherentData. To use InherentData, the timestamp module implements the `ProvideInherentData` trait to store the current system time (in seconds). + +It also implements the `ProvideInherent` trait to allow the validators to set and validate the timestamp inherent. \ No newline at end of file diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index d1d1f9f54e86f..c0d77a06e898f 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -98,11 +98,16 @@ impl TimestampInherentData for InherentData { pub struct InherentDataProvider; #[cfg(feature = "std")] +/// Implementation of ProvideInherentData impl ProvideInherentData for InherentDataProvider { + /// returns the identifier (storage key) for timestamp inherent data fn inherent_identifier(&self) -> &'static InherentIdentifier { &INHERENT_IDENTIFIER } + /// provides the current system timestamp (in seconds from epoch) as timestamp inherent data + /// uses the std library's SystemTime to get the current time + /// stores the timestamp against the timestamp INHERENT_IDENTIFIER in the inherent data storage fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString> { use std::time::SystemTime; @@ -116,6 +121,7 @@ impl ProvideInherentData for InherentDataProvider { }) } + /// tries to converts the inherent error into an string fn error_to_string(&self, error: &[u8]) -> Option { InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e)) } @@ -144,6 +150,7 @@ macro_rules! impl_timestamp_set { for_each_tuple!(impl_timestamp_set); +/// the module configuration trait pub trait Trait: consensus::Trait + system::Trait { /// Type used for expressing timestamp. type Moment: Parameter + Default + SimpleArithmetic @@ -176,6 +183,7 @@ decl_module! { >::on_timestamp_set(now); } + /// checks if the timestamp was set in the current block fn on_finalise() { assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); } @@ -184,8 +192,10 @@ decl_module! { decl_storage! { trait Store for Module as Timestamp { + /// Current time for the current block. pub Now get(now) build(|_| T::Moment::sa(0)): T::Moment; + /// The minimum (and advised) period between blocks. pub BlockPeriod get(block_period) config(period): T::Moment = T::Moment::sa(5); @@ -211,17 +221,27 @@ impl Module { } } +/// extracts the timestamp inherent from inherent data +/// gets the inherent against the timestamp INHERENT_IDENTIFIER +/// tries to deserialize the timestamp inherent into the InherentType (u64) fn extract_inherent_data(data: &InherentData) -> Result { data.get_data::(&INHERENT_IDENTIFIER) .map_err(|_| RuntimeString::from("Invalid timestamp inherent data encoding."))? .ok_or_else(|| "Timestamp inherent data is not provided.".into()) } +/// Implementation of `ProvideInherent` trait for timestamp module +/// create_inherent - to set a new timestamp by the block proposer +/// check_inherent - to validate the timestamp by other validators impl ProvideInherent for Module { type Call = Call; type Error = InherentError; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + /// Creates inherent data in storage for timestamp inherent + /// Extracts timestamp inherent from the inherent data + /// Finds out the max between current timestamp and now + block period + /// Sets the new timestamp by calling the `set` dispatchable function fn create_inherent(data: &InherentData) -> Option { let data = extract_inherent_data(data).expect("Gets and decodes timestamp inherent data"); @@ -229,6 +249,9 @@ impl ProvideInherent for Module { Some(Call::set(next_time.into())) } + /// Allows other validators to validate the inherent data for timestamp + /// Checks if the timestamp is not too far in the future (current + max drift) + /// or too behind in the past (current - (now + block period)) fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { const MAX_TIMESTAMP_DRIFT: u64 = 60; From f7c424829dc0b62667ca31f52dfdf9473ac22f52 Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Mon, 11 Mar 2019 15:56:15 +0100 Subject: [PATCH 02/12] addressed review comments in timestamp module docs --- srml/timestamp/readme.md | 50 ++++++----------- srml/timestamp/src/lib.rs | 114 ++++++++++++++++++++++++++------------ 2 files changed, 97 insertions(+), 67 deletions(-) diff --git a/srml/timestamp/readme.md b/srml/timestamp/readme.md index dd2dcd64c157f..b8b1bae767260 100644 --- a/srml/timestamp/readme.md +++ b/srml/timestamp/readme.md @@ -4,45 +4,49 @@ The timestamp module provides functionality to get and set the on-chain time. ## Overview -The timestamp module allows the validators to set and validate a timestamp with each block. It uses timestamp data as inherent data which is provided by the block author and validated/verified by other validators. +The timestamp module allows the validators to set and validate a timestamp with each block. It uses timestamp data as an inherent which is provided by the block author and validated/verified by other validators. -The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. +It is expected that the timestamp is set by the validator in the beginning of each block, typically one of the first extrinsics. The timestamp can be set only once per block and must be set each block. -## Public Interface +Note, that there might be a constraint on how much time must pass before setting the new timestamp, specified by the `tim:block_period` storage entry. -### Supported origins +The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. -* `inherent` - Used to set the timestamp for the current block +## Public Interface ### Types -* `Moment` - Represents the current timestamp. Generally implemented as a `u64`. +* `Moment` - Represents the current timestamp. ### Storage Items -* `Now`: `Moment` - The current timestamp. A `u64` having the timestamps as **total seconds from the unix epoch**. -* `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. Also represented as `Moment`. -* `DidUpdate`: `bool` - Private flag to check if the timestamp was updated for the current block. +* `Now`: `Moment` - The current timestamp represented as **total seconds from the unix epoch**. +* `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. ### Public Inspection functions - Immutable (getters) #### get() -Get the current time for the current block. If this function is called prior the setting the timestamp, it will return the timestamp of the previous block. +Get the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. Returns the timestamp as `Moment`. +#### block_period() + +Get the block period for the chain. Return the block period as the `Moment` type. + ### Public Mutable functions (changing state) #### set(origin, now: T::Moment) -Sets the current time. Extrinsic with this call should be placed at the specific position in the each block (specified by the Trait::TIMESTAMP_SET_POSITION) typically at the start of the each block. This call should be invoked exactly once per block. It will panic at the finalization phase, if this call hasn't been invoked by that time. +Sets the current time. This call should be invoked exactly once per block. It will panic at the finalization phase, if this call hasn't been invoked by that time. + The timestamp should be greater than the previous one by the amount specified by `block_period`. ##### Errors: * Timestamp must be updated only once in the block -* Timestamp must increment by at least between sequential blocks +* Timestamp must increment by at least `BlockPeriod` between sequential blocks ### Inherent Data @@ -54,28 +58,10 @@ The timestamp module defines and implements the trait `TimestampInherentData` fo The following example show how to use the timestamp module in your custom module to query the current timestamp. -1. Import the `timestamp` module and derive your module configuration trait with the timestamp trait. - -``` -use {timestamp}; - -pub trait Trait: timestamp::Trait { } -``` - -2. In your module call the timestamp module's get function to get the current timestamp, +In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's get function to get the current timestamp, ``` let now = >::get(); ``` -## Implementation Details - -### Module configuration trait - -The module configuration trait of the timestamp module derives from the system module and it defines the `Moment` type to represent a timestamp. - -### Other implemented traits - -As mentioned above, the timestamp module manages the block timestamp using InherentData. To use InherentData, the timestamp module implements the `ProvideInherentData` trait to store the current system time (in seconds). - -It also implements the `ProvideInherent` trait to allow the validators to set and validate the timestamp inherent. \ No newline at end of file +Similarly, the `block_period` function can be called. \ No newline at end of file diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index c0d77a06e898f..f89cb9ea6cb6f 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -14,21 +14,73 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -//! Timestamp manager: provides means to find out the current time. -//! -//! It is expected that the timestamp is set by the validator in the -//! beginning of each block, typically one of the first extrinsics. The timestamp -//! can be set only once per block and must be set each block. -//! -//! Note, that there might be a constraint on how much time must pass -//! before setting the new timestamp, specified by the `tim:block_period` -//! storage entry. -//! -//! # Interaction with the system -//! -//! ## Finalization -//! -//! This module should be hooked up to the finalization routine. +//! # Timestamp Module +//! +//! The timestamp module provides functionality to get and set the on-chain time. +//! +//! ## Overview +//! +//! The timestamp module allows the validators to set and validate a timestamp with each block. It uses timestamp data as an inherent which is provided by the block author and validated/verified by other validators. +//! +//! It is expected that the timestamp is set by the validator in the beginning of each block, typically one of the first extrinsics. The timestamp can be set only once per block and must be set each block. +//! +//! Note, that there might be a constraint on how much time must pass before setting the new timestamp, specified by the `tim:block_period` storage entry. +//! +//! The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. +//! +//! ## Public Interface +//! +//! ### Types +//! +//! * `Moment` - Represents the current timestamp. +//! +//! ### Storage Items +//! +//! * `Now`: `Moment` - The current timestamp represented as **total seconds from the unix epoch**. +//! * `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. +//! +//! ### Public Inspection functions - Immutable (getters) +//! +//! #### get() +//! +//! Get the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. +//! +//! Returns the timestamp as `Moment`. +//! +//! #### block_period() +//! +//! Get the block period for the chain. Return the block period as the `Moment` type. +//! +//! ### Public Mutable functions (changing state) +//! +//! #### set(origin, now: T::Moment) +//! +//! Sets the current time. This call should be invoked exactly once per block. It will panic at the finalization phase, if this call hasn't been invoked by that time. +//! +//! The timestamp should be greater than the previous one by the amount specified by `block_period`. +//! +//! ##### Errors: +//! +//! * Timestamp must be updated only once in the block +//! * Timestamp must increment by at least `BlockPeriod` between sequential blocks +//! +//! ### Inherent Data +//! +//! The timestamp module manages the block timestamp using InherentData. To identify the timestamp inherent, it defines an `InherentIdentifier`. +//! +//! The timestamp module defines and implements the trait `TimestampInherentData` for `InherentData` to query the timestamp inherent using the timestamp `InherentIdentifier`. +//! +//! ## Usage +//! +//! The following example show how to use the timestamp module in your custom module to query the current timestamp. +//! +//! In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's get function to get the current timestamp, +//! +//! ``` +//! let now = >::get(); +//! ``` +//! +//! Similarly, the `block_period` function can be called. #![cfg_attr(not(feature = "std"), no_std)] @@ -98,16 +150,13 @@ impl TimestampInherentData for InherentData { pub struct InherentDataProvider; #[cfg(feature = "std")] -/// Implementation of ProvideInherentData impl ProvideInherentData for InherentDataProvider { - /// returns the identifier (storage key) for timestamp inherent data + /// Returns the identifier for timestamp in inherent data fn inherent_identifier(&self) -> &'static InherentIdentifier { &INHERENT_IDENTIFIER } - /// provides the current system timestamp (in seconds from epoch) as timestamp inherent data - /// uses the std library's SystemTime to get the current time - /// stores the timestamp against the timestamp INHERENT_IDENTIFIER in the inherent data storage + /// Provides the current system timestamp (in seconds from epoch) as timestamp inherent data fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString> { use std::time::SystemTime; @@ -121,7 +170,7 @@ impl ProvideInherentData for InherentDataProvider { }) } - /// tries to converts the inherent error into an string + /// Tries to convert the `InherentError` into a string fn error_to_string(&self, error: &[u8]) -> Option { InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e)) } @@ -150,12 +199,13 @@ macro_rules! impl_timestamp_set { for_each_tuple!(impl_timestamp_set); -/// the module configuration trait +/// The module configuration trait pub trait Trait: consensus::Trait + system::Trait { /// Type used for expressing timestamp. type Moment: Parameter + Default + SimpleArithmetic + Mul + Div; + /// Something which can be notified when the timestamp is set. Set this to `()` if not needed. type OnTimestampSet: OnTimestampSet; } @@ -164,8 +214,6 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { /// Set the current time. /// - /// Extrinsic with this call should be placed at the specific position in the each block - /// (specified by the Trait::TIMESTAMP_SET_POSITION) typically at the start of the each block. /// This call should be invoked exactly once per block. It will panic at the finalization phase, /// if this call hasn't been invoked by that time. /// @@ -183,7 +231,6 @@ decl_module! { >::on_timestamp_set(now); } - /// checks if the timestamp was set in the current block fn on_finalise() { assert!(::DidUpdate::take(), "Timestamp must be updated once in the block"); } @@ -208,7 +255,7 @@ impl Module { /// Get the current time for the current block. /// - /// NOTE: if this function is called prior the setting the timestamp, + /// NOTE: if this function is called prior to setting the timestamp, /// it will return the timestamp of the previous block. pub fn get() -> T::Moment { Self::now() @@ -221,26 +268,22 @@ impl Module { } } -/// extracts the timestamp inherent from inherent data -/// gets the inherent against the timestamp INHERENT_IDENTIFIER -/// tries to deserialize the timestamp inherent into the InherentType (u64) +/// Extracts the timestamp inherent from inherent data. fn extract_inherent_data(data: &InherentData) -> Result { data.get_data::(&INHERENT_IDENTIFIER) .map_err(|_| RuntimeString::from("Invalid timestamp inherent data encoding."))? .ok_or_else(|| "Timestamp inherent data is not provided.".into()) } -/// Implementation of `ProvideInherent` trait for timestamp module -/// create_inherent - to set a new timestamp by the block proposer -/// check_inherent - to validate the timestamp by other validators impl ProvideInherent for Module { type Call = Call; type Error = InherentError; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; /// Creates inherent data in storage for timestamp inherent + /// /// Extracts timestamp inherent from the inherent data - /// Finds out the max between current timestamp and now + block period + /// Finds out the max between current timestamp and `now + block period` /// Sets the new timestamp by calling the `set` dispatchable function fn create_inherent(data: &InherentData) -> Option { let data = extract_inherent_data(data).expect("Gets and decodes timestamp inherent data"); @@ -250,8 +293,9 @@ impl ProvideInherent for Module { } /// Allows other validators to validate the inherent data for timestamp - /// Checks if the timestamp is not too far in the future (current + max drift) - /// or too behind in the past (current - (now + block period)) + /// + /// Checks if the timestamp is not too far in the future + /// or too behind in the past fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { const MAX_TIMESTAMP_DRIFT: u64 = 60; From 1cf17db35e6b63e99b68236bec9e304bbfe512c5 Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Mon, 11 Mar 2019 16:03:45 +0100 Subject: [PATCH 03/12] fixed typos --- srml/timestamp/readme.md | 8 ++++---- srml/timestamp/src/lib.rs | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/srml/timestamp/readme.md b/srml/timestamp/readme.md index b8b1bae767260..4bf2dc4b3dffa 100644 --- a/srml/timestamp/readme.md +++ b/srml/timestamp/readme.md @@ -23,7 +23,7 @@ The timestamp module is the recommended way to query the on-chain time instead o * `Now`: `Moment` - The current timestamp represented as **total seconds from the unix epoch**. * `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. -### Public Inspection functions - Immutable (getters) +### Public Immutable functions #### get() @@ -35,7 +35,7 @@ Returns the timestamp as `Moment`. Get the block period for the chain. Return the block period as the `Moment` type. -### Public Mutable functions (changing state) +### Public Mutable functions #### set(origin, now: T::Moment) @@ -56,9 +56,9 @@ The timestamp module defines and implements the trait `TimestampInherentData` fo ## Usage -The following example show how to use the timestamp module in your custom module to query the current timestamp. +The following example shows how to use the timestamp module in your custom module to query the current timestamp. -In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's get function to get the current timestamp, +In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's `get` function to get the current timestamp, ``` let now = >::get(); diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index f89cb9ea6cb6f..9142cc975ef5b 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -39,7 +39,7 @@ //! * `Now`: `Moment` - The current timestamp represented as **total seconds from the unix epoch**. //! * `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. //! -//! ### Public Inspection functions - Immutable (getters) +//! ### Public Immutable functions //! //! #### get() //! @@ -51,7 +51,7 @@ //! //! Get the block period for the chain. Return the block period as the `Moment` type. //! -//! ### Public Mutable functions (changing state) +//! ### Public Mutable functions //! //! #### set(origin, now: T::Moment) //! @@ -72,9 +72,10 @@ //! //! ## Usage //! -//! The following example show how to use the timestamp module in your custom module to query the current timestamp. +//! The following example shows how to use the timestamp module in your custom module to query the current timestamp. //! -//! In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's get function to get the current timestamp, +//! In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, +//! call the timestamp module's `get` function to get the current timestamp, //! //! ``` //! let now = >::get(); From b695b9b677d5f62714b72b232f46e6fb6875cd3e Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Mon, 11 Mar 2019 16:10:00 +0100 Subject: [PATCH 04/12] uppercase readme file name --- srml/timestamp/{readme.md => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename srml/timestamp/{readme.md => README.md} (100%) diff --git a/srml/timestamp/readme.md b/srml/timestamp/README.md similarity index 100% rename from srml/timestamp/readme.md rename to srml/timestamp/README.md From 2f526c13d5b6ca96b7734819b0c4fb1943b6495f Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Mon, 11 Mar 2019 16:44:43 +0100 Subject: [PATCH 05/12] merge with master --- srml/timestamp/src/lib.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index 9142cc975ef5b..27512c39e7970 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2017-2018 Parity Technologies (UK) Ltd. +// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify @@ -85,17 +85,17 @@ #![cfg_attr(not(feature = "std"), no_std)] +use parity_codec::Encode; #[cfg(feature = "std")] -use parity_codec_derive::Decode; -use parity_codec_derive::Encode; +use parity_codec::Decode; +#[cfg(feature = "std")] +use inherents::ProvideInherentData; use srml_support::{StorageValue, Parameter, decl_storage, decl_module}; use srml_support::for_each_tuple; use runtime_primitives::traits::{As, SimpleArithmetic, Zero}; use system::ensure_inherent; use rstd::{result, ops::{Mul, Div}, cmp}; use inherents::{RuntimeString, InherentIdentifier, ProvideInherent, IsFatalError, InherentData}; -#[cfg(feature = "std")] -use inherents::ProvideInherentData; /// The identifier for the `timestamp` inherent. pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0"; @@ -201,7 +201,7 @@ macro_rules! impl_timestamp_set { for_each_tuple!(impl_timestamp_set); /// The module configuration trait -pub trait Trait: consensus::Trait + system::Trait { +pub trait Trait: system::Trait { /// Type used for expressing timestamp. type Moment: Parameter + Default + SimpleArithmetic + Mul @@ -240,7 +240,6 @@ decl_module! { decl_storage! { trait Store for Module as Timestamp { - /// Current time for the current block. pub Now get(now) build(|_| T::Moment::sa(0)): T::Moment; @@ -327,7 +326,7 @@ mod tests { use substrate_primitives::H256; use runtime_primitives::BuildStorage; use runtime_primitives::traits::{BlakeTwo256, IdentityLookup}; - use runtime_primitives::testing::{Digest, DigestItem, Header, UintAuthorityId}; + use runtime_primitives::testing::{Digest, DigestItem, Header}; impl_outer_origin! { pub enum Origin for Test {} @@ -348,11 +347,6 @@ mod tests { type Event = (); type Log = DigestItem; } - impl consensus::Trait for Test { - type Log = DigestItem; - type SessionKey = UintAuthorityId; - type InherentOfflineReport = (); - } impl Trait for Test { type Moment = u64; type OnTimestampSet = (); From a8c1aded976f11f80a834c6e6496467aa2d0dbbc Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Mon, 11 Mar 2019 17:23:11 +0100 Subject: [PATCH 06/12] fixed build failure --- srml/timestamp/README.md | 6 +++--- srml/timestamp/src/lib.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/srml/timestamp/README.md b/srml/timestamp/README.md index 4bf2dc4b3dffa..c0ced206dcaef 100644 --- a/srml/timestamp/README.md +++ b/srml/timestamp/README.md @@ -43,7 +43,7 @@ Sets the current time. This call should be invoked exactly once per block. It wi The timestamp should be greater than the previous one by the amount specified by `block_period`. -##### Errors: +##### Errors * Timestamp must be updated only once in the block * Timestamp must increment by at least `BlockPeriod` between sequential blocks @@ -58,9 +58,9 @@ The timestamp module defines and implements the trait `TimestampInherentData` fo The following example shows how to use the timestamp module in your custom module to query the current timestamp. -In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's `get` function to get the current timestamp, +In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's `get` function to get the current timestamp. -``` +```ignore let now = >::get(); ``` diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index 27512c39e7970..d8212a51516de 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -59,7 +59,7 @@ //! //! The timestamp should be greater than the previous one by the amount specified by `block_period`. //! -//! ##### Errors: +//! ##### Errors //! //! * Timestamp must be updated only once in the block //! * Timestamp must increment by at least `BlockPeriod` between sequential blocks @@ -75,9 +75,9 @@ //! The following example shows how to use the timestamp module in your custom module to query the current timestamp. //! //! In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, -//! call the timestamp module's `get` function to get the current timestamp, +//! call the timestamp module's `get` function to get the current timestamp. //! -//! ``` +//! ```ignore //! let now = >::get(); //! ``` //! From d3bc702d92eb859559e4fcfab6f0ba714ecf572b Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Mon, 11 Mar 2019 17:46:04 +0100 Subject: [PATCH 07/12] removed md file --- srml/timestamp/README.md | 67 ---------------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 srml/timestamp/README.md diff --git a/srml/timestamp/README.md b/srml/timestamp/README.md deleted file mode 100644 index c0ced206dcaef..0000000000000 --- a/srml/timestamp/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Timestamp Module - -The timestamp module provides functionality to get and set the on-chain time. - -## Overview - -The timestamp module allows the validators to set and validate a timestamp with each block. It uses timestamp data as an inherent which is provided by the block author and validated/verified by other validators. - -It is expected that the timestamp is set by the validator in the beginning of each block, typically one of the first extrinsics. The timestamp can be set only once per block and must be set each block. - -Note, that there might be a constraint on how much time must pass before setting the new timestamp, specified by the `tim:block_period` storage entry. - -The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. - -## Public Interface - -### Types - -* `Moment` - Represents the current timestamp. - -### Storage Items - -* `Now`: `Moment` - The current timestamp represented as **total seconds from the unix epoch**. -* `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. - -### Public Immutable functions - -#### get() - -Get the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. - -Returns the timestamp as `Moment`. - -#### block_period() - -Get the block period for the chain. Return the block period as the `Moment` type. - -### Public Mutable functions - -#### set(origin, now: T::Moment) - -Sets the current time. This call should be invoked exactly once per block. It will panic at the finalization phase, if this call hasn't been invoked by that time. - -The timestamp should be greater than the previous one by the amount specified by `block_period`. - -##### Errors - -* Timestamp must be updated only once in the block -* Timestamp must increment by at least `BlockPeriod` between sequential blocks - -### Inherent Data - -The timestamp module manages the block timestamp using InherentData. To identify the timestamp inherent, it defines an `InherentIdentifier`. - -The timestamp module defines and implements the trait `TimestampInherentData` for `InherentData` to query the timestamp inherent using the timestamp `InherentIdentifier`. - -## Usage - -The following example shows how to use the timestamp module in your custom module to query the current timestamp. - -In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, call the timestamp module's `get` function to get the current timestamp. - -```ignore -let now = >::get(); -``` - -Similarly, the `block_period` function can be called. \ No newline at end of file From ac865a8bbfeeab831798ced3b6ba9e9ffad74dba Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Tue, 12 Mar 2019 17:22:29 +0100 Subject: [PATCH 08/12] updated as per the latest template --- srml/timestamp/src/lib.rs | 59 ++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index d8212a51516de..d82ee6cf28f12 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -24,55 +24,47 @@ //! //! It is expected that the timestamp is set by the validator in the beginning of each block, typically one of the first extrinsics. The timestamp can be set only once per block and must be set each block. //! -//! Note, that there might be a constraint on how much time must pass before setting the new timestamp, specified by the `tim:block_period` storage entry. +//! Note, that there could be a constraint on how much time must pass before setting the new timestamp, specified by the `tim:block_period` storage entry. //! //! The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. //! -//! ## Public Interface +//! ## Interface //! //! ### Types //! //! * `Moment` - Represents the current timestamp. //! -//! ### Storage Items +//! ### Dispatchable functions //! -//! * `Now`: `Moment` - The current timestamp represented as **total seconds from the unix epoch**. -//! * `BlockPeriod`: `Moment` - The minimum (and advised) period between blocks. +//! * `set` - Sets the current time. //! -//! ### Public Immutable functions +//! Please refer to the [`Call`] enum and its associated functions for a detailed list of dispatchable functions. //! -//! #### get() +//! ### Public functions //! -//! Get the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. +//! * `get` - Gets the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. //! -//! Returns the timestamp as `Moment`. +//! * `block_period` - Gets the block period for the chain. //! -//! #### block_period() -//! -//! Get the block period for the chain. Return the block period as the `Moment` type. -//! -//! ### Public Mutable functions -//! -//! #### set(origin, now: T::Moment) -//! -//! Sets the current time. This call should be invoked exactly once per block. It will panic at the finalization phase, if this call hasn't been invoked by that time. -//! -//! The timestamp should be greater than the previous one by the amount specified by `block_period`. +//! ## Usage //! -//! ##### Errors +//! The following example shows how to use the timestamp module in your custom module to query the current timestamp. //! -//! * Timestamp must be updated only once in the block -//! * Timestamp must increment by at least `BlockPeriod` between sequential blocks +//! ### Prerequisites //! -//! ### Inherent Data +//! Import the `timestamp` module in your custom module. //! -//! The timestamp module manages the block timestamp using InherentData. To identify the timestamp inherent, it defines an `InherentIdentifier`. +//! ```ignore +//! use timestamp; +//! ``` //! -//! The timestamp module defines and implements the trait `TimestampInherentData` for `InherentData` to query the timestamp inherent using the timestamp `InherentIdentifier`. +//! Derive the module configuration trait from the `timestamp` trait. //! -//! ## Usage +//! ```ignore +//! pub trait Trait: timestamp::Trait {} +//! ``` //! -//! The following example shows how to use the timestamp module in your custom module to query the current timestamp. +//! ### Simple getter //! //! In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, //! call the timestamp module's `get` function to get the current timestamp. @@ -81,7 +73,15 @@ //! let now = >::get(); //! ``` //! -//! Similarly, the `block_period` function can be called. +//! ### Example from SRML +//! +//! The [`Session` module](https://github.com/paritytech/substrate/blob/master/srml/session/src/lib.rs) uses the `timestamp` module for session management. +//! +//! ## Related Modules +//! +//! * [`System`](https://crates.parity.io/srml_system/index.html) +//! * [`Session`](https://crates.parity.io/srml_session/index.html) +//! #![cfg_attr(not(feature = "std"), no_std)] @@ -219,6 +219,7 @@ decl_module! { /// if this call hasn't been invoked by that time. /// /// The timestamp should be greater than the previous one by the amount specified by `block_period`. + /// The dispatch origin for this call must be `Inherent`. fn set(origin, #[compact] now: T::Moment) { ensure_inherent(origin)?; assert!(!::DidUpdate::exists(), "Timestamp must be updated only once in the block"); From 024c0a1436d7ef688bb5d82a97925ea5b8777ec4 Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Wed, 13 Mar 2019 14:53:32 +0100 Subject: [PATCH 09/12] updated docs --- srml/timestamp/src/lib.rs | 53 ++++++++++----------------------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index d82ee6cf28f12..12a0a53361b8a 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -16,24 +16,22 @@ //! # Timestamp Module //! -//! The timestamp module provides functionality to get and set the on-chain time. +//! The timestamp module provides functionality to get and set the on-chain time. +//! To use it in your module, you need to implement the following [`Trait`]. +//! The supported dispatchable functions are documented as part of the [`Call`] enum. //! //! ## Overview //! -//! The timestamp module allows the validators to set and validate a timestamp with each block. It uses timestamp data as an inherent which is provided by the block author and validated/verified by other validators. -//! -//! It is expected that the timestamp is set by the validator in the beginning of each block, typically one of the first extrinsics. The timestamp can be set only once per block and must be set each block. -//! -//! Note, that there could be a constraint on how much time must pass before setting the new timestamp, specified by the `tim:block_period` storage entry. +//! The timestamp module allows the validators to set and validate a timestamp with each block. +//! +//! It uses inherents for timestamp data, which is provided by the block author and validated/verified by other validators. +//! The timestamp can be set only once per block and must be set each block. There could be a constraint on how much time must pass before setting the new timestamp. //! -//! The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. +//! **NOTE:** The timestamp module is the recommended way to query the on-chain time instead of using an approach based on block numbers. +//! The block numbers based time measurement can cause issues because of cummulative calculation errors and hence it should be avoided. //! //! ## Interface //! -//! ### Types -//! -//! * `Moment` - Represents the current timestamp. -//! //! ### Dispatchable functions //! //! * `set` - Sets the current time. @@ -52,28 +50,15 @@ //! //! ### Prerequisites //! -//! Import the `timestamp` module in your custom module. -//! -//! ```ignore -//! use timestamp; -//! ``` +//! Import the `timestamp` module in your custom module and derive the module configuration trait from the `timestamp` trait. //! -//! Derive the module configuration trait from the `timestamp` trait. -//! -//! ```ignore -//! pub trait Trait: timestamp::Trait {} -//! ``` -//! -//! ### Simple getter -//! -//! In your custom module, after importing the `timestamp` module and deriving your module's configuration trait with the timestamp trait, -//! call the timestamp module's `get` function to get the current timestamp. +//! ### Get current timestamp //! //! ```ignore //! let now = >::get(); //! ``` //! -//! ### Example from SRML +//! ### Example usage //! //! The [`Session` module](https://github.com/paritytech/substrate/blob/master/srml/session/src/lib.rs) uses the `timestamp` module for session management. //! @@ -152,12 +137,10 @@ pub struct InherentDataProvider; #[cfg(feature = "std")] impl ProvideInherentData for InherentDataProvider { - /// Returns the identifier for timestamp in inherent data fn inherent_identifier(&self) -> &'static InherentIdentifier { &INHERENT_IDENTIFIER } - /// Provides the current system timestamp (in seconds from epoch) as timestamp inherent data fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString> { use std::time::SystemTime; @@ -171,7 +154,6 @@ impl ProvideInherentData for InherentDataProvider { }) } - /// Tries to convert the `InherentError` into a string fn error_to_string(&self, error: &[u8]) -> Option { InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e)) } @@ -219,6 +201,7 @@ decl_module! { /// if this call hasn't been invoked by that time. /// /// The timestamp should be greater than the previous one by the amount specified by `block_period`. + /// /// The dispatch origin for this call must be `Inherent`. fn set(origin, #[compact] now: T::Moment) { ensure_inherent(origin)?; @@ -253,7 +236,6 @@ decl_storage! { } impl Module { - /// Get the current time for the current block. /// /// NOTE: if this function is called prior to setting the timestamp, @@ -281,11 +263,6 @@ impl ProvideInherent for Module { type Error = InherentError; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; - /// Creates inherent data in storage for timestamp inherent - /// - /// Extracts timestamp inherent from the inherent data - /// Finds out the max between current timestamp and `now + block period` - /// Sets the new timestamp by calling the `set` dispatchable function fn create_inherent(data: &InherentData) -> Option { let data = extract_inherent_data(data).expect("Gets and decodes timestamp inherent data"); @@ -293,10 +270,6 @@ impl ProvideInherent for Module { Some(Call::set(next_time.into())) } - /// Allows other validators to validate the inherent data for timestamp - /// - /// Checks if the timestamp is not too far in the future - /// or too behind in the past fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> { const MAX_TIMESTAMP_DRIFT: u64 = 60; From 6508415c7cbe973645f565987516ed437e8d6d8b Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Wed, 13 Mar 2019 14:59:08 +0100 Subject: [PATCH 10/12] updated docs --- srml/timestamp/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index 12a0a53361b8a..c2edf6b87d140 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -17,7 +17,7 @@ //! # Timestamp Module //! //! The timestamp module provides functionality to get and set the on-chain time. -//! To use it in your module, you need to implement the following [`Trait`]. +//! To use it in your module, you need to implement the timestamp [`Trait`]. //! The supported dispatchable functions are documented as part of the [`Call`] enum. //! //! ## Overview From aaab62cfb14e626d7cf0d52435bc5085c46bfb5a Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Thu, 14 Mar 2019 11:55:53 +0100 Subject: [PATCH 11/12] addressed review comments --- srml/timestamp/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index c2edf6b87d140..ddb8e7161e662 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -32,12 +32,10 @@ //! //! ## Interface //! -//! ### Dispatchable functions +//! ### Dispatchable functions ([`Call`]) //! //! * `set` - Sets the current time. //! -//! Please refer to the [`Call`] enum and its associated functions for a detailed list of dispatchable functions. -//! //! ### Public functions //! //! * `get` - Gets the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. @@ -251,7 +249,6 @@ impl Module { } } -/// Extracts the timestamp inherent from inherent data. fn extract_inherent_data(data: &InherentData) -> Result { data.get_data::(&INHERENT_IDENTIFIER) .map_err(|_| RuntimeString::from("Invalid timestamp inherent data encoding."))? From 843a2aac5221f261f29d3c88f7325c8bf59f361c Mon Sep 17 00:00:00 2001 From: Gautam Dhameja Date: Fri, 15 Mar 2019 11:18:09 +0100 Subject: [PATCH 12/12] addressed review comments --- srml/timestamp/src/lib.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/srml/timestamp/src/lib.rs b/srml/timestamp/src/lib.rs index ddb8e7161e662..f3e0d8153e2a0 100644 --- a/srml/timestamp/src/lib.rs +++ b/srml/timestamp/src/lib.rs @@ -36,11 +36,11 @@ //! //! * `set` - Sets the current time. //! -//! ### Public functions +//! ### Public functions ([`Module`]) //! //! * `get` - Gets the current time for the current block. If this function is called prior the setting to timestamp, it will return the timestamp of the previous block. //! -//! * `block_period` - Gets the block period for the chain. +//! * `block_period` - Gets the minimum (and advised) period between blocks for the chain. //! //! ## Usage //! @@ -53,10 +53,23 @@ //! ### Get current timestamp //! //! ```ignore -//! let now = >::get(); +//! use support::{decl_module, dispatch::Result}; +//! use system::ensure_signed; +//! +//! pub trait Trait: timestamp::Trait {} +//! +//! decl_module! { +//! pub struct Module for enum Call where origin: T::Origin { +//! pub fn get_time(origin) -> Result { +//! let _sender = ensure_signed(origin)?; +//! let _now = >::get(); +//! Ok(()) +//! } +//! } +//! } //! ``` //! -//! ### Example usage +//! ### Example from SRML //! //! The [`Session` module](https://github.com/paritytech/substrate/blob/master/srml/session/src/lib.rs) uses the `timestamp` module for session management. //!