Files
pezkuwi-subxt/substrate/srml/babe/src/lib.rs
T
DemiMarie-parity 53e8ad8728 Add runtime support for PreRuntime and Consensus digests (#2757)
* Try to fix runtime panic

Does not work

* Fix trivial typo

* Add runtime support for `PreRuntime` and `Consensus` digests

Fixes c7d1204ce5

* Fix silly compile error.

* Fix overly-long lines

Also remove some in-progress code that would not wind up being useful
anyway.

* Respond to review comments

* delete `unset RUSTC_WRAPPER` from scripts/common.sh
* delete unnecessary `use aura::AURA_ENGINE_ID` from
  `node/runtime/src/lib.rs`
* add comments explaining why `PreRuntime` and `Consensus` must be
  special-cased in `core/sr-primitives/lib.rs`
* switch to using `$crate::rstd::marker::PhantomData` in
  `impl_outer_log!`
* improve documentation of `DigestItem::Seal`

* Fix compilation and add proof that we do not panic

Also fix some warnings.

* Apply suggestions from code review

Mostly for readability

Co-Authored-By: Sergei Pepyakin <s.pepyakin@gmail.com>

* Apply suggestions from code review

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* $crate::rstd::marker::PhantomData → Default::default()

The import is still needed, as `Default::default()` can’t be used in
patterns.

* Bump `spec_version`

Also do some reformatting.
2019-06-04 15:59:47 +02:00

170 lines
5.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Consensus extension module for BABE consensus.
#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code)]
pub use timestamp;
use rstd::{result, prelude::*, marker::PhantomData};
use srml_support::{decl_storage, decl_module};
use timestamp::{OnTimestampSet, Trait};
use primitives::traits::{SaturatedConversion, Saturating};
#[cfg(feature = "std")]
use timestamp::TimestampInherentData;
use parity_codec::{Encode, Decode};
use inherents::{RuntimeString, InherentIdentifier, InherentData, ProvideInherent, MakeFatalError};
#[cfg(feature = "std")]
use inherents::{InherentDataProviders, ProvideInherentData};
#[cfg(feature = "std")]
use serde::Serialize;
/// The BABE inherent identifier.
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"babeslot";
/// The type of the BABE inherent.
pub type InherentType = u64;
/// Auxiliary trait to extract BABE inherent data.
pub trait BabeInherentData {
/// Get BABE inherent data.
fn babe_inherent_data(&self) -> result::Result<InherentType, RuntimeString>;
/// Replace BABE inherent data.
fn babe_replace_inherent_data(&mut self, new: InherentType);
}
impl BabeInherentData for InherentData {
fn babe_inherent_data(&self) -> result::Result<InherentType, RuntimeString> {
self.get_data(&INHERENT_IDENTIFIER)
.and_then(|r| r.ok_or_else(|| "BABE inherent data not found".into()))
}
fn babe_replace_inherent_data(&mut self, new: InherentType) {
self.replace_data(INHERENT_IDENTIFIER, &new);
}
}
/// Logs in this module.
pub type Log<T> = RawLog<T>;
/// Logs in this module.
///
/// The type parameter distinguishes logs belonging to two different runtimes,
/// which should not be mixed.
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
pub enum RawLog<T> {
/// BABE inherent digests
PreRuntime([u8; 4], Vec<u8>, PhantomData<T>),
}
/// Provides the slot duration inherent data for BABE.
#[cfg(feature = "std")]
pub struct InherentDataProvider {
slot_duration: u64,
}
#[cfg(feature = "std")]
impl InherentDataProvider {
pub fn new(slot_duration: u64) -> Self {
Self {
slot_duration
}
}
}
#[cfg(feature = "std")]
impl ProvideInherentData for InherentDataProvider {
fn on_register(
&self,
providers: &InherentDataProviders,
) -> result::Result<(), RuntimeString> {
if !providers.has_provider(&timestamp::INHERENT_IDENTIFIER) {
// Add the timestamp inherent data provider, as we require it.
providers.register_provider(timestamp::InherentDataProvider)
} else {
Ok(())
}
}
fn inherent_identifier(&self) -> &'static inherents::InherentIdentifier {
&INHERENT_IDENTIFIER
}
fn provide_inherent_data(
&self,
inherent_data: &mut InherentData,
) -> result::Result<(), RuntimeString> {
let timestamp = inherent_data.timestamp_inherent_data()?;
let slot_num = timestamp / self.slot_duration;
inherent_data.put_data(INHERENT_IDENTIFIER, &slot_num)
}
fn error_to_string(&self, error: &[u8]) -> Option<String> {
RuntimeString::decode(&mut &error[..]).map(Into::into)
}
}
decl_storage! {
trait Store for Module<T: Trait> as Babe {
// The last timestamp.
LastTimestamp get(last): T::Moment;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin { }
}
impl<T: Trait> Module<T> {
/// Determine the BABE slot duration based on the Timestamp module configuration.
pub fn slot_duration() -> T::Moment {
// we double the minimum block-period so each author can always propose within
// the majority of their slot.
<timestamp::Module<T>>::minimum_period().saturating_mul(2.into())
}
}
impl<T: Trait> OnTimestampSet<T::Moment> for Module<T> {
fn on_timestamp_set(_moment: T::Moment) { }
}
impl<T: Trait> ProvideInherent for Module<T> {
type Call = timestamp::Call<T>;
type Error = MakeFatalError<RuntimeString>;
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;
fn create_inherent(_: &InherentData) -> Option<Self::Call> {
None
}
fn check_inherent(call: &Self::Call, data: &InherentData) -> result::Result<(), Self::Error> {
let timestamp = match call {
timestamp::Call::set(ref timestamp) => timestamp.clone(),
_ => return Ok(()),
};
let timestamp_based_slot = (timestamp / Self::slot_duration()).saturated_into::<u64>();
let seal_slot = data.babe_inherent_data()?;
if timestamp_based_slot == seal_slot {
Ok(())
} else {
Err(RuntimeString::from("timestamp set in block doesnt match slot in seal").into())
}
}
}