diff --git a/node/standalone/src/main.rs b/node/standalone/src/main.rs
index cce3a05ce6919..4e3d4c65fea6b 100644
--- a/node/standalone/src/main.rs
+++ b/node/standalone/src/main.rs
@@ -23,6 +23,7 @@ mod service;
mod cli;
mod command;
mod rpc;
+mod mock_timestamp;
fn main() -> sc_cli::Result<()> {
command::run()
diff --git a/node/standalone/src/mock_timestamp.rs b/node/standalone/src/mock_timestamp.rs
new file mode 100644
index 0000000000000..62e7f615a508e
--- /dev/null
+++ b/node/standalone/src/mock_timestamp.rs
@@ -0,0 +1,62 @@
+/// Provide a mock duration starting at 0 in millisecond for timestamp inherent.
+/// Each call will increment timestamp by slot_duration making Aura think time has passed.
+// Copyright 2019-2020 PureStake Inc.
+// This file is part of Moonbeam.
+
+// Moonbeam is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Moonbeam is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Moonbeam. If not, see .
+
+// This module introduces a FAKE timestamp inherent data provider which will
+// always include timestamps that are one aura-slot-duration apart from one another.
+// This allows us to use manual seal to author blocks quickly without violating
+// timestamp assumptions made by either the Aura pallet or the Timestamp pallet.
+//
+// This code was taken from https://github.com/paritytech/frontier/pull/170
+// When moonbeam updates to a Frontier version that includes that PR, we should re-evaluate
+// whether it makes sense to keep this here.
+
+use sp_inherents::{InherentData, InherentIdentifier, ProvideInherentData};
+use sp_timestamp::InherentError;
+use std::cell::RefCell;
+
+use moonbeam_runtime::MINIMUM_PERIOD;
+
+const SLOT_DURATION : u64 = MINIMUM_PERIOD * 2;
+
+/// Provide a mock duration starting at 0 in millisecond for timestamp inherent.
+/// Each call will increment timestamp by slot_duration making Aura think time has passed.
+pub struct MockTimestampInherentDataProvider;
+
+pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0";
+
+thread_local!(static TIMESTAMP: RefCell = RefCell::new(0));
+
+impl ProvideInherentData for MockTimestampInherentDataProvider {
+ fn inherent_identifier(&self) -> &'static InherentIdentifier {
+ &INHERENT_IDENTIFIER
+ }
+
+ fn provide_inherent_data(
+ &self,
+ inherent_data: &mut InherentData,
+ ) -> Result<(), sp_inherents::Error> {
+ TIMESTAMP.with(|x| {
+ *x.borrow_mut() += SLOT_DURATION;
+ inherent_data.put_data(INHERENT_IDENTIFIER, &*x.borrow())
+ })
+ }
+
+ fn error_to_string(&self, error: &[u8]) -> Option {
+ InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e))
+ }
+}
diff --git a/node/standalone/src/service.rs b/node/standalone/src/service.rs
index 68090e56352b5..316f9bc7de9ba 100644
--- a/node/standalone/src/service.rs
+++ b/node/standalone/src/service.rs
@@ -30,6 +30,7 @@ use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
use sc_finality_grandpa::{
GrandpaBlockImport, FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState,
};
+use crate::mock_timestamp::MockTimestampInherentDataProvider;
// Our native executor instance.
native_executor_instance!(
@@ -84,7 +85,7 @@ pub fn new_partial(config: &Configuration, manual_seal: bool) -> Result<
if manual_seal {
inherent_data_providers
- .register_provider(sp_timestamp::InherentDataProvider)
+ .register_provider(MockTimestampInherentDataProvider)
.map_err(Into::into)
.map_err(sp_consensus::error::Error::InherentData)?;
diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs
index 0ac7e0af3c602..9ebc87538c8e0 100644
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -100,6 +100,9 @@ pub type Hash = sp_core::H256;
/// Digest item type.
pub type DigestItem = generic::DigestItem;
+/// Minimum time between blocks.
+pub const MINIMUM_PERIOD: u64 = 3000;
+
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
@@ -193,7 +196,7 @@ parameter_types! {
// When running in standalone mode, this controls the block time.
// Block time is double the minimum period.
// https://github.com/paritytech/substrate/blob/e4803bd/frame/aura/src/lib.rs#L197-L199
- pub const MinimumPeriod: u64 = 3_000;
+ pub const MinimumPeriod: u64 = MINIMUM_PERIOD;
}
impl pallet_timestamp::Trait for Runtime {
diff --git a/tests/tests/test-block.ts b/tests/tests/test-block.ts
index a0725f15acd4a..d79b62d84c326 100644
--- a/tests/tests/test-block.ts
+++ b/tests/tests/test-block.ts
@@ -57,10 +57,11 @@ describeWithMoonbeam("Moonbeam RPC (Block)", `simple-specs.json`, (context) => {
});
it("should have valid timestamp after block production", async function () {
+ // Originally ,this test required the timestamp be in the last finve minutes.
+ // This requirement doesn't make sense when we forge timestamps in manual seal.
const block = await context.web3.eth.getBlock("latest");
- const last5Minutes = Date.now() / 1000 - 300;
const next5Minutes = Date.now() / 1000 + 300;
- expect(block.timestamp).to.be.least(last5Minutes);
+ expect(block.timestamp).to.be.least(0);
expect(block.timestamp).to.be.below(next5Minutes);
});
@@ -81,7 +82,7 @@ describeWithMoonbeam("Moonbeam RPC (Block)", `simple-specs.json`, (context) => {
//parentHash: "0x04540257811b46d103d9896e7807040e7de5080e285841c5430d1a81588a0ce4",
receiptsRoot: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
sha3Uncles: "0x0000000000000000000000000000000000000000000000000000000000000000",
- size: 539,
+ size: 535,
stateRoot: "0x0000000000000000000000000000000000000000000000000000000000000000",
//timestamp: 1595012243836,
totalDifficulty: null,