// 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 .
//! Authorship tracking for SRML runtimes.
//!
//! This tracks the current author of the block and recent uncles.
#![cfg_attr(not(feature = "std"), no_std)]
use rstd::{result, prelude::*};
use rstd::collections::btree_set::BTreeSet;
use srml_support::{decl_module, decl_storage, for_each_tuple, StorageValue};
use srml_support::traits::{FindAuthor, VerifySeal, Get};
use srml_support::dispatch::Result as DispatchResult;
use codec::{Encode, Decode};
use system::ensure_none;
use sr_primitives::traits::{SimpleArithmetic, Header as HeaderT, One, Zero};
use sr_primitives::weights::SimpleDispatchInfo;
use inherents::{
RuntimeString, InherentIdentifier, ProvideInherent,
InherentData, MakeFatalError,
};
/// The identifier for the `uncles` inherent.
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"uncles00";
/// Auxiliary trait to extract uncles inherent data.
pub trait UnclesInherentData {
/// Get uncles.
fn uncles(&self) -> Result, RuntimeString>;
}
impl UnclesInherentData for InherentData {
fn uncles(&self) -> Result, RuntimeString> {
Ok(self.get_data(&INHERENT_IDENTIFIER)?.unwrap_or_default())
}
}
/// Provider for inherent data.
#[cfg(feature = "std")]
pub struct InherentDataProvider {
inner: F,
_marker: std::marker::PhantomData,
}
#[cfg(feature = "std")]
impl InherentDataProvider {
pub fn new(uncles_oracle: F) -> Self {
InherentDataProvider { inner: uncles_oracle, _marker: Default::default() }
}
}
#[cfg(feature = "std")]
impl inherents::ProvideInherentData for InherentDataProvider
where F: Fn() -> Vec
{
fn inherent_identifier(&self) -> &'static InherentIdentifier {
&INHERENT_IDENTIFIER
}
fn provide_inherent_data(&self, inherent_data: &mut InherentData) -> Result<(), RuntimeString> {
let uncles = (self.inner)();
if !uncles.is_empty() {
inherent_data.put_data(INHERENT_IDENTIFIER, &uncles)
} else {
Ok(())
}
}
fn error_to_string(&self, _error: &[u8]) -> Option {
Some(format!("no further information"))
}
}
pub trait Trait: system::Trait {
/// Find the author of a block.
type FindAuthor: FindAuthor;
/// The number of blocks back we should accept uncles.
/// This means that we will deal with uncle-parents that are
/// `UncleGenerations + 1` before `now`.
type UncleGenerations: Get;
/// A filter for uncles within a block. This is for implementing
/// further constraints on what uncles can be included, other than their ancestry.
///
/// For PoW, as long as the seals are checked, there is no need to use anything
/// but the `VerifySeal` implementation as the filter. This is because the cost of making many equivocating
/// uncles is high.
///
/// For PoS, there is no such limitation, so a further constraint must be imposed
/// beyond a seal check in order to prevent an arbitrary number of
/// equivocating uncles from being included.
///
/// The `OnePerAuthorPerHeight` filter is good for many slot-based PoS
/// engines.
type FilterUncle: FilterUncle;
/// An event handler for authored blocks.
type EventHandler: EventHandler;
}
/// An event handler for the authorship module. There is a dummy implementation
/// for `()`, which does nothing.
pub trait EventHandler {
/// Note that the given account ID is the author of the current block.
fn note_author(author: Author);
/// Note that the given account ID authored the given uncle, and how many
/// blocks older than the current block it is (age >= 0, so siblings are allowed)
fn note_uncle(author: Author, age: BlockNumber);
}
macro_rules! impl_event_handler {
() => (
impl EventHandler for () {
fn note_author(_author: A) { }
fn note_uncle(_author: A, _age: B) { }
}
);
( $($t:ident)* ) => {
impl),*>
EventHandler for ($($t,)*)
{
fn note_author(author: Author) {
$($t::note_author(author.clone());)*
}
fn note_uncle(author: Author, age: BlockNumber) {
$($t::note_uncle(author.clone(), age.clone());)*
}
}
}
}
for_each_tuple!(impl_event_handler);
/// Additional filtering on uncles that pass preliminary ancestry checks.
///
/// This should do work such as checking seals
pub trait FilterUncle {
/// An accumulator of data about uncles included.
///
/// In practice, this is used to validate uncles against others in the same block.
type Accumulator: Default;
/// Do additional filtering on a seal-checked uncle block, with the accumulated
/// filter.
fn filter_uncle(header: &Header, acc: &mut Self::Accumulator)
-> Result