Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental: Strongly typed types of time #1907

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion libs/mocks/src/pools.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#[frame_support::pallet(dev_mode)]
pub mod pallet {
use cfg_primitives::Seconds;
use cfg_traits::{
investments::InvestmentAccountant, PoolInspect, PoolReserve, Seconds, TrancheTokenPrice,
investments::InvestmentAccountant, PoolInspect, PoolReserve, TrancheTokenPrice,
};
use cfg_types::investments::InvestmentInfo;
use frame_support::pallet_prelude::*;
Expand Down
5 changes: 3 additions & 2 deletions libs/mocks/src/time.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[frame_support::pallet(dev_mode)]
pub mod pallet {
use cfg_traits::time::TimeUnit;
use frame_support::{pallet_prelude::*, traits::Time};
use mock_builder::{execute_call, register_call};
use sp_runtime::traits::AtLeast32Bit;
Expand Down Expand Up @@ -31,10 +32,10 @@ pub mod pallet {

impl<T: Config> frame_support::traits::UnixTime for Pallet<T>
where
T::Moment: Into<u64>,
<T as Config>::Moment: TimeUnit,
{
fn now() -> std::time::Duration {
core::time::Duration::from_millis(<Pallet<T> as Time>::now().into())
core::time::Duration::from_millis(<Self as Time>::now().as_millis().into())
}
}
}
4 changes: 4 additions & 0 deletions libs/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }
cfg-utils = { workspace = true }

# substrate frame dependencies
frame-support = { workspace = true }
Expand Down Expand Up @@ -57,6 +58,7 @@ std = [
"sp-std/std",
"staging-xcm-executor/std",
"staging-xcm/std",
"cfg-utils/std",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
Expand All @@ -65,11 +67,13 @@ runtime-benchmarks = [
"pallet-membership/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"staging-xcm-executor/runtime-benchmarks",
"cfg-utils/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-collective/try-runtime",
"pallet-membership/try-runtime",
"sp-runtime/try-runtime",
"cfg-utils/try-runtime",
]
35 changes: 22 additions & 13 deletions libs/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,23 @@ pub mod types {

/// The type for LP gateway session IDs.
pub type LPGatewaySessionId = u64;

/// The type to represent milliseconds
pub type Millis = cfg_utils::time::Millis<u64>;

/// The type to represent seconds
pub type Seconds = cfg_utils::time::Seconds<u64>;

/// The type to represent days
pub type Days = cfg_utils::time::Days<u32>;
}

/// Common constants for all runtimes
pub mod constants {
use frame_support::weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight};
use sp_runtime::Perbill;

use super::types::{Balance, BlockNumber};
use super::types::{Balance, BlockNumber, Millis, Seconds};

/// This determines the average expected block time that we are targeting.
/// Blocks will be produced at a minimum duration defined by
Expand All @@ -180,24 +189,24 @@ pub mod constants {
/// slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLISECS_PER_BLOCK: u64 = 12000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
pub const MILLISECS_PER_BLOCK: Millis = Millis::new(12000);
pub const SLOT_DURATION: Millis = MILLISECS_PER_BLOCK;

// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK.inner as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;

/// Milliseconds per day
pub const MILLISECS_PER_DAY: u64 = SECONDS_PER_DAY * 1000;

// Seconds units
pub const SECONDS_PER_MINUTE: u64 = 60;
pub const SECONDS_PER_HOUR: u64 = SECONDS_PER_MINUTE * 60;
pub const SECONDS_PER_DAY: u64 = SECONDS_PER_HOUR * 24;
pub const SECONDS_PER_WEEK: u64 = SECONDS_PER_DAY * 7;
pub const SECONDS_PER_MONTH: u64 = SECONDS_PER_DAY * 30;
pub const SECONDS_PER_YEAR: u64 = SECONDS_PER_DAY * 365;
pub const SECONDS_PER_MINUTE: Seconds = Seconds::new(60);
pub const SECONDS_PER_HOUR: Seconds = SECONDS_PER_MINUTE.mul_int(60);
pub const SECONDS_PER_DAY: Seconds = SECONDS_PER_HOUR.mul_int(24);
pub const SECONDS_PER_WEEK: Seconds = SECONDS_PER_DAY.mul_int(7);
pub const SECONDS_PER_MONTH: Seconds = SECONDS_PER_DAY.mul_int(30);
pub const SECONDS_PER_YEAR: Seconds = SECONDS_PER_DAY.mul_int(365);

/// Milliseconds per day
pub const MILLISECS_PER_DAY: Millis = Millis::new(SECONDS_PER_DAY.inner * 1000);

/// We assume that ~5% of the block weight is consumed by `on_initialize`
/// handlers. This is used to limit the maximal weight of a single
Expand Down
5 changes: 3 additions & 2 deletions libs/test-utils/src/mocks/nav.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
use cfg_traits::{PoolNAV, Seconds};
use cfg_primitives::Seconds;
use cfg_traits::PoolNAV;
use frame_support::pallet_prelude::*;
use parity_scale_codec::HasCompact;
use sp_runtime::traits::{AtLeast32BitUnsigned, Zero};
Expand Down Expand Up @@ -53,7 +54,7 @@ pub mod pallet {
}

pub fn latest(pool_id: T::PoolId) -> (T::Balance, Seconds) {
Nav::<T>::get(pool_id).unwrap_or((T::Balance::zero(), 0))
Nav::<T>::get(pool_id).unwrap_or((T::Balance::zero(), Seconds::zero()))
}
}

Expand Down
4 changes: 1 addition & 3 deletions libs/traits/src/interest.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cfg_primitives::SECONDS_PER_YEAR;
use cfg_primitives::{Seconds, SECONDS_PER_YEAR};
use frame_support::{
dispatch::DispatchResult,
pallet_prelude::{RuntimeDebug, TypeInfo},
Expand All @@ -14,8 +14,6 @@ use sp_runtime::{
DispatchError,
};

use crate::Seconds;

#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeDebug, MaxEncodedLen)]
pub enum CompoundingSchedule {
/// Interest compounds every second
Expand Down
34 changes: 3 additions & 31 deletions libs/traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
// Ensure we're `no_std` when compiling for WebAssembly.
#![cfg_attr(not(feature = "std"), no_std)]

use cfg_primitives::Seconds;
use frame_support::{
dispatch::DispatchResult,
pallet_prelude::{RuntimeDebug, TypeInfo},
traits::UnixTime,
Parameter,
};
use impl_trait_for_tuples::impl_for_tuples;
Expand All @@ -40,6 +40,7 @@ pub mod investments;
pub mod liquidity_pools;
pub mod rewards;
pub mod swaps;
pub mod time;

#[cfg(feature = "runtime-benchmarks")]
/// Traits related to benchmarking tooling.
Expand All @@ -50,7 +51,7 @@ pub trait PoolNAV<PoolId, Amount> {
type ClassId;
type RuntimeOrigin;
// nav returns the nav and the last time it was calculated
fn nav(pool_id: PoolId) -> Option<(Amount, u64)>;
fn nav(pool_id: PoolId) -> Option<(Amount, Seconds)>;
fn update_nav(pool_id: PoolId) -> Result<Amount, DispatchError>;
fn initialise(
origin: Self::RuntimeOrigin,
Expand Down Expand Up @@ -370,35 +371,6 @@ pub trait TryConvert<A, B> {
fn try_convert(a: A) -> Result<B, Self::Error>;
}

// TODO: Probably these should be in a future cfg-utils.
// Issue: https://github.com/centrifuge/centrifuge-chain/issues/1380

/// Type to represent milliseconds
pub type Millis = u64;

/// Type to represent seconds
pub type Seconds = u64;

/// Trait to obtain the time as seconds
pub trait TimeAsSecs: UnixTime {
fn now() -> Seconds {
<Self as UnixTime>::now().as_secs()
}
}

impl<T: UnixTime> TimeAsSecs for T {}

/// Trait to convert into seconds
pub trait IntoSeconds {
fn into_seconds(self) -> Seconds;
}

impl IntoSeconds for Millis {
fn into_seconds(self) -> Seconds {
self / 1000
}
}

pub trait ValueProvider<Source, Key> {
type Value;

Expand Down
66 changes: 66 additions & 0 deletions libs/traits/src/time.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use cfg_primitives::{Days, Millis, Seconds};
use frame_support::traits::UnixTime;

/// Trait to obtain the unix time as seconds
pub trait UnixTimeSecs: UnixTime {
fn now() -> Seconds {
Seconds::from(<Self as UnixTime>::now().as_secs())
}

/// Same as now(), shortcut for cases where `now()` conflicts with
/// `UnixTime::now()`
fn now_secs() -> Seconds {
<Self as UnixTimeSecs>::now()
}
}

impl<T: UnixTime> UnixTimeSecs for T {}

/// Trait to handle an unknown time unit type
pub trait TimeUnit {
fn as_millis(self) -> Millis;
fn as_seconds(self) -> Seconds;
fn as_days(self) -> Days;
}

impl TimeUnit for Millis {
fn as_millis(self) -> Millis {
self
}

fn as_seconds(self) -> Seconds {
self.into_seconds()
}

fn as_days(self) -> Days {
self.into_days()
}
}

impl TimeUnit for Seconds {
fn as_millis(self) -> Millis {
self.into_millis()
}

fn as_seconds(self) -> Seconds {
self
}

fn as_days(self) -> Days {
self.into_days()
}
}

impl TimeUnit for Days {
fn as_millis(self) -> Millis {
self.into_millis()
}

fn as_seconds(self) -> Seconds {
self.into_seconds()
}

fn as_days(self) -> Days {
self
}
}
2 changes: 1 addition & 1 deletion libs/types/src/epoch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

use cfg_traits::Seconds;
use cfg_primitives::Seconds;
use frame_support::pallet_prelude::RuntimeDebug;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
Expand Down
Loading