Unverified Commit 394f83c5 authored by Gav Wood's avatar Gav Wood Committed by GitHub
Browse files

Introduce and enforce block time (#232)

* Recompile runtime.

* Introduce and enforce block time
parent eb6a2ec3
...@@ -2531,6 +2531,7 @@ name = "substrate-telemetry" ...@@ -2531,6 +2531,7 @@ name = "substrate-telemetry"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
......
This diff is collapsed.
...@@ -221,6 +221,7 @@ mod tests { ...@@ -221,6 +221,7 @@ mod tests {
democracy: Some(Default::default()), democracy: Some(Default::default()),
parachains: Some(Default::default()), parachains: Some(Default::default()),
staking: Some(Default::default()), staking: Some(Default::default()),
timestamp: Some(Default::default()),
}; };
::client::new_in_mem(LocalDispatch::new(), genesis_config.build_storage()).unwrap() ::client::new_in_mem(LocalDispatch::new(), genesis_config.build_storage()).unwrap()
......
...@@ -136,6 +136,7 @@ impl PresetConfig { ...@@ -136,6 +136,7 @@ impl PresetConfig {
voting_period: 7 * 120 * 24, // 7 day voting period for council members. voting_period: 7 * 120 * 24, // 7 day voting period for council members.
}), }),
parachains: Some(Default::default()), parachains: Some(Default::default()),
timestamp: Some(Default::default()),
}); });
let boot_nodes = vec![ let boot_nodes = vec![
"enode://a93a29fa68d965452bf0ff8c1910f5992fe2273a72a1ee8d3a3482f68512a61974211ba32bb33f051ceb1530b8ba3527fc36224ba6b9910329025e6d9153cf50@104.211.54.233:30333".into(), "enode://a93a29fa68d965452bf0ff8c1910f5992fe2273a72a1ee8d3a3482f68512a61974211ba32bb33f051ceb1530b8ba3527fc36224ba6b9910329025e6d9153cf50@104.211.54.233:30333".into(),
...@@ -200,6 +201,7 @@ impl PresetConfig { ...@@ -200,6 +201,7 @@ impl PresetConfig {
voting_period: 20, voting_period: 20,
}), }),
parachains: Some(Default::default()), parachains: Some(Default::default()),
timestamp: Some(Default::default()),
}); });
let boot_nodes = Vec::new(); let boot_nodes = Vec::new();
PresetConfig { genesis_config, boot_nodes } PresetConfig { genesis_config, boot_nodes }
......
...@@ -213,6 +213,7 @@ impl_outer_config! { ...@@ -213,6 +213,7 @@ impl_outer_config! {
StakingConfig => staking, StakingConfig => staking,
DemocracyConfig => democracy, DemocracyConfig => democracy,
CouncilConfig => council, CouncilConfig => council,
TimestampConfig => timestamp,
ParachainsConfig => parachains, ParachainsConfig => parachains,
} }
} }
......
This diff is collapsed.
...@@ -39,13 +39,13 @@ extern crate substrate_codec as codec; ...@@ -39,13 +39,13 @@ extern crate substrate_codec as codec;
use runtime_support::{StorageValue, Parameter}; use runtime_support::{StorageValue, Parameter};
use runtime_support::dispatch::Result; use runtime_support::dispatch::Result;
use runtime_primitives::traits::{HasPublicAux, Executable, MaybeEmpty}; use runtime_primitives::traits::{HasPublicAux, Executable, MaybeEmpty, SimpleArithmetic};
pub trait Trait: HasPublicAux + system::Trait { pub trait Trait: HasPublicAux + system::Trait {
// the position of the required timestamp-set extrinsic. // the position of the required timestamp-set extrinsic.
const SET_POSITION: u32; const SET_POSITION: u32;
type Value: Parameter + Default; type Value: Parameter + Default + SimpleArithmetic;
} }
decl_module! { decl_module! {
...@@ -60,6 +60,8 @@ decl_module! { ...@@ -60,6 +60,8 @@ decl_module! {
decl_storage! { decl_storage! {
trait Store for Module<T: Trait>; trait Store for Module<T: Trait>;
pub Now get(now): b"tim:val" => required T::Value; pub Now get(now): b"tim:val" => required T::Value;
// The minimum (and advised) period between blocks.
pub BlockPeriod get(block_period): b"tim:block_period" => required T::Value;
// Did the timestamp get updated in this block? // Did the timestamp get updated in this block?
DidUpdate: b"tim:did" => default bool; DidUpdate: b"tim:did" => default bool;
...@@ -79,6 +81,10 @@ impl<T: Trait> Module<T> { ...@@ -79,6 +81,10 @@ impl<T: Trait> Module<T> {
"Timestamp extrinsic must be at position {} in the block", "Timestamp extrinsic must be at position {} in the block",
T::SET_POSITION T::SET_POSITION
); );
assert!(
now >= Self::get() + Self::block_period(),
"Timestamp but increment by at least <BlockPeriod> between sequential blocks"
);
<Self as Store>::Now::put(now); <Self as Store>::Now::put(now);
<Self as Store>::DidUpdate::put(true); <Self as Store>::DidUpdate::put(true);
Ok(()) Ok(())
...@@ -92,9 +98,18 @@ impl<T: Trait> Executable for Module<T> { ...@@ -92,9 +98,18 @@ impl<T: Trait> Executable for Module<T> {
} }
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
#[derive(Default)]
pub struct GenesisConfig<T: Trait> { pub struct GenesisConfig<T: Trait> {
pub now: T::Value, pub now: T::Value,
pub period: T::Value,
}
impl<T: Trait> Default for GenesisConfig<T> {
fn default() -> Self {
GenesisConfig {
now: T::Value::default(),
period: T::Value::default(),
}
}
} }
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
...@@ -104,7 +119,8 @@ impl<T: Trait> runtime_primitives::BuildStorage for GenesisConfig<T> ...@@ -104,7 +119,8 @@ impl<T: Trait> runtime_primitives::BuildStorage for GenesisConfig<T>
use runtime_io::twox_128; use runtime_io::twox_128;
use codec::Slicable; use codec::Slicable;
map![ map![
twox_128(<Now<T>>::key()).to_vec() => self.now.encode() twox_128(<Now<T>>::key()).to_vec() => self.now.encode(),
twox_128(<BlockPeriod<T>>::key()).to_vec() => self.period.encode()
] ]
} }
} }
...@@ -143,7 +159,7 @@ mod tests { ...@@ -143,7 +159,7 @@ mod tests {
#[test] #[test]
fn timestamp_works() { fn timestamp_works() {
let mut t = system::GenesisConfig::<Test>::default().build_storage(); let mut t = system::GenesisConfig::<Test>::default().build_storage();
t.extend(GenesisConfig::<Test> { now: 42 }.build_storage()); t.extend(GenesisConfig::<Test> { now: 42, period: 0 }.build_storage());
with_externalities(&mut t, || { with_externalities(&mut t, || {
assert_eq!(<Timestamp as Store>::Now::get(), 42); assert_eq!(<Timestamp as Store>::Now::get(), 42);
...@@ -151,4 +167,27 @@ mod tests { ...@@ -151,4 +167,27 @@ mod tests {
assert_eq!(Timestamp::now(), 69); assert_eq!(Timestamp::now(), 69);
}); });
} }
#[test]
#[should_panic(expected = "Timestamp must be updated only once in the block")]
fn double_timestamp_should_fail() {
let mut t = system::GenesisConfig::<Test>::default().build_storage();
t.extend(GenesisConfig::<Test> { now: 42, period: 5 }.build_storage());
with_externalities(&mut t, || {
assert_ok!(Timestamp::aux_dispatch(Call::set(69), &0));
let _ = Timestamp::aux_dispatch(Call::set(70), &0);
});
}
#[test]
#[should_panic(expected = "Timestamp but increment by at least <BlockPeriod> between sequential blocks")]
fn block_period_is_enforced() {
let mut t = system::GenesisConfig::<Test>::default().build_storage();
t.extend(GenesisConfig::<Test> { now: 42, period: 5 }.build_storage());
with_externalities(&mut t, || {
let _ = Timestamp::aux_dispatch(Call::set(46), &0);
});
}
} }
...@@ -7,6 +7,7 @@ description = "Telemetry utils" ...@@ -7,6 +7,7 @@ description = "Telemetry utils"
[dependencies] [dependencies]
parking_lot = "0.4" parking_lot = "0.4"
lazy_static = "1.0" lazy_static = "1.0"
log = "^0.3"
slog = "^2" slog = "^2"
slog-json = "^2" slog-json = "^2"
slog-async = "^2" slog-async = "^2"
......
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment