Files
pezkuwi-subxt/substrate/primitives/timestamp/src/lib.rs
T
Bastian Köcher 2675741a09 Rework inherent data client side (#8526)
* Lol

* Yeah

* Moare

* adaasda

* Convert AURA to new pallet macro

* AURA: Switch to `CurrentSlot` instead of `LastTimestamp`

This switches AURA to use `CurrentSlot` instead of `LastTimestamp`.

* Add missing file

* Update frame/aura/src/migrations.rs

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

* Remove the runtime side provide inherent code

* Use correct weight

* Add TODO

* Remove the Inherent from AURA

* 🤦

* Remove unused stuff

* Update primitives authorship

* Fix babe inherent data provider

* Fix consensus-uncles

* Fix BABE

* Do some further changes to authorship primitives... :D

* More work

* Make it compile the happy path

* Make it async!

* Take hash

* More stuff

* Hacks

* Revert "Hacks"

This reverts commit cfffad88668cfdebf632a59c4fbfada001ef8251.

* Fix

* Make `execute_block` return the final block header

* Move Aura digest stuff

* Make it possible to disable equivocation checking

* Fix fix fix

* Some refactorings

* Comment

* Fixes fixes fixes

* More cleanups

* Some love

* Better love

* Make slot duration being exposed as `Duration` to the outside

* Some slot info love

* Add `build_aura_worker` utility function

* Copy copy copy

* Some stuff

* Start fixing pow

* Fix pow

* Remove some bounds

* More work

* Make grandpa work

* Make slots use `async_trait`

* Introduce `SharedData`

* Add test and fix bugs

* Switch to `SharedData`

* Make grandpa tests working

* More Babe work

* Make grandpa work

* Introduce `SharedData`

* Add test and fix bugs

* Switch to `SharedData`

* Make grandpa tests working

* More Babe work

* Make it async

* Fix fix

* Use `async_trait` in sc-consensus-slots

This makes the code a little bit easier to read and also expresses that
there can always only be one call at a time to `on_slot`.

* Make grandpa tests compile

* More Babe tests work

* Fix network test

* Start fixing service test

* Finish service-test

* Fix sc-consensus-aura

* Fix fix fix

* More fixes

* Make everything compile *yeah*

* Make manual-seal compile

* More fixes

* Start fixing Aura

* Fix Aura tests

* Fix Babe tests

* Make everything compile

* Move code around and switch to async_trait

* Fix Babe

* Docs docs docs

* Move to FRAME

* Fix fix fix

* Make everything compile

* Last cleanups

* Fix integration test

* Change slot usage of the timestamp

* We really need to switch to `impl-trait-for-tuples`

* Update primitives/inherents/src/lib.rs

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

* Update primitives/inherents/src/lib.rs

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

* Update primitives/inherents/src/lib.rs

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

* Some extra logging

* Remove dbg!

* Update primitives/consensus/common/src/import_queue/basic_queue.rs

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
2021-05-03 14:39:25 +00:00

273 lines
7.2 KiB
Rust

// This file is part of Substrate.
// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Substrate core types and inherents for timestamps.
#![cfg_attr(not(feature = "std"), no_std)]
use codec::{Encode, Decode};
use sp_inherents::{InherentIdentifier, IsFatalError, InherentData};
use sp_std::time::Duration;
/// The identifier for the `timestamp` inherent.
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"timstap0";
/// The type of the inherent.
pub type InherentType = Timestamp;
/// Unit type wrapper that represents a timestamp.
///
/// Such a timestamp is the time since the UNIX_EPOCH in milliseconds at a given point in time.
#[derive(Debug, Encode, Decode, Eq, Clone, Copy, Default, Ord)]
pub struct Timestamp(u64);
impl Timestamp {
/// Create new `Self`.
pub const fn new(inner: u64) -> Self {
Self(inner)
}
/// Returns `self` as [`Duration`].
pub fn as_duration(self) -> Duration {
Duration::from_millis(self.0)
}
/// Checked subtraction that returns `None` on an underflow.
pub fn checked_sub(self, other: Self) -> Option<Self> {
self.0.checked_sub(other.0).map(Self)
}
}
impl sp_std::ops::Deref for Timestamp {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl core::ops::Add for Timestamp {
type Output = Self;
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl core::ops::Add<u64> for Timestamp {
type Output = Self;
fn add(self, other: u64) -> Self {
Self(self.0 + other)
}
}
impl<T: Into<u64> + Copy> core::cmp::PartialEq<T> for Timestamp {
fn eq(&self, eq: &T) -> bool {
self.0 == (*eq).into()
}
}
impl<T: Into<u64> + Copy> core::cmp::PartialOrd<T> for Timestamp {
fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
self.0.partial_cmp(&(*other).into())
}
}
#[cfg(feature = "std")]
impl std::fmt::Display for Timestamp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for Timestamp {
fn from(timestamp: u64) -> Self {
Timestamp(timestamp)
}
}
impl From<Timestamp> for u64 {
fn from(timestamp: Timestamp) -> u64 {
timestamp.0
}
}
impl From<Duration> for Timestamp {
fn from(duration: Duration) -> Self {
Timestamp(duration.as_millis() as u64)
}
}
/// Errors that can occur while checking the timestamp inherent.
#[derive(Encode, sp_runtime::RuntimeDebug)]
#[cfg_attr(feature = "std", derive(Decode, thiserror::Error))]
pub enum InherentError {
/// The timestamp is valid in the future.
/// This is a non-fatal-error and will not stop checking the inherents.
#[cfg_attr(feature = "std", error("Block will be valid at {0}."))]
ValidAtTimestamp(InherentType),
/// The block timestamp is too far in the future
#[cfg_attr(feature = "std", error("The timestamp of the block is too far in the future."))]
TooFarInFuture,
}
impl IsFatalError for InherentError {
fn is_fatal_error(&self) -> bool {
match self {
InherentError::ValidAtTimestamp(_) => false,
InherentError::TooFarInFuture => true,
}
}
}
impl InherentError {
/// Try to create an instance ouf of the given identifier and data.
#[cfg(feature = "std")]
pub fn try_from(id: &InherentIdentifier, data: &[u8]) -> Option<Self> {
if id == &INHERENT_IDENTIFIER {
<InherentError as codec::Decode>::decode(&mut &data[..]).ok()
} else {
None
}
}
}
/// Auxiliary trait to extract timestamp inherent data.
pub trait TimestampInherentData {
/// Get timestamp inherent data.
fn timestamp_inherent_data(&self) -> Result<Option<InherentType>, sp_inherents::Error>;
}
impl TimestampInherentData for InherentData {
fn timestamp_inherent_data(&self) -> Result<Option<InherentType>, sp_inherents::Error> {
self.get_data(&INHERENT_IDENTIFIER)
}
}
/// The current timestamp using the system time.
///
/// This timestamp is the time since the UNIX epoch.
#[cfg(feature = "std")]
fn current_timestamp() -> std::time::Duration {
use wasm_timer::SystemTime;
let now = SystemTime::now();
now.duration_since(SystemTime::UNIX_EPOCH)
.expect("Current time is always after unix epoch; qed")
}
/// Provide duration since unix epoch in millisecond for timestamp inherent.
#[cfg(feature = "std")]
pub struct InherentDataProvider {
max_drift: InherentType,
timestamp: InherentType,
}
#[cfg(feature = "std")]
impl InherentDataProvider {
/// Create `Self` while using the system time to get the timestamp.
pub fn from_system_time() -> Self {
Self {
max_drift: std::time::Duration::from_secs(60).into(),
timestamp: current_timestamp().into(),
}
}
/// Create `Self` using the given `timestamp`.
pub fn new(timestamp: InherentType) -> Self {
Self {
max_drift: std::time::Duration::from_secs(60).into(),
timestamp,
}
}
/// With the given maximum drift.
///
/// By default the maximum drift is 60 seconds.
///
/// The maximum drift is used when checking the inherents of a runtime. If the current timestamp
/// plus the maximum drift is smaller than the timestamp in the block, the block will be rejected
/// as being too far in the future.
pub fn with_max_drift(mut self, max_drift: std::time::Duration) -> Self {
self.max_drift = max_drift.into();
self
}
/// Returns the timestamp of this inherent data provider.
pub fn timestamp(&self) -> InherentType {
self.timestamp
}
}
#[cfg(feature = "std")]
impl sp_std::ops::Deref for InherentDataProvider {
type Target = InherentType;
fn deref(&self) -> &Self::Target {
&self.timestamp
}
}
#[cfg(feature = "std")]
#[async_trait::async_trait]
impl sp_inherents::InherentDataProvider for InherentDataProvider {
fn provide_inherent_data(
&self,
inherent_data: &mut InherentData,
) -> Result<(), sp_inherents::Error> {
inherent_data.put_data(INHERENT_IDENTIFIER, &InherentType::from(self.timestamp))
}
async fn try_handle_error(
&self,
identifier: &InherentIdentifier,
error: &[u8],
) -> Option<Result<(), sp_inherents::Error>> {
if *identifier != INHERENT_IDENTIFIER {
return None
}
match InherentError::try_from(&INHERENT_IDENTIFIER, error)? {
InherentError::ValidAtTimestamp(valid) => {
let max_drift = self.max_drift;
let timestamp = self.timestamp;
// halt import until timestamp is valid.
// reject when too far ahead.
if valid > timestamp + max_drift {
return Some(Err(
sp_inherents::Error::Application(Box::from(InherentError::TooFarInFuture))
))
}
let diff = valid.checked_sub(timestamp).unwrap_or_default();
log::info!(
target: "timestamp",
"halting for block {} milliseconds in the future",
diff.0,
);
futures_timer::Delay::new(diff.as_duration()).await;
Some(Ok(()))
},
o => Some(Err(sp_inherents::Error::Application(Box::from(o)))),
}
}
}