Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

DigestItem trait (v3) #687

Merged
merged 7 commits into from
Sep 10, 2018
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
17 changes: 2 additions & 15 deletions demo/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use rstd::prelude::*;
use runtime_primitives::generic;
#[cfg(feature = "std")]
use primitives::bytes;
use runtime_primitives::traits::{BlakeTwo256, DigestItem};
use runtime_primitives::traits::BlakeTwo256;

/// An index to a block.
pub type BlockNumber = u64;
Expand Down Expand Up @@ -73,25 +73,12 @@ pub type Signature = runtime_primitives::Ed25519Signature;
pub type Timestamp = u64;

/// Header type.
pub type Header = generic::Header<BlockNumber, BlakeTwo256, Log>;
pub type Header = generic::Header<BlockNumber, BlakeTwo256, generic::DigestItem<()>>;
/// Block type.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// Block ID.
pub type BlockId = generic::BlockId<Block>;

/// A log entry in the block.
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);

//TODO: remove this. Generic primitives should not require DigestItem
impl DigestItem for Log {
type AuthoritiesChange = ();
fn as_authorities_change(&self) -> Option<&()> {
unreachable!()
}
}

/// Opaque, encoded, unchecked extrinsic.
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
Expand Down
13 changes: 7 additions & 6 deletions demo/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ use demo_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index
use runtime_primitives::generic;
use runtime_primitives::traits::{Convert, BlakeTwo256, DigestItem};
use version::RuntimeVersion;
use codec::{Encode, Decode, Input};
use council::motions as council_motions;
use substrate_primitives::u32_trait::{_2, _4};

Expand Down Expand Up @@ -202,8 +203,8 @@ impl_outer_event! {
}

impl_outer_log! {
pub enum Log for Runtime {
consensus
pub enum Log(InternalLog: DigestItem<SessionKey>) for Runtime {
consensus(AuthoritiesChange)
}
}

Expand Down Expand Up @@ -243,11 +244,11 @@ impl_outer_config! {
}

impl DigestItem for Log {
type AuthoritiesChange = consensus::AuthoritiesChange<SessionKey>;
type AuthorityId = SessionKey;

fn as_authorities_change(&self) -> Option<&Self::AuthoritiesChange> {
match *self {
Log::consensus(ref item) => item.as_authorities_change(),
fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> {
match self.0 {
InternalLog::consensus(ref item) => item.as_authorities_change(),
}
}
}
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
24 changes: 0 additions & 24 deletions substrate/runtime-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,27 +174,3 @@ macro_rules! impl_outer_origin {
}
}
}

#[macro_export]
macro_rules! impl_outer_log {

($(#[$attr:meta])* pub enum $name:ident for $trait:ident { $( $module:ident ),* }) => {
// 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)
}
}
)*
};
}
30 changes: 8 additions & 22 deletions substrate/runtime/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ 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, OnFinalise, Member, AuthoritiesChangeDigest};
use primitives::traits::{MaybeSerializeDebug, OnFinalise, Member, DigestItem};
use primitives::bft::MisbehaviorReport;
use system::{ensure_signed, ensure_inherent, ensure_root};

Expand Down Expand Up @@ -80,31 +80,25 @@ pub type Log<T> = RawLog<
<T as Trait>::SessionKey,
>;

/// An logs in this module.
/// A 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>),
AuthoritiesChange(Vec<SessionKey>),
}

