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

Forge block timestamps in manual seal mode #76

Merged
merged 9 commits into from
Oct 29, 2020
Merged
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
1 change: 1 addition & 0 deletions node/standalone/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod service;
mod cli;
mod command;
mod rpc;
mod mock_timestamp;

fn main() -> sc_cli::Result<()> {
command::run()
Expand Down
62 changes: 62 additions & 0 deletions node/standalone/src/mock_timestamp.rs
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.

// 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<u64> = 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<String> {
InherentError::try_from(&INHERENT_IDENTIFIER, error).map(|e| format!("{:?}", e))
}
}
3 changes: 2 additions & 1 deletion node/standalone/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -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)?;

Expand Down
5 changes: 4 additions & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ pub type Hash = sp_core::H256;
/// Digest item type.
pub type DigestItem = generic::DigestItem<Hash>;

/// 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
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 4 additions & 3 deletions tests/tests/test-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

Expand All @@ -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,
Expand Down