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,