mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 22:11:06 +00:00
committed by
Gav Wood
parent
153439aeea
commit
0e1023ae42
@@ -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;
|
||||
@@ -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))]
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -187,27 +187,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)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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)]
|
||||
@@ -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 {
|
||||
@@ -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);
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use substrate_primitives::{H256, H512};
|
||||
use super::{Digest, Header, UncheckedExtrinsic};
|
||||
use super::{Digest, Header, DigestItem, UncheckedExtrinsic};
|
||||
|
||||
type Block = super::Block<
|
||||
Header<u64, ::traits::BlakeTwo256, Vec<u8>>,
|
||||
Header<u64, ::traits::BlakeTwo256, DigestItem<u32>>,
|
||||
UncheckedExtrinsic<H256, u64, u64, ::Ed25519Signature>,
|
||||
>;
|
||||
|
||||
@@ -33,7 +33,10 @@ fn block_roundtrip_serialization() {
|
||||
number: 100_000,
|
||||
state_root: [1u8; 32].into(),
|
||||
extrinsics_root: [2u8; 32].into(),
|
||||
digest: Digest { logs: vec![vec![1, 2, 3], vec![4, 5, 6]] },
|
||||
digest: Digest { logs: vec![
|
||||
DigestItem::Other::<u32>(vec![1, 2, 3]),
|
||||
DigestItem::Other::<u32>(vec![4, 5, 6]),
|
||||
] },
|
||||
},
|
||||
extrinsics: vec![
|
||||
UncheckedExtrinsic::new_signed(
|
||||
@@ -64,3 +67,39 @@ fn block_roundtrip_serialization() {
|
||||
assert_eq!(block, decoded);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn system_digest_item_encoding() {
|
||||
let item = DigestItem::AuthoritiesChange::<u32>(vec![10, 20, 30]);
|
||||
let encoded = item.encode();
|
||||
assert_eq!(encoded, vec![
|
||||
// type = DigestItemType::AuthoritiesChange
|
||||
1,
|
||||
// number of items in athorities set
|
||||
3, 0, 0, 0,
|
||||
// authorities
|
||||
10, 0, 0, 0,
|
||||
20, 0, 0, 0,
|
||||
30, 0, 0, 0,
|
||||
]);
|
||||
|
||||
let decoded: DigestItem<u32> = Decode::decode(&mut &encoded[..]).unwrap();
|
||||
assert_eq!(item, decoded);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_system_digest_item_encoding() {
|
||||
let item = DigestItem::Other::<u32>(vec![10, 20, 30]);
|
||||
let encoded = item.encode();
|
||||
assert_eq!(encoded, vec![
|
||||
// type = DigestItemType::Other
|
||||
0,
|
||||
// length of other data
|
||||
3, 0, 0, 0,
|
||||
// authorities
|
||||
10, 20, 30,
|
||||
]);
|
||||
|
||||
let decoded: DigestItem<u32> = Decode::decode(&mut &encoded[..]).unwrap();
|
||||
assert_eq!(item, decoded);
|
||||
}
|
||||
@@ -242,3 +242,193 @@ macro_rules! impl_outer_config {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates enum that contains all possible log entries for the runtime.
|
||||
/// Every individual module of the runtime that is mentioned, must
|
||||
/// expose a `Log` and `RawLog` enums.
|
||||
///
|
||||
/// Generated enum is binary-compatible with and could be interpreted
|
||||
/// as `generic::DigestItem`.
|
||||
///
|
||||
/// Requires `use runtime_primitives::generic;` to be used.
|
||||
///
|
||||
/// Runtime requirements:
|
||||
/// 1) binary representation of all supported 'system' log items should stay
|
||||
/// the same. Otherwise, the native code will be unable to read log items
|
||||
/// generated by previous runtime versions
|
||||
/// 2) the support of 'system' log items should never be dropped by runtime.
|
||||
/// Otherwise, native code will lost its ability to read items of this type
|
||||
/// even if they were generated by the versions which have supported these
|
||||
/// items.
|
||||
#[macro_export]
|
||||
macro_rules! impl_outer_log {
|
||||
(
|
||||
$(#[$attr:meta])*
|
||||
pub enum $name:ident ($internal:ident: DigestItem<$( $genarg:ty ),*>) for $trait:ident {
|
||||
$( $module:ident($( $item:ident ),*) ),*
|
||||
}
|
||||
) => {
|
||||
/// Wrapper for all possible log entries for the `$trait` runtime. Provides binary-compatible
|
||||
/// `Encode`/`Decode` implementations with the corresponding `generic::DigestItem`.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
$(#[$attr])*
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct $name($internal);
|
||||
|
||||
/// All possible log entries for the `$trait` runtime. `Encode`/`Decode` implementations
|
||||
/// are auto-generated => it is not binary-compatible with `generic::DigestItem`.
|
||||
#[derive(Clone, PartialEq, Eq, Encode, Decode)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
|
||||
$(#[$attr])*
|
||||
#[allow(non_camel_case_types)]
|
||||
enum $internal {
|
||||
$(
|
||||
$module($module::Log<$trait>),
|
||||
)*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
/// Try to convert `$name` into `generic::DigestItemRef`. Returns Some when
|
||||
/// `self` is a 'system' log && it has been marked as 'system' in macro call.
|
||||
/// Otherwise, None is returned.
|
||||
#[allow(unreachable_patterns)]
|
||||
fn dref<'a>(&'a self) -> Option<generic::DigestItemRef<'a, $($genarg),*>> {
|
||||
match self.0 {
|
||||
$($(
|
||||
$internal::$module($module::RawLog::$item(ref v)) =>
|
||||
Some(generic::DigestItemRef::$item(v)),
|
||||
)*)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<generic::DigestItem<$($genarg),*>> for $name {
|
||||
/// Converts `generic::DigestItem` into `$name`. If `generic::DigestItem` represents
|
||||
/// a system item which is supported by the runtime, it is returned.
|
||||
/// Otherwise we expect a `Other` log item. Trying to convert from anything other
|
||||
/// will lead to panic in runtime, since the runtime does not supports this 'system'
|
||||
/// log item.
|
||||
#[allow(unreachable_patterns)]
|
||||
fn from(gen: generic::DigestItem<$($genarg),*>) -> Self {
|
||||
match gen {
|
||||
$($(
|
||||
generic::DigestItem::$item(value) =>
|
||||
$name($internal::$module($module::RawLog::$item(value))),
|
||||
)*)*
|
||||
_ => gen.as_other()
|
||||
.and_then(|value| Decode::decode(&mut &value[..]))
|
||||
.map($name)
|
||||
.expect("not allowed to fail in runtime"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for $name {
|
||||
/// `generic::DigestItem` binray compatible decode.
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
let gen: generic::DigestItem<$($genarg),*> = Decode::decode(input)?;
|
||||
Some($name::from(gen))
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for $name {
|
||||
/// `generic::DigestItem` binray compatible encode.
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
match self.dref() {
|
||||
Some(dref) => dref.encode(),
|
||||
None => {
|
||||
let gen: generic::DigestItem<$($genarg),*> = generic::DigestItem::Other(self.0.encode());
|
||||
gen.encode()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
impl From<$module::Log<$trait>> for $name {
|
||||
/// Converts single module log item into `$name`.
|
||||
fn from(x: $module::Log<$trait>) -> Self {
|
||||
$name(x.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$module::Log<$trait>> for $internal {
|
||||
/// Converts single module log item into `$internal`.
|
||||
fn from(x: $module::Log<$trait>) -> Self {
|
||||
$internal::$module(x)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use codec::{Encode, Decode, Input};
|
||||
|
||||
pub trait RuntimeT {
|
||||
type AuthorityId;
|
||||
}
|
||||
|
||||
pub struct Runtime;
|
||||
|
||||
impl RuntimeT for Runtime {
|
||||
type AuthorityId = u64;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn impl_outer_log_works() {
|
||||
mod a {
|
||||
use super::RuntimeT;
|
||||
pub type Log<R> = RawLog<<R as RuntimeT>::AuthorityId>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawLog<AuthorityId> { A1(AuthorityId), AuthoritiesChange(Vec<AuthorityId>), A3(AuthorityId) }
|
||||
}
|
||||
|
||||
mod b {
|
||||
use super::RuntimeT;
|
||||
pub type Log<R> = RawLog<<R as RuntimeT>::AuthorityId>;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Encode, Decode, PartialEq, Eq, Clone)]
|
||||
pub enum RawLog<AuthorityId> { B1(AuthorityId), B2(AuthorityId) }
|
||||
}
|
||||
|
||||
use super::generic; // required before macro invocation
|
||||
|
||||
// TODO try to avoid redundant brackets: a(AuthoritiesChange), b
|
||||
impl_outer_log! {
|
||||
pub enum Log(InternalLog: DigestItem<u64>) for Runtime {
|
||||
a(AuthoritiesChange), b()
|
||||
}
|
||||
}
|
||||
|
||||
// encode/decode regular item
|
||||
let b1: Log = b::RawLog::B1::<u64>(777).into();
|
||||
let encoded_b1 = b1.encode();
|
||||
let decoded_b1: Log = Decode::decode(&mut &encoded_b1[..]).unwrap();
|
||||
assert_eq!(b1, decoded_b1);
|
||||
|
||||
// encode/decode system item
|
||||
let auth_change: Log = a::RawLog::AuthoritiesChange::<u64>(vec![100, 200, 300]).into();
|
||||
let encoded_auth_change = auth_change.encode();
|
||||
let decoded_auth_change: Log = Decode::decode(&mut &encoded_auth_change[..]).unwrap();
|
||||
assert_eq!(auth_change, decoded_auth_change);
|
||||
|
||||
// interpret regular item using `generic::DigestItem`
|
||||
let generic_b1: generic::DigestItem<u64> = Decode::decode(&mut &encoded_b1[..]).unwrap();
|
||||
match generic_b1 {
|
||||
generic::DigestItem::Other(_) => (),
|
||||
_ => panic!("unexpected generic_b1: {:?}", generic_b1),
|
||||
}
|
||||
|
||||
// interpret system item using `generic::DigestItem`
|
||||
let generic_auth_change: generic::DigestItem<u64> = Decode::decode(&mut &encoded_auth_change[..]).unwrap();
|
||||
match generic_auth_change {
|
||||
generic::DigestItem::AuthoritiesChange(authorities) => assert_eq!(authorities, vec![100, 200, 300]),
|
||||
_ => panic!("unexpected generic_auth_change: {:?}", generic_auth_change),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,12 @@ impl traits::Digest for Digest {
|
||||
}
|
||||
}
|
||||
|
||||
impl traits::DigestItem for () {
|
||||
type AuthorityId = ();
|
||||
}
|
||||
|
||||
impl traits::DigestItem for u64 {
|
||||
type AuthoritiesChange = ();
|
||||
type AuthorityId = ();
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Debug, Encode, Decode)]
|
||||
|
||||
@@ -433,35 +433,10 @@ pub trait Digest: Member + Default {
|
||||
///
|
||||
/// If the runtime does not supports some 'system' items, use `()` as a stub.
|
||||
pub trait DigestItem: Member {
|
||||
/// Events of this type is raised by the runtime when set of authorities is changed.
|
||||
/// Provides access to the new set of authorities.
|
||||
type AuthoritiesChange: AuthoritiesChangeDigest; // TODO: = () when associated type defaults are stabilized
|
||||
type AuthorityId;
|
||||
|
||||
/// Returns Some if the entry is the `AuthoritiesChange` entry.
|
||||
fn as_authorities_change(&self) -> Option<&Self::AuthoritiesChange> {
|
||||
fn as_authorities_change(&self) -> Option<&[Self::AuthorityId]> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Authorities change digest item. Created when the set of authorities is changed
|
||||
/// within the runtime.
|
||||
pub trait AuthoritiesChangeDigest {
|
||||
/// Type of authority Id.
|
||||
type AuthorityId: Member;
|
||||
|
||||
/// Get reference to the new authorities set.
|
||||
fn authorities(&self) -> &[Self::AuthorityId];
|
||||
}
|
||||
|
||||
/// Stub implementations for the digest item that is never created and used.
|
||||
///
|
||||
/// Should be used as a stub for items that are not supported by runtimes.
|
||||
impl DigestItem for () {
|
||||
type AuthoritiesChange = ();
|
||||
}
|
||||
|
||||
impl AuthoritiesChangeDigest for () {
|
||||
type AuthorityId = ();
|
||||
|
||||
fn authorities(&self) -> &[Self::AuthorityId] { unreachable!("() is never created") }
|
||||
}
|
||||
|
||||
@@ -111,12 +111,14 @@ pub type Hash = H256;
|
||||
pub type BlockNumber = u64;
|
||||
/// Index of a transaction.
|
||||
pub type Index = u64;
|
||||
/// The item of a block digest.
|
||||
pub type DigestItem = runtime_primitives::generic::DigestItem<u64>;
|
||||
/// The digest of a block.
|
||||
pub type Digest = runtime_primitives::generic::Digest<()>;
|
||||
pub type Digest = runtime_primitives::generic::Digest<DigestItem>;
|
||||
/// A test block.
|
||||
pub type Block = runtime_primitives::generic::Block<Header, Extrinsic>;
|
||||
/// A test block's header.
|
||||
pub type Header = runtime_primitives::generic::Header<BlockNumber, BlakeTwo256, ()>;
|
||||
pub type Header = runtime_primitives::generic::Header<BlockNumber, BlakeTwo256, DigestItem>;
|
||||
|
||||
/// Run whatever tests we have.
|
||||
pub fn run_tests(mut input: &[u8]) -> Vec<u8> {
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user