impl<SessionKey> RawLog<SessionKey> {
impl<SessionKey: Member> DigestItem for RawLog<SessionKey> {
type AuthorityId = SessionKey;

/// Try to cast the log entry as AuthoritiesChange log entry.
pub fn as_authorities_change(&self) -> Option<&AuthoritiesChange<SessionKey>> {
fn as_authorities_change(&self) -> Option<&[SessionKey]> {
match *self {
RawLog::AuthoritiesChange(ref item) => Some(item),
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 {
Expand All @@ -114,14 +108,6 @@ impl<N> From<RawLog<N>> for u64 {
}
}

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;
Expand Down
150 changes: 150 additions & 0 deletions substrate/runtime/primitives/src/generic/digest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright 2017 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/>.

//! Generic implementation of a digest.

use rstd::prelude::*;

use codec::{Decode, Encode, Codec, Input};
use traits::{self, Member, DigestItem as DigestItemT};

#[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: DigestItemT + Codec
{
type Item = Item;

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

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

/// Digest item that is able to encode/decode 'system' digest items and
/// provide opaque access to other items.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
pub enum DigestItem<AuthorityId> {
/// System digest item announcing that authorities set has been changed
/// in the block. Contains the new set of authorities.
AuthoritiesChange(Vec<AuthorityId>),
/// Any 'non-system' digest item, opaque to the native code.
Other(Vec<u8>),
}

/// A 'referencing view' for digest item. Does not own its contents. Used by
/// final runtime implementations for encoding/decoding its log items.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum DigestItemRef<'a, AuthorityId: 'a> {
/// Reference to `DigestItem::AuthoritiesChange`.
AuthoritiesChange(&'a [AuthorityId]),
/// Reference to `DigestItem::Other`.
Other(&'a Vec<u8>),
}

/// Type of the digest item. Used to gain explicit control over `DigestItem` encoding
/// process. We need an explicit control, because final runtimes are encoding their own
/// digest items using `DigestItemRef` type and we can't auto-derive `Decode`
/// trait for `DigestItemRef`.
#[repr(u32)]
#[derive(Encode, Decode)]
enum DigestItemType {
Other = 0,
AuthoritiesChange,
}

impl<AuthorityId> DigestItem<AuthorityId> {
/// Returns Some if `self` is a `DigestItem::Other`.
pub fn as_other(&self) -> Option<&Vec<u8>> {
match *self {
DigestItem::Other(ref v) => Some(v),
_ => None,
}
}

/// Returns a 'referencing view' for this digest item.
fn dref<'a>(&'a self) -> DigestItemRef<'a, AuthorityId> {
match *self {
DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v),
DigestItem::Other(ref v) => DigestItemRef::Other(v),
}
}
}

impl<AuthorityId: Member> traits::DigestItem for DigestItem<AuthorityId> {
type AuthorityId = AuthorityId;

fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> {
match *self {
DigestItem::AuthoritiesChange(ref authorities) => Some(authorities),
_ => None,
}
}
}

impl<AuthorityId: Encode> Encode for DigestItem<AuthorityId> {
fn encode(&self) -> Vec<u8> {
self.dref().encode()
}
}

impl<AuthorityId: Decode> Decode for DigestItem<AuthorityId> {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
let item_type: DigestItemType = Decode::decode(input)?;
match item_type {
DigestItemType::AuthoritiesChange => Some(DigestItem::AuthoritiesChange(
Decode::decode(input)?,
)),
DigestItemType::Other => Some(DigestItem::Other(
Decode::decode(input)?,
)),
}
}
}

impl<'a, AuthorityId: Encode> Encode for DigestItemRef<'a, AuthorityId> {
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();

match *self {
DigestItemRef::AuthoritiesChange(authorities) => {
DigestItemType::AuthoritiesChange.encode_to(&mut v);
authorities.encode_to(&mut v);
},
DigestItemRef::Other(val) => {
DigestItemType::Other.encode_to(&mut v);
val.encode_to(&mut v);
},
}

v
}
}
34 changes: 4 additions & 30 deletions substrate/runtime/primitives/src/generic/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

//! Generic implementation of a header and digest.
//! Generic implementation of a block header.

#[cfg(feature = "std")]
use serde::{Deserialize, Deserializer};

use rstd::prelude::*;
use codec::{Decode, Encode, Codec, Input, Output};
use traits::{self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay,
Hash as HashT, DigestItem as DigestItemT};

#[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: DigestItemT + Codec
{
type Item = Item;

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

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

/// Abstraction over a block header for a substrate chain.
#[derive(PartialEq, Eq, Clone)]
Expand Down Expand Up @@ -112,7 +86,7 @@ impl<Number, Hash, DigestItem> Decode for Header<Number, Hash, DigestItem> where
Number: Decode,
Hash: HashT,
Hash::Output: Decode,
DigestItem: Decode,
DigestItem: DigestItemT + Decode,
{
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Header {
Expand All @@ -129,7 +103,7 @@ impl<Number, Hash, DigestItem> Encode for Header<Number, Hash, DigestItem> where
Number: Encode,
Hash: HashT,
Hash::Output: Encode,
DigestItem: Encode,
DigestItem: DigestItemT + Encode,
{
fn encode_to<T: Output>(&self, dest: &mut T) {
dest.push(&self.parent_hash);
Expand Down
4 changes: 3 additions & 1 deletion substrate/runtime/primitives/src/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ mod unchecked_extrinsic;
mod checked_extrinsic;
mod header;
mod block;
mod digest;
#[cfg(test)]
mod tests;

pub use self::unchecked_extrinsic::UncheckedExtrinsic;
pub use self::checked_extrinsic::CheckedExtrinsic;
pub use self::header::{Header, Digest};
pub use self::header::Header;
pub use self::block::{Block, SignedBlock, BlockId};
pub use self::digest::{Digest, DigestItem, DigestItemRef};
Loading