mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 22:51:13 +00:00
Traitify Runtime (#104)
* Factor out safe-mix and dispatch * Refactor dispatch into something more modular. * Fix wasm build. * Fix up timestamp * fix warnings. * Borked timestamp example * Fix build * Timestamp as skeleton for traity runtime. * New storage macro. * Dispatch module has traity API. * Move consensus module to new API * Refactoring and outer dispatch * Avoid unnecessary derives. * Abstract the low-level half of system. * nicer outer dispatch syntax. * Make runtime compile again (albeit in a heavily simplified state) * Reworking runtime and the upper levels of system. * Initial reworking of runtime: - Introduced executive module; - Introduced trait primitives module; - Provided an API endpoint. * Expose an additional function in system * Another couple of functions traitified in executive. * another function in executive traitified. * One more function traitified. * Finish traitifying executive! * Traitify session module. * Cleanups and ensure session gets run. * First part of traitification of staking module. * Bit more of staking traitified. * Additional stuff in staking. Fix up session. * Penultimate part of staking module. * Final part of staking (code) * Update demo runtime to include staking. * Final tweaks for staking integration. * Remove old runtime files. * Schedule staking. * Minor fixes * First bits of democracy. * Democracy module integrated. * Fix warning. * Traitify and integrate council module * Council voting. * Runtime binary and tweaks. * Binary update. * Fix `*Type` grumble. * Fix up genesis_map * Remove NonTrivialSlicable * Staking "test externalities" stuff along with refactor. * Add session test externalities constructor * Fixed executor tests. * Make one test in executive module work. * Remove test framework stuff into common module. * Enable other tests in executive * Session tests reinstated, minor refactoring of keyring. * Fix staking tests. * Fix up democracy tests. * First few tests in council. * Council tests reinstated :) * Avoid hardcoding blake2 into Header. * Fix last few tests. * Make all primitives generic. * Fix tests. * Refactor runtime to remove genesismap. * Streamline runtime more with macrofied config. * Clean paths * Fix warning. * Consolidate demo runtime crate. * Remove stale code. * Refactor away dodgy trait. * Add corresponding Aux type. * Fixes * Rename Digesty -> Digest * Rename Headery -> Header * Blocky -> Block * Fix wasm build. * kill warnings * more docs * minor cleanups
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "substrate-runtime-primitives"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
num-traits = { version = "0.2", default_features = false }
|
||||
integer-sqrt = "0.1.0"
|
||||
serde = { version = "1.0", optional = true }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
substrate-codec = { path = "../../codec", 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 }
|
||||
substrate-runtime-support = { path = "../../runtime-support", default_features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = [
|
||||
"num-traits/std",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"substrate-runtime-std/std",
|
||||
"substrate-runtime-io/std",
|
||||
"substrate-runtime-support/std",
|
||||
"substrate-codec/std",
|
||||
"substrate-primitives/std",
|
||||
]
|
||||
@@ -0,0 +1,398 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate Demo.
|
||||
|
||||
// Substrate Demo 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 Demo 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 Demo. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Generic implementations of Extrinsic/Header/Block.
|
||||
|
||||
#[cfg(feature = "std")] use serde::Serialize;
|
||||
use rstd::prelude::*;
|
||||
use codec::{Slicable, Input};
|
||||
use runtime_support::AuxDispatchable;
|
||||
use traits;
|
||||
use rstd::ops;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::fmt::{self, Debug};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub trait MaybeSerializeDebug: Serialize + Debug {}
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: Serialize + Debug> MaybeSerializeDebug for T {}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub trait MaybeSerializeDebug {}
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T> MaybeSerializeDebug for T {}
|
||||
|
||||
pub trait Member: MaybeSerializeDebug + Eq + PartialEq + Clone {}
|
||||
impl<T: MaybeSerializeDebug + Eq + PartialEq + Clone> Member for T {}
|
||||
|
||||
/// A vetted and verified extrinsic from the external world.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
|
||||
pub struct Extrinsic<AccountId, Index, Call> where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
{
|
||||
/// Who signed it (note this is not a signature).
|
||||
pub signed: AccountId,
|
||||
/// The number of extrinsics have come before from the same signer.
|
||||
pub index: Index,
|
||||
/// The function that should be called.
|
||||
pub function: Call,
|
||||
}
|
||||
|
||||
impl<AccountId, Index, Call> Slicable for Extrinsic<AccountId, Index, Call> where
|
||||
AccountId: Member + Slicable,
|
||||
Index: Member + Slicable,
|
||||
Call: Member + Slicable
|
||||
{
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Extrinsic {
|
||||
signed: Slicable::decode(input)?,
|
||||
index: Slicable::decode(input)?,
|
||||
function: Slicable::decode(input)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut v = Vec::new();
|
||||
|
||||
self.signed.using_encoded(|s| v.extend(s));
|
||||
self.index.using_encoded(|s| v.extend(s));
|
||||
self.function.using_encoded(|s| v.extend(s));
|
||||
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
/// A extrinsics right from the external world. Unchecked.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Serialize))]
|
||||
pub struct UncheckedExtrinsic<AccountId, Index, Call, Signature> where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member
|
||||
{
|
||||
/// The actual extrinsic information.
|
||||
pub extrinsic: Extrinsic<AccountId, Index, Call>,
|
||||
/// The signature; should be an Ed25519 signature applied to the serialised `extrinsic` field.
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
impl<AccountId, Index, Call, Signature> Slicable for UncheckedExtrinsic<AccountId, Index, Call, Signature> where
|
||||
AccountId: Member + Slicable,
|
||||
Index: Member + Slicable,
|
||||
Call: Member + Slicable,
|
||||
Signature: Member + Slicable
|
||||
{
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
// This is a little more complicated than usual since the binary format must be compatible
|
||||
// with substrate's generic `Vec<u8>` type. Basically this just means accepting that there
|
||||
// will be a prefix of u32, which has the total number of bytes following (we don't need
|
||||
// to use this).
|
||||
let _length_do_not_remove_me_see_above: u32 = Slicable::decode(input)?;
|
||||
|
||||
Some(UncheckedExtrinsic {
|
||||
extrinsic: Slicable::decode(input)?,
|
||||
signature: Slicable::decode(input)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut v = Vec::new();
|
||||
|
||||
// need to prefix with the total length as u32 to ensure it's binary comptible with
|
||||
// Vec<u8>. we'll make room for it here, then overwrite once we know the length.
|
||||
v.extend(&[0u8; 4]);
|
||||
|
||||
self.extrinsic.signed.using_encoded(|s| v.extend(s));
|
||||
self.extrinsic.index.using_encoded(|s| v.extend(s));
|
||||
self.extrinsic.function.using_encoded(|s| v.extend(s));
|
||||
self.signature.using_encoded(|s| v.extend(s));
|
||||
|
||||
let length = (v.len() - 4) as u32;
|
||||
length.using_encoded(|s| v[0..4].copy_from_slice(s));
|
||||
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<AccountId, Index, Call, Signature> fmt::Debug for UncheckedExtrinsic<AccountId, Index, Call, Signature> where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "UncheckedExtrinsic({:?})", self.extrinsic)
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId, Index, Call, Signature> traits::Checkable for UncheckedExtrinsic<AccountId, Index, Call, Signature> where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member + traits::Verify<Signer = AccountId>,
|
||||
Extrinsic<AccountId, Index, Call>: Slicable
|
||||
{
|
||||
type Checked = CheckedExtrinsic<AccountId, Index, Call, Signature>;
|
||||
|
||||
fn check(self) -> Result<Self::Checked, Self> {
|
||||
if ::codec::Slicable::using_encoded(&self.extrinsic, |msg|
|
||||
self.signature.verify(msg, &self.extrinsic.signed)
|
||||
) {
|
||||
Ok(CheckedExtrinsic(self))
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A type-safe indicator that a extrinsic has been checked.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug))]
|
||||
pub struct CheckedExtrinsic<AccountId, Index, Call, Signature>
|
||||
(UncheckedExtrinsic<AccountId, Index, Call, Signature>)
|
||||
where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member;
|
||||
|
||||
impl<AccountId, Index, Call, Signature> CheckedExtrinsic<AccountId, Index, Call, Signature>
|
||||
where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member
|
||||
{
|
||||
/// Get a reference to the checked signature.
|
||||
pub fn signature(&self) -> &Signature {
|
||||
&self.0.signature
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId, Index, Call, Signature> ops::Deref
|
||||
for CheckedExtrinsic<AccountId, Index, Call, Signature>
|
||||
where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member
|
||||
{
|
||||
type Target = Extrinsic<AccountId, Index, Call>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0.extrinsic
|
||||
}
|
||||
}
|
||||
|
||||
impl<AccountId, Index, Call, Signature> traits::Applyable
|
||||
for CheckedExtrinsic<AccountId, Index, Call, Signature>
|
||||
where
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member + AuxDispatchable<Aux = AccountId>,
|
||||
Signature: Member
|
||||
{
|
||||
type Index = Index;
|
||||
type AccountId = AccountId;
|
||||
|
||||
fn index(&self) -> &Self::Index {
|
||||
&self.0.extrinsic.index
|
||||
}
|
||||
|
||||
fn sender(&self) -> &Self::AccountId {
|
||||
&self.0.extrinsic.signed
|
||||
}
|
||||
|
||||
fn apply(self) {
|
||||
let xt = self.0.extrinsic;
|
||||
xt.function.dispatch(&xt.signed);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
pub struct Digest<Item: Member> {
|
||||
pub logs: Vec<Item>,
|
||||
}
|
||||
impl<Item> Slicable for Digest<Item> where
|
||||
Item: Member + Slicable
|
||||
{
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Digest { logs: Slicable::decode(input)? })
|
||||
}
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
self.logs.using_encoded(f)
|
||||
}
|
||||
}
|
||||
impl<Item> traits::Digest for Digest<Item> where
|
||||
Item: Member + Slicable
|
||||
{
|
||||
type Item = Item;
|
||||
fn push(&mut self, item: Self::Item) {
|
||||
self.logs.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// Abstraction over a block header for a substrate chain.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
|
||||
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
|
||||
pub struct Header<Number, Hash, DigestItem> where
|
||||
Number: Member,
|
||||
Hash: Member,
|
||||
DigestItem: Member,
|
||||
{
|
||||
/// The parent hash.
|
||||
pub parent_hash: Hash,
|
||||
/// The block number.
|
||||
pub number: Number,
|
||||
/// The state trie merkle root
|
||||
pub state_root: Hash,
|
||||
/// The merkle root of the extrinsics.
|
||||
pub extrinsics_root: Hash,
|
||||
/// A chain-specific digest of data useful for light clients or referencing auxiliary data.
|
||||
pub digest: Digest<DigestItem>,
|
||||
}
|
||||
|
||||
impl<Number, Hash, DigestItem> Slicable for Header<Number, Hash, DigestItem> where
|
||||
Number: Member + Slicable,
|
||||
Hash: Member + Slicable,
|
||||
DigestItem: Member + Slicable,
|
||||
{
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Header {
|
||||
parent_hash: Slicable::decode(input)?,
|
||||
number: Slicable::decode(input)?,
|
||||
state_root: Slicable::decode(input)?,
|
||||
extrinsics_root: Slicable::decode(input)?,
|
||||
digest: Slicable::decode(input)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut v = Vec::new();
|
||||
self.parent_hash.using_encoded(|s| v.extend(s));
|
||||
self.number.using_encoded(|s| v.extend(s));
|
||||
self.state_root.using_encoded(|s| v.extend(s));
|
||||
self.extrinsics_root.using_encoded(|s| v.extend(s));
|
||||
self.digest.using_encoded(|s| v.extend(s));
|
||||
v
|
||||
}
|
||||
}
|
||||
impl<Number, Hash, DigestItem> traits::Header for Header<Number, Hash, DigestItem> where
|
||||
Number: Member + Slicable,
|
||||
Hash: Member + Slicable,
|
||||
DigestItem: Member + Slicable,
|
||||
{
|
||||
type Number = Number;
|
||||
type Hash = Hash;
|
||||
type Digest = Digest<DigestItem>;
|
||||
|
||||
fn number(&self) -> &Self::Number { &self.number }
|
||||
fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root }
|
||||
fn state_root(&self) -> &Self::Hash { &self.state_root }
|
||||
fn parent_hash(&self) -> &Self::Hash { &self.parent_hash }
|
||||
fn digest(&self) -> &Self::Digest { &self.digest }
|
||||
fn new(
|
||||
number: Self::Number,
|
||||
extrinsics_root: Self::Hash,
|
||||
state_root: Self::Hash,
|
||||
parent_hash: Self::Hash,
|
||||
digest: Self::Digest
|
||||
) -> Self {
|
||||
Header {
|
||||
number, extrinsics_root: extrinsics_root, state_root, parent_hash, digest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Abstraction over a substrate block.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
|
||||
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
|
||||
pub struct Block<Number, Hash, DigestItem, AccountId, Index, Call, Signature> where
|
||||
Number: Member,
|
||||
Hash: Member,
|
||||
DigestItem: Member,
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member
|
||||
{
|
||||
/// The block header.
|
||||
pub header: Header<Number, Hash, DigestItem>,
|
||||
/// The accompanying extrinsics.
|
||||
pub extrinsics: Vec<UncheckedExtrinsic<AccountId, Index, Call, Signature>>,
|
||||
}
|
||||
|
||||
impl<Number, Hash, DigestItem, AccountId, Index, Call, Signature> Slicable
|
||||
for Block<Number, Hash, DigestItem, AccountId, Index, Call, Signature>
|
||||
where
|
||||
Number: Member,
|
||||
Hash: Member,
|
||||
DigestItem: Member,
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member,
|
||||
Header<Number, Hash, DigestItem>: Slicable,
|
||||
UncheckedExtrinsic<AccountId, Index, Call, Signature>: Slicable,
|
||||
{
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Block {
|
||||
header: Slicable::decode(input)?,
|
||||
extrinsics: Slicable::decode(input)?,
|
||||
})
|
||||
}
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut v: Vec<u8> = Vec::new();
|
||||
v.extend(self.header.encode());
|
||||
v.extend(self.extrinsics.encode());
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl<Number, Hash, DigestItem, AccountId, Index, Call, Signature> traits::Block
|
||||
for Block<Number, Hash, DigestItem, AccountId, Index, Call, Signature>
|
||||
where
|
||||
Number: Member + Slicable,
|
||||
Hash: Member + Slicable,
|
||||
DigestItem: Member + Slicable,
|
||||
AccountId: Member,
|
||||
Index: Member,
|
||||
Call: Member,
|
||||
Signature: Member
|
||||
{
|
||||
type Extrinsic = UncheckedExtrinsic<AccountId, Index, Call, Signature>;
|
||||
type Header = Header<Number, Hash, DigestItem>;
|
||||
fn header(&self) -> &Self::Header {
|
||||
&self.header
|
||||
}
|
||||
fn extrinsics(&self) -> &[Self::Extrinsic] {
|
||||
&self.extrinsics[..]
|
||||
}
|
||||
fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>) {
|
||||
(self.header, self.extrinsics)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate Demo.
|
||||
|
||||
// Substrate Demo 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 Demo 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 Demo. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code
|
||||
//! and depositing logs.
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate serde;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate num_traits;
|
||||
extern crate integer_sqrt;
|
||||
extern crate substrate_runtime_std as rstd;
|
||||
extern crate substrate_runtime_io as runtime_io;
|
||||
extern crate substrate_runtime_support as runtime_support;
|
||||
extern crate substrate_codec as codec;
|
||||
extern crate substrate_primitives;
|
||||
|
||||
#[cfg(feature = "std")] use std::collections::HashMap;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod testing;
|
||||
|
||||
pub mod traits;
|
||||
pub mod generic;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub type BuiltExternalities = HashMap<Vec<u8>, Vec<u8>>;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub trait BuildExternalities {
|
||||
fn build_externalities(self) -> BuiltExternalities;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! __impl_outer_config_types {
|
||||
($concrete:ident $config:ident $snake:ident $($rest:ident)*) => {
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub type $config = $snake::GenesisConfig<$concrete>;
|
||||
__impl_outer_config_types! {$concrete $($rest)*}
|
||||
};
|
||||
($concrete:ident) => ()
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Implement the output "meta" module configuration struct.
|
||||
macro_rules! impl_outer_config {
|
||||
( pub struct $main:ident for $concrete:ident { $( $config:ident => $snake:ident, )* } ) => {
|
||||
__impl_outer_config_types! { $concrete $( $config $snake )* }
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub struct $main {
|
||||
$(
|
||||
pub $snake: Option<$config>,
|
||||
)*
|
||||
}
|
||||
#[cfg(any(feature = "std", test))]
|
||||
impl $crate::BuildExternalities for $main {
|
||||
fn build_externalities(self) -> $crate::BuiltExternalities {
|
||||
let mut s = $crate::BuiltExternalities::new();
|
||||
$(
|
||||
if let Some(extra) = self.$snake {
|
||||
s.extend(extra.build_externalities());
|
||||
}
|
||||
)*
|
||||
s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate Demo.
|
||||
|
||||
// Substrate Demo 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 Demo 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 Demo. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Testing utilities.
|
||||
|
||||
use serde;
|
||||
use codec::{Slicable, Input};
|
||||
use runtime_support::AuxDispatchable;
|
||||
use substrate_primitives::H256;
|
||||
use traits::{self, Checkable, Applyable};
|
||||
|
||||
#[derive(Default, PartialEq, Eq, Clone, Serialize, Debug)]
|
||||
pub struct Digest {
|
||||
pub logs: Vec<u64>,
|
||||
}
|
||||
impl Slicable for Digest {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Vec::<u64>::decode(input).map(|logs| Digest { logs })
|
||||
}
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||
self.logs.using_encoded(f)
|
||||
}
|
||||
}
|
||||
impl traits::Digest for Digest {
|
||||
type Item = u64;
|
||||
fn push(&mut self, item: Self::Item) {
|
||||
self.logs.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Serialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Header {
|
||||
pub parent_hash: H256,
|
||||
pub number: u64,
|
||||
pub state_root: H256,
|
||||
pub extrinsics_root: H256,
|
||||
pub digest: Digest,
|
||||
}
|
||||
impl Slicable for Header {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Header {
|
||||
parent_hash: Slicable::decode(input)?,
|
||||
number: Slicable::decode(input)?,
|
||||
state_root: Slicable::decode(input)?,
|
||||
extrinsics_root: Slicable::decode(input)?,
|
||||
digest: Slicable::decode(input)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut v = Vec::new();
|
||||
self.parent_hash.using_encoded(|s| v.extend(s));
|
||||
self.number.using_encoded(|s| v.extend(s));
|
||||
self.state_root.using_encoded(|s| v.extend(s));
|
||||
self.extrinsics_root.using_encoded(|s| v.extend(s));
|
||||
self.digest.using_encoded(|s| v.extend(s));
|
||||
v
|
||||
}
|
||||
}
|
||||
impl traits::Header for Header {
|
||||
type Number = u64;
|
||||
type Hash = H256;
|
||||
type Digest = Digest;
|
||||
fn number(&self) -> &Self::Number { &self.number }
|
||||
fn extrinsics_root(&self) -> &Self::Hash { &self.extrinsics_root }
|
||||
fn state_root(&self) -> &Self::Hash { &self.state_root }
|
||||
fn parent_hash(&self) -> &Self::Hash { &self.parent_hash }
|
||||
fn digest(&self) -> &Self::Digest { &self.digest }
|
||||
fn new(
|
||||
number: Self::Number,
|
||||
extrinsics_root: Self::Hash,
|
||||
state_root: Self::Hash,
|
||||
parent_hash: Self::Hash,
|
||||
digest: Self::Digest
|
||||
) -> Self {
|
||||
Header {
|
||||
number, extrinsics_root: extrinsics_root, state_root, parent_hash, digest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Serialize, Debug)]
|
||||
pub struct Block<Xt: Slicable + Sized + serde::Serialize> {
|
||||
pub header: Header,
|
||||
pub extrinsics: Vec<Xt>,
|
||||
}
|
||||
impl<Xt: Slicable + Sized + serde::Serialize> Slicable for Block<Xt> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(Block {
|
||||
header: Slicable::decode(input)?,
|
||||
extrinsics: Slicable::decode(input)?,
|
||||
})
|
||||
}
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
let mut v: Vec<u8> = Vec::new();
|
||||
v.extend(self.header.encode());
|
||||
v.extend(self.extrinsics.encode());
|
||||
v
|
||||
}
|
||||
}
|
||||
impl<Xt: Slicable + Sized + serde::Serialize> traits::Block for Block<Xt> {
|
||||
type Extrinsic = Xt;
|
||||
type Header = Header;
|
||||
fn header(&self) -> &Self::Header {
|
||||
&self.header
|
||||
}
|
||||
fn extrinsics(&self) -> &[Self::Extrinsic] {
|
||||
&self.extrinsics[..]
|
||||
}
|
||||
fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>) {
|
||||
(self.header, self.extrinsics)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Serialize, Debug)]
|
||||
pub struct TestXt<Call: AuxDispatchable + Slicable + Sized + serde::Serialize>(pub (u64, u64, Call));
|
||||
impl<Call: AuxDispatchable + Slicable + Sized + serde::Serialize> Slicable for TestXt<Call> {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> {
|
||||
Some(TestXt(Slicable::decode(input)?))
|
||||
}
|
||||
fn encode(&self) -> Vec<u8> {
|
||||
self.0.encode()
|
||||
}
|
||||
}
|
||||
impl<Call: AuxDispatchable + Slicable + Sized + serde::Serialize> Checkable for TestXt<Call> {
|
||||
type Checked = Self;
|
||||
fn check(self) -> Result<Self, Self> { Ok(self) }
|
||||
}
|
||||
impl<Call: AuxDispatchable<Aux = u64> + Slicable + Sized + serde::Serialize> Applyable for TestXt<Call> {
|
||||
type AccountId = u64;
|
||||
type Index = u64;
|
||||
fn sender(&self) -> &u64 { &(self.0).0 }
|
||||
fn index(&self) -> &u64 { &(self.0).1 }
|
||||
fn apply(self) { (self.0).2.dispatch(&(self.0).0); }
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate Demo.
|
||||
|
||||
// Substrate Demo 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 Demo 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 Demo. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Primitives for the runtime modules.
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd;
|
||||
#[cfg(not(feature = "std"))] use runtime_io;
|
||||
use substrate_primitives;
|
||||
use codec::{Input, Slicable};
|
||||
use substrate_primitives::hash::H512;
|
||||
pub use integer_sqrt::IntegerSquareRoot;
|
||||
pub use num_traits::{Zero, One, Bounded};
|
||||
use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
||||
|
||||
/// Means of signature verification.
|
||||
pub trait Verify {
|
||||
/// Type of the signer.
|
||||
type Signer;
|
||||
/// Verify a signature.
|
||||
fn verify(&self, msg: &[u8], signer: &Self::Signer) -> bool;
|
||||
}
|
||||
|
||||
/// Ed25519 signature verify.
|
||||
#[derive(Eq, PartialEq, Clone)]
|
||||
#[cfg_attr(feature = "std", derive(Debug, Serialize))]
|
||||
pub struct Ed25519Signature(H512);
|
||||
impl Verify for Ed25519Signature {
|
||||
type Signer = [u8; 32];
|
||||
fn verify(&self, msg: &[u8], signer: &Self::Signer) -> bool {
|
||||
::runtime_io::ed25519_verify(&(self.0).0, msg, &signer[..])
|
||||
}
|
||||
}
|
||||
impl Slicable for Ed25519Signature {
|
||||
fn decode<I: Input>(input: &mut I) -> Option<Self> { Some(Ed25519Signature(Slicable::decode(input)?,)) }
|
||||
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R { self.0.using_encoded(f) }
|
||||
}
|
||||
impl From<H512> for Ed25519Signature {
|
||||
fn from(h: H512) -> Ed25519Signature {
|
||||
Ed25519Signature(h)
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple payment making trait, operating on a single generic `AccountId` type.
|
||||
pub trait MakePayment<AccountId> {
|
||||
/// Make some sort of payment concerning `who`.
|
||||
fn make_payment(who: &AccountId);
|
||||
}
|
||||
|
||||
impl<T> MakePayment<T> for () {
|
||||
fn make_payment(_: &T) {}
|
||||
}
|
||||
|
||||
/// Extensible conversion trait. Generic over both source and destination types.
|
||||
pub trait Convert<A, B> {
|
||||
/// Make conversion.
|
||||
fn convert(a: A) -> B;
|
||||
}
|
||||
|
||||
/// Simple trait similar to `Into`, except that it can be used to convert numerics between each
|
||||
/// other.
|
||||
pub trait As<T> {
|
||||
/// Convert forward (ala `Into::into`).
|
||||
fn as_(self) -> T;
|
||||
/// Convert backward (ala `From::from`).
|
||||
fn sa(T) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! impl_numerics {
|
||||
( $( $t:ty ),* ) => {
|
||||
$(
|
||||
impl_numerics!($t: u8, u16, u32, u64, usize, i8, i16, i32, i64, isize,);
|
||||
)*
|
||||
};
|
||||
( $f:ty : $t:ty, $( $rest:ty, )* ) => {
|
||||
impl As<$t> for $f {
|
||||
fn as_(self) -> $t { self as $t }
|
||||
fn sa(t: $t) -> Self { t as Self }
|
||||
}
|
||||
impl_numerics!($f: $( $rest, )*);
|
||||
};
|
||||
( $f:ty : ) => {}
|
||||
}
|
||||
|
||||
impl_numerics!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
|
||||
|
||||
pub struct Identity;
|
||||
impl<T> Convert<T, T> for Identity {
|
||||
fn convert(a: T) -> T { a }
|
||||
}
|
||||
|
||||
pub trait HasPublicAux {
|
||||
type PublicAux;
|
||||
}
|
||||
|
||||
pub trait RefInto<T> {
|
||||
fn ref_into(&self) -> &T;
|
||||
}
|
||||
impl<T> RefInto<T> for T {
|
||||
fn ref_into(&self) -> &T { &self }
|
||||
}
|
||||
|
||||
pub trait SimpleArithmetic:
|
||||
Zero + One + IntegerSquareRoot + As<usize> +
|
||||
Add<Self, Output = Self> + AddAssign<Self> +
|
||||
Sub<Self, Output = Self> + SubAssign<Self> +
|
||||
Mul<Self, Output = Self> + MulAssign<Self> +
|
||||
Div<Self, Output = Self> + DivAssign<Self> +
|
||||
Rem<Self, Output = Self> + RemAssign<Self> +
|
||||
PartialOrd<Self> + Ord
|
||||
{}
|
||||
impl<T:
|
||||
Zero + One + IntegerSquareRoot + As<usize> +
|
||||
Add<Self, Output = Self> + AddAssign<Self> +
|
||||
Sub<Self, Output = Self> + SubAssign<Self> +
|
||||
Mul<Self, Output = Self> + MulAssign<Self> +
|
||||
Div<Self, Output = Self> + DivAssign<Self> +
|
||||
Rem<Self, Output = Self> + RemAssign<Self> +
|
||||
PartialOrd<Self> + Ord
|
||||
> SimpleArithmetic for T {}
|
||||
|
||||
pub trait SimpleBitOps:
|
||||
Sized +
|
||||
rstd::ops::BitOr<Self, Output = Self> +
|
||||
rstd::ops::BitAnd<Self, Output = Self>
|
||||
{}
|
||||
impl<T:
|
||||
Sized +
|
||||
rstd::ops::BitOr<Self, Output = Self> +
|
||||
rstd::ops::BitAnd<Self, Output = Self>
|
||||
> SimpleBitOps for T {}
|
||||
|
||||
/// Something that can be executed.
|
||||
pub trait Executable {
|
||||
fn execute();
|
||||
}
|
||||
|
||||
impl Executable for () {
|
||||
fn execute() {}
|
||||
}
|
||||
impl<A: Executable, B: Executable> Executable for (A, B) {
|
||||
fn execute() {
|
||||
A::execute();
|
||||
B::execute();
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that acts like a `Digest` - it can have `Log`s `push`ed onto it and these `Log`s are
|
||||
/// each `Slicable`.
|
||||
pub trait Digest {
|
||||
type Item: Sized;
|
||||
fn push(&mut self, item: Self::Item);
|
||||
}
|
||||
|
||||
impl Digest for substrate_primitives::Digest {
|
||||
type Item = substrate_primitives::block::Log;
|
||||
fn push(&mut self, item: Self::Item) {
|
||||
self.logs.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// Something which fulfills the abstract idea of a Substrate header. It has types for a `Number`,
|
||||
/// a `Hash` and a `Digest`. It provides access to an `extrinsics_root`, `state_root` and
|
||||
/// `parent_hash`, as well as a `digest` and a block `number`.
|
||||
///
|
||||
/// You can also create a `new` one from those fields.
|
||||
pub trait Header: Sized + Slicable {
|
||||
type Number: Sized;
|
||||
type Hash: Sized;
|
||||
type Digest: Sized;
|
||||
fn number(&self) -> &Self::Number;
|
||||
fn extrinsics_root(&self) -> &Self::Hash;
|
||||
fn state_root(&self) -> &Self::Hash;
|
||||
fn parent_hash(&self) -> &Self::Hash;
|
||||
fn digest(&self) -> &Self::Digest;
|
||||
fn new(
|
||||
number: Self::Number,
|
||||
extrinsics_root: Self::Hash,
|
||||
state_root: Self::Hash,
|
||||
parent_hash: Self::Hash,
|
||||
digest: Self::Digest
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl Header for substrate_primitives::Header {
|
||||
type Number = substrate_primitives::block::Number;
|
||||
type Hash = substrate_primitives::block::HeaderHash;
|
||||
type Digest = substrate_primitives::block::Digest;
|
||||
fn number(&self) -> &Self::Number { &self.number }
|
||||
fn extrinsics_root(&self) -> &Self::Hash { &self.transaction_root }
|
||||
fn state_root(&self) -> &Self::Hash { &self.state_root }
|
||||
fn parent_hash(&self) -> &Self::Hash { &self.parent_hash }
|
||||
fn digest(&self) -> &Self::Digest { &self.digest }
|
||||
fn new(
|
||||
number: Self::Number,
|
||||
extrinsics_root: Self::Hash,
|
||||
state_root: Self::Hash,
|
||||
parent_hash: Self::Hash,
|
||||
digest: Self::Digest
|
||||
) -> Self {
|
||||
substrate_primitives::Header {
|
||||
number: number,
|
||||
transaction_root: extrinsics_root,
|
||||
state_root: state_root,
|
||||
parent_hash: parent_hash,
|
||||
digest: digest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Something which fulfills the abstract idea of a Substrate block. It has types for an
|
||||
/// `Extrinsic` piece of information as well as a `Header`.
|
||||
///
|
||||
/// You can get an iterator over each of the `extrinsics` and retrieve the `header`.
|
||||
pub trait Block {
|
||||
type Extrinsic: Sized;
|
||||
type Header: Header;
|
||||
fn header(&self) -> &Self::Header;
|
||||
fn extrinsics(&self) -> &[Self::Extrinsic];
|
||||
fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>);
|
||||
}
|
||||
|
||||
impl Block for substrate_primitives::Block {
|
||||
type Extrinsic = substrate_primitives::block::Transaction;
|
||||
type Header = substrate_primitives::Header;
|
||||
fn header(&self) -> &Self::Header {
|
||||
&self.header
|
||||
}
|
||||
fn extrinsics(&self) -> &[Self::Extrinsic] {
|
||||
&self.transactions[..]
|
||||
}
|
||||
fn deconstruct(self) -> (Self::Header, Vec<Self::Extrinsic>) {
|
||||
(self.header, self.transactions)
|
||||
}
|
||||
}
|
||||
|
||||
/// A "checkable" piece of information, used by the standard Substrate Executive in order to
|
||||
/// check the validity of a piece of extrinsic information, usually by verifying the signature.
|
||||
pub trait Checkable: Sized {
|
||||
type Checked: Sized;
|
||||
fn check(self) -> Result<Self::Checked, Self>;
|
||||
}
|
||||
|
||||
/// An "executable" piece of information, used by the standard Substrate Executive in order to
|
||||
/// enact a piece of extrinsic information by marshalling and dispatching to a named functioon
|
||||
/// call.
|
||||
///
|
||||
/// Also provides information on to whom this information is attributable and an index that allows
|
||||
/// each piece of attributable information to be disambiguated.
|
||||
pub trait Applyable {
|
||||
type AccountId;
|
||||
type Index;
|
||||
fn index(&self) -> &Self::Index;
|
||||
fn sender(&self) -> &Self::AccountId;
|
||||
fn apply(self);
|
||||
}
|
||||
|
||||
/// Something that can be checked for equality and printed out to a debug channel if bad.
|
||||
pub trait CheckEqual {
|
||||
fn check_equal(&self, other: &Self);
|
||||
}
|
||||
|
||||
impl CheckEqual for substrate_primitives::H256 {
|
||||
#[cfg(feature = "std")]
|
||||
fn check_equal(&self, other: &Self) {
|
||||
use substrate_primitives::hexdisplay::HexDisplay;
|
||||
if &self.0 != &other.0 {
|
||||
println!("Hash: given={}, expected={}", HexDisplay::from(&self.0), HexDisplay::from(&other.0));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn check_equal(&self, other: &Self) {
|
||||
if self != other {
|
||||
runtime_io::print("Hash not equal");
|
||||
runtime_io::print(&self.0[..]);
|
||||
runtime_io::print(&other.0[..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user