Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions demo/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,9 @@ extern crate substrate_runtime_timestamp as timestamp;
extern crate substrate_runtime_version as version;
extern crate demo_primitives;

use rstd::prelude::*;
use demo_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature};
use runtime_primitives::generic;
use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256};
use runtime_primitives::traits::{Convert, HasPublicAux, BlakeTwo256, DigestItem};
use version::RuntimeVersion;

#[cfg(any(feature = "std", test))]
Expand Down Expand Up @@ -94,9 +93,9 @@ impl system::Trait for Concrete {
type BlockNumber = BlockNumber;
type Hash = Hash;
type Hashing = BlakeTwo256;
type Digest = generic::Digest<Vec<u8>>;
type Digest = generic::Digest<Log>;
type AccountId = AccountId;
type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
type Event = Event;
}

Expand All @@ -116,6 +115,7 @@ pub type Balances = balances::Module<Concrete>;

impl consensus::Trait for Concrete {
const NOTE_OFFLINE_POSITION: u32 = 1;
type Log = Log;
type SessionKey = SessionKey;
type OnOfflineValidator = Staking;
}
Expand Down Expand Up @@ -176,6 +176,12 @@ impl_outer_event! {
}
}

impl_outer_log! {
pub enum Log for Concrete {
consensus(AuthoritiesChange => consensus::AuthoritiesChange<SessionKey> => as_authorities_change)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider just introducing trait AsAuthoritiesChange { fn as_authorities_change(self) -> Result<Vec<SessionKey>, Self> } and then manually making an impl of it here. might save quite a lot of somewhat opaque syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Substrate has an access to digest items only through DigestItem trait, which is shared among all possible runtimes (declared in primitives). Extracting as_authorities_change (and other similar conversions later) into separate conversion trait would require DiggestItem to inherit from all those traits + will make it impossible to use default implementation (which returns None right now) => all runtimes have to explicitly declare support even for those 'system' digest items, which they are not willing to support (by simply using StubDigestItem and returning None).

I'm not sure it is better - this is an additional overhead for runtimes development. From the other side, it will force runtime developers to explicitly throw away items the do not want to support. Left as is for now, but could extract if you insist.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably also could remove AuthoritiesChangeDigest trait in favor of Vec<AuthorityId>.

}
}

impl_outer_dispatch! {
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
Expand Down Expand Up @@ -206,7 +212,7 @@ impl_outer_dispatch! {
/// The address format for describing accounts.
pub type Address = balances::Address<Concrete>;
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Vec<u8>>;
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// BlockId type as expected by this runtime.
Expand Down
1 change: 1 addition & 0 deletions demo/runtime/wasm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
35 changes: 35 additions & 0 deletions substrate/runtime-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,38 @@ macro_rules! impl_outer_event {
)*
}
}

#[macro_export]
macro_rules! impl_outer_log {
($(#[$attr:meta])* pub enum $name:ident for $trait:ident { $( $module:ident($( $log_type_name:ident => $log_type:ty => $as_log:ident ),*) ),* }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like there's always parens after the $module:ident (though potentially empty). prefer no parens to empty parens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this at all, because of manual DigestItem impl

// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
$(#[$attr])*
#[allow(non_camel_case_types)]
pub enum $name {
$(
$module($module::Log<$trait>),
)*
}
$(
impl From<$module::Log<$trait>> for $name {
fn from(x: $module::Log<$trait>) -> Self {
$name::$module(x)
}
}

impl DigestItem for $name {
$(
type $log_type_name = $log_type;

fn $as_log(&self) -> Option<&$log_type> {
match *self {
$name::$module(ref item) => item.$as_log(),
}
}
)*
}
)*
}
}
2 changes: 2 additions & 0 deletions substrate/runtime/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ hex-literal = "0.1.0"
serde = { version = "1.0", default_features = false }
serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../codec", default_features = false }
substrate-codec-derive = { path = "../../codec/derive", default_features = false }
substrate-primitives = { path = "../../primitives", default_features = false }
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
substrate-runtime-io = { path = "../../runtime-io", default_features = false }
Expand All @@ -21,6 +22,7 @@ std = [
"serde/std",
"serde_derive",
"substrate-codec/std",
"substrate-codec-derive/std",
"substrate-primitives/std",
"substrate-runtime-std/std",
"substrate-runtime-io/std",
Expand Down
95 changes: 92 additions & 3 deletions substrate/runtime/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ extern crate serde;
#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate substrate_codec_derive;

extern crate substrate_runtime_io as runtime_io;
extern crate substrate_runtime_primitives as primitives;
extern crate substrate_codec as codec;
Expand All @@ -41,8 +44,9 @@ extern crate substrate_primitives;
use rstd::prelude::*;
use runtime_support::{storage, Parameter};
use runtime_support::dispatch::Result;
use runtime_support::storage::StorageValue;
use runtime_support::storage::unhashed::StorageVec;
use primitives::traits::{MaybeSerializeDebug, MaybeEmpty};
use primitives::traits::{MaybeSerializeDebug, MaybeEmpty, Executable, Member, AuthoritiesChangeDigest};
use primitives::bft::MisbehaviorReport;

#[cfg(any(feature = "std", test))]
Expand Down Expand Up @@ -71,14 +75,71 @@ impl OnOfflineValidator for () {
fn on_offline_validator(_validator_index: usize) {}
}

pub type Log<T> = RawLog<
<T as Trait>::SessionKey,
>;

/// An logs in this module.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
pub enum RawLog<SessionKey> {
/// Authorities set has been changed. Contains the new set of authorities.
AuthoritiesChange(AuthoritiesChange<SessionKey>),
}

impl<SessionKey> RawLog<SessionKey> {
/// Try to cast the log entry as AuthoritiesChange log entry.
pub fn as_authorities_change(&self) -> Option<&AuthoritiesChange<SessionKey>> {
match *self {
RawLog::AuthoritiesChange(ref item) => Some(item),
}
}
}

/// Authorities change log entry.
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
pub struct AuthoritiesChange<SessionKey> {
/// New set of authorities.
pub new_authorities: Vec<SessionKey>,
}

// Implementation for tests outside of this crate.
impl<N> From<RawLog<N>> for u64 {
fn from(log: RawLog<N>) -> u64 {
match log {
RawLog::AuthoritiesChange(_) => 1,
}
}
}

impl<SessionKey: Member> AuthoritiesChangeDigest for AuthoritiesChange<SessionKey> {
type AuthorityId = SessionKey;

fn authorities(&self) -> &[Self::AuthorityId] {
&self.new_authorities
}
}

pub trait Trait: system::Trait {
/// The allowed extrinsic position for `note_offline` inherent.
const NOTE_OFFLINE_POSITION: u32;

/// Type for all log entries of this module.
type Log: From<Log<Self>> + Into<system::DigestItemOf<Self>>;

type SessionKey: Parameter + Default + MaybeSerializeDebug;
type OnOfflineValidator: OnOfflineValidator;
}

decl_storage! {
trait Store for Module<T: Trait> as Consensus {
// Authorities set actual at the block execution start. IsSome only if
// the set has been changed.
OriginalAuthorities: Vec<T::SessionKey>;
}
}

decl_module! {
pub struct Module<T: Trait>;

Expand Down Expand Up @@ -149,12 +210,40 @@ impl<T: Trait> Module<T> {
///
/// Called by `next_session` only.
pub fn set_authorities(authorities: &[T::SessionKey]) {
AuthorityStorageVec::<T::SessionKey>::set_items(authorities);
let current_authorities = AuthorityStorageVec::<T::SessionKey>::items();
if current_authorities != authorities {
Self::save_original_authorities(Some(current_authorities));
AuthorityStorageVec::<T::SessionKey>::set_items(authorities);
}
}

/// Set a single authority by index.
pub fn set_authority(index: u32, key: &T::SessionKey) {
AuthorityStorageVec::<T::SessionKey>::set_item(index, key);
let current_authority = AuthorityStorageVec::<T::SessionKey>::item(index);
if current_authority != *key {
Self::save_original_authorities(None);
AuthorityStorageVec::<T::SessionKey>::set_item(index, key);
}
}

/// Save original authorities set.
fn save_original_authorities(current_authorities: Option<Vec<T::SessionKey>>) {
if OriginalAuthorities::<T>::get().is_some() {
// if we have already saved original set before, do not overwrite
return;
}

<OriginalAuthorities<T>>::put(current_authorities.unwrap_or_else(||
AuthorityStorageVec::<T::SessionKey>::items()));
}
}

/// Finalization hook for the consensus module.
impl<T: Trait> Executable for Module<T> {
fn execute() {
if let Some(_) = <OriginalAuthorities<T>>::take() {
// TODO: call Self::deposit_log
}
}
}

Expand Down
1 change: 1 addition & 0 deletions substrate/runtime/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ mod tests {
}
impl consensus::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
type Log = u64;
type SessionKey = u64;
type OnOfflineValidator = staking::Module<Test>;
}
Expand Down
21 changes: 16 additions & 5 deletions substrate/runtime/primitives/src/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use rstd::prelude::*;
use codec::{Decode, Encode, Codec, Input, Output};
use runtime_support::AuxDispatchable;
use traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Block as BlockT,
Header as HeaderT, Hash as HashT};
Header as HeaderT, Hash as HashT, DigestItem as DigestItemT};
use rstd::ops;
use bft::Justification;

Expand Down Expand Up @@ -208,16 +208,27 @@ where
}
}

#[derive(Default, PartialEq, Eq, Clone, Encode, Decode)]
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub struct Digest<Item> {
pub logs: Vec<Item>,
}

impl<Item> Default for Digest<Item> {
fn default() -> Self {
Digest { logs: Vec::new(), }
}
}

impl<Item> traits::Digest for Digest<Item> where
Item: Member + Default + Codec
Item: DigestItemT + Codec
{
type Item = Item;

fn logs(&self) -> &[Self::Item] {
&self.logs
}

fn push(&mut self, item: Self::Item) {
self.logs.push(item);
}
Expand Down Expand Up @@ -317,7 +328,7 @@ impl<Number, Hash, DigestItem> Encode for Header<Number, Hash, DigestItem> where
impl<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestItem> where
Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec,
Hash: HashT,
DigestItem: Member + Default + Codec,
DigestItem: DigestItemT + Codec,
Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec,
{
type Number = Number;
Expand Down Expand Up @@ -356,7 +367,7 @@ impl<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestIte
impl<Number, Hash, DigestItem> Header<Number, Hash, DigestItem> where
Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec,
Hash: HashT,
DigestItem: Member + Default + Codec,
DigestItem: DigestItemT + Codec,
Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec,
{
/// Convenience helper for computing the hash of the header without having
Expand Down
9 changes: 9 additions & 0 deletions substrate/runtime/primitives/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,20 @@ pub struct Digest {

impl traits::Digest for Digest {
type Item = u64;

fn logs(&self) -> &[Self::Item] {
&self.logs
}

fn push(&mut self, item: Self::Item) {
self.logs.push(item);
}
}

impl traits::DigestItem for u64 {
type AuthoritiesChange = traits::StubDigestItem;
}

#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
Expand Down
Loading