Make Polkadot use the Substrate traity libraries (#105)

* Initial stuff.

* Various fixes.

* Fix tests.

* Fix another test

* Fix another test.

* Docs in polkadot runtime.

* Fix up ser/de tests.

* Update god keys

* Syntax

* Fix

* Merge remote-tracking branch 'origin/master' into gav-merge-runtime

* Permissions on init.sh

* Port-over the whitespace from @rphmeier

* Rename

* Merge branch 'master' into gav-merge-runtime

* Fix typo.

* Fix grumbles.

* Make more idiomatic.

* Move `Ed25519Signature` out of traits.
This commit is contained in:
Gav Wood
2018-04-05 17:13:12 +02:00
committed by Robert Habermeier
parent 6b83f11a11
commit 1d8a9a6dd3
60 changed files with 1335 additions and 3636 deletions
+2
View File
@@ -9,6 +9,7 @@ serde_derive = { version = "1.0", optional = true }
substrate-codec = { path = "../../substrate/codec", default_features = false }
substrate-primitives = { path = "../../substrate/primitives", default_features = false }
substrate-runtime-std = { path = "../../substrate/runtime-std", default_features = false }
substrate-runtime-primitives = { path = "../../substrate/runtime/primitives", default_features = false }
[dev-dependencies]
substrate-serializer = { path = "../../substrate/serializer" }
@@ -20,6 +21,7 @@ std = [
"substrate-codec/std",
"substrate-primitives/std",
"substrate-runtime-std/std",
"substrate-runtime-primitives/std",
"serde_derive",
"serde/std",
]
-375
View File
@@ -1,375 +0,0 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Block and header type definitions.
#[cfg(feature = "std")]
use primitives::bytes;
use primitives::H256;
use rstd::vec::Vec;
use codec::{Input, Slicable};
use transaction::{UncheckedTransaction, Function, InherentFunction};
pub use primitives::block::Id;
/// Used to refer to a block number.
pub type Number = u64;
/// Hash used to refer to a block hash.
pub type HeaderHash = H256;
/// Hash used to refer to a transaction hash.
pub type TransactionHash = H256;
/// Execution log (event)
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Log {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<u8>::decode(input).map(Log)
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
/// The digest of a block, useful for light-clients.
#[derive(Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Digest {
/// All logs that have happened in the block.
pub logs: Vec<Log>,
}
impl Slicable for Digest {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Vec::<Log>::decode(input).map(|logs| Digest { logs })
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.logs.using_encoded(f)
}
}
/// Iterator over all inherent transactions.
pub struct InherentTransactions<'a> {
number: u64,
body: &'a Body,
}
impl<'a> Iterator for InherentTransactions<'a> {
type Item = UncheckedTransaction;
fn next(&mut self) -> Option<UncheckedTransaction> {
if self.number == InherentFunction::count() {
return None
}
self.number += 1;
let function = match self.number {
1 => Some(InherentFunction::TimestampSet(self.body.timestamp)),
_ => None,
};
function.map(UncheckedTransaction::inherent)
}
}
/// Type alias for an iterator over all transactions in a block.
pub type AllTransactions<'a> = ::rstd::iter::Chain<
InherentTransactions<'a>,
::rstd::iter::Cloned<::rstd::slice::Iter<'a, UncheckedTransaction>>,
>;
/// The block body. Contains timestamp and transactions.
// TODO: add candidates update as well.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Body {
/// The timestamp of the block.
pub timestamp: u64,
/// The transactions in the block.
pub transactions: Vec<UncheckedTransaction>,
}
impl Body {
/// Get an iterator over all inherent transactions of the body.
pub fn inherent_transactions(&self) -> InherentTransactions {
InherentTransactions {
number: 0,
body: self,
}
}
/// Get an iterator over all transactions in a block.
pub fn all_transactions(&self) -> AllTransactions {
self.inherent_transactions().chain(self.transactions.iter().cloned())
}
}
/// A Polkadot relay chain block.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Block {
/// The block header.
pub header: Header,
/// The block body.
pub body: Body,
}
impl Block {
/// Get an iterator over all inherent transactions of the body.
pub fn inherent_transactions(&self) -> InherentTransactions {
self.body.inherent_transactions()
}
/// Get an iterator over all transactions in a block.
pub fn all_transactions(&self) -> AllTransactions {
self.body.all_transactions()
}
}
impl Slicable for Block {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
let header = try_opt!(Slicable::decode(input));
let transactions_len: u32 = try_opt!(Slicable::decode(input));
let regular_transactions_len = try_opt!(transactions_len.checked_sub(InherentFunction::count() as u32));
let timestamp_tx = try_opt!(UncheckedTransaction::decode(input));
let timestamp = match timestamp_tx.transaction.function {
Function::Inherent(InherentFunction::TimestampSet(ref t)) if timestamp_tx.is_well_formed() => { t.clone() }
_ => return None,
};
let transactions: Option<Vec<_>> = (0..regular_transactions_len)
.map(|_| UncheckedTransaction::decode(input))
.filter(|tx| tx.as_ref().map_or(true, |tx| tx.is_well_formed()))
.collect();
let body = Body {
timestamp,
transactions: try_opt!(transactions),
};
Some(Block { header, body })
}
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
v.extend(self.header.encode());
// encode inherent transactions before non-inherent.
let transactions_len = self.body.transactions.len() as u64 + InherentFunction::count();
(transactions_len as u32).using_encoded(|s| v.extend(s));
let timestamp_set_tx = UncheckedTransaction::inherent(
InherentFunction::TimestampSet(self.body.timestamp)
);
v.extend(timestamp_set_tx.encode());
for non_inherent_transaction in &self.body.transactions {
v.extend(non_inherent_transaction.encode());
}
v
}
}
/// A relay chain block header.
///
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Header {
/// Block parent's hash.
pub parent_hash: HeaderHash,
/// Block number.
pub number: Number,
/// State root after this transition.
pub state_root: H256,
/// The root of the trie that represents this block's transactions, indexed by a 32-byte integer.
pub transaction_root: H256,
/// The digest of activity on the block.
pub digest: Digest,
}
impl Header {
/// Create a new instance with default fields except `number`, which is given as an argument.
pub fn from_block_number(number: Number) -> Self {
Header {
parent_hash: Default::default(),
number,
state_root: Default::default(),
transaction_root: Default::default(),
digest: Default::default(),
}
}
}
impl Slicable for Header {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Header {
parent_hash: try_opt!(Slicable::decode(input)),
number: try_opt!(Slicable::decode(input)),
state_root: try_opt!(Slicable::decode(input)),
transaction_root: try_opt!(Slicable::decode(input)),
digest: try_opt!(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.transaction_root.using_encoded(|s| v.extend(s));
self.digest.using_encoded(|s| v.extend(s));
v
}
}
#[cfg(test)]
mod tests {
use super::*;
use codec::Slicable;
use substrate_serializer as ser;
#[test]
fn test_header_serialization() {
let header = Header {
parent_hash: 5.into(),
number: 67,
state_root: 3.into(),
transaction_root: 6.into(),
digest: Digest { logs: vec![Log(vec![1])] },
};
assert_eq!(ser::to_string_pretty(&header), r#"{
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005",
"number": 67,
"stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003",
"transactionRoot": "0x0000000000000000000000000000000000000000000000000000000000000006",
"digest": {
"logs": [
"0x01"
]
}
}"#);
let v = header.encode();
assert_eq!(Header::decode(&mut &v[..]).unwrap(), header);
}
#[test]
fn block_encoding_round_trip() {
let mut block = Block {
header: Header::from_block_number(1),
body: Body {
timestamp: 100_000_000,
transactions: Vec::new(),
}
};
let raw = block.encode();
let decoded = Block::decode(&mut &raw[..]).unwrap();
assert_eq!(block, decoded);
block.body.transactions.push(UncheckedTransaction {
transaction: ::transaction::Transaction {
function: Function::StakingStake,
signed: Default::default(),
nonce: 10101,
},
signature: Default::default(),
});
let raw = block.encode();
let decoded = Block::decode(&mut &raw[..]).unwrap();
assert_eq!(block, decoded);
}
#[test]
fn block_encoding_substrate_round_trip() {
let mut block = Block {
header: Header::from_block_number(1),
body: Body {
timestamp: 100_000_000,
transactions: Vec::new(),
}
};
block.body.transactions.push(UncheckedTransaction {
transaction: ::transaction::Transaction {
function: Function::StakingStake,
signed: Default::default(),
nonce: 10101,
},
signature: Default::default(),
});
let raw = block.encode();
let decoded_substrate = ::primitives::block::Block::decode(&mut &raw[..]).unwrap();
let encoded_substrate = decoded_substrate.encode();
let decoded = Block::decode(&mut &encoded_substrate[..]).unwrap();
assert_eq!(block, decoded);
}
#[test]
fn decode_body_without_inherents_fails() {
let substrate_blank = ::primitives::block::Block {
header: ::primitives::block::Header::from_block_number(1),
transactions: Vec::new(),
};
let encoded_substrate = substrate_blank.encode();
assert!(Block::decode(&mut &encoded_substrate[..]).is_none());
}
#[test]
fn inherent_transactions_iter_contains_all_inherent() {
let block = Block {
header: Header::from_block_number(1),
body: Body {
timestamp: 10101,
transactions: Vec::new(),
}
};
let mut iter = block.inherent_transactions();
assert_eq!(InherentFunction::count(), 1); // following depends on this assertion.
assert_eq!(iter.next().unwrap(), UncheckedTransaction::inherent(InherentFunction::TimestampSet(10101)));
assert!(iter.next().is_none());
}
}
+13 -22
View File
@@ -21,7 +21,6 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
@@ -30,34 +29,29 @@ extern crate serde;
extern crate substrate_runtime_std as rstd;
extern crate substrate_primitives as primitives;
extern crate substrate_runtime_primitives as runtime_primitives;
#[cfg(test)]
extern crate substrate_serializer;
extern crate substrate_codec as codec;
macro_rules! try_opt {
($e: expr) => {
match $e {
Some(x) => x,
None => return None,
}
}
}
pub mod parachain;
pub mod validator;
pub mod block;
pub mod transaction;
pub use self::block::{Header, Body, Block, Log, Digest};
pub use self::block::Number as BlockNumber;
pub use self::transaction::{Transaction, UncheckedTransaction, Function, InherentFunction, Proposal};
/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody
/// (who matters). Essentially this means that a majority of validators have decided it is
/// "correct".
pub const EVERYBODY: AccountId = [255u8; 32];
/// Something that identifies a block.
pub use primitives::block::Id as BlockId;
/// The type of digest item.
pub use primitives::block::Log as Log;
/// An index to a block.
pub type BlockNumber = u64;
/// Alias to Ed25519 pubkey that identifies an account on the relay chain. This will almost
/// certainly continue to be the same as the substrate's `AuthorityId`.
pub type AccountId = primitives::AuthorityId;
@@ -67,22 +61,19 @@ pub type AccountId = primitives::AuthorityId;
pub type SessionKey = primitives::AuthorityId;
/// Indentifier for a chain.
pub type ChainID = u64;
pub type ChainId = u64;
/// Index of a transaction in the relay chain.
pub type TxOrder = u64;
pub type Index = u64;
/// A hash of some data used by the relay chain.
pub type Hash = primitives::H256;
/// Alias to 512-bit hash when used in the context of a signature on the relay chain.
pub type Signature = primitives::hash::H512;
pub type Signature = runtime_primitives::Ed25519Signature;
/// A timestamp: seconds since the unix epoch.
pub type Timestamp = u64;
/// The balance of an account.
pub type Balance = u64;
/// The amount of bonding period left in an account. Measured in eras.
pub type Bondage = u64;
+21 -21
View File
@@ -26,7 +26,7 @@ use ::Hash;
/// Unique identifier of a parachain.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct Id(u32);
impl From<Id> for u32 {
@@ -63,7 +63,7 @@ impl Slicable for Chain {
match disc {
0 => Some(Chain::Relay),
1 => Some(Chain::Parachain(try_opt!(Slicable::decode(input)))),
1 => Some(Chain::Parachain(Slicable::decode(input)?)),
_ => None,
}
}
@@ -102,8 +102,8 @@ pub struct DutyRoster {
impl Slicable for DutyRoster {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(DutyRoster {
validator_duty: try_opt!(Slicable::decode(input)),
guarantor_duty: try_opt!(Slicable::decode(input)),
validator_duty: Slicable::decode(input)?,
guarantor_duty: Slicable::decode(input)?,
})
}
@@ -123,7 +123,7 @@ impl Slicable for DutyRoster {
/// Extrinsic data for a parachain.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Extrinsic;
@@ -132,7 +132,7 @@ pub struct Extrinsic;
///
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Candidate {
@@ -150,7 +150,7 @@ pub struct Candidate {
/// Candidate receipt type.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
#[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 CandidateReceipt {
@@ -184,12 +184,12 @@ impl Slicable for CandidateReceipt {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(CandidateReceipt {
parachain_index: try_opt!(Slicable::decode(input)),
collator: try_opt!(Slicable::decode(input)),
head_data: try_opt!(Slicable::decode(input).map(HeadData)),
balance_uploads: try_opt!(Slicable::decode(input)),
egress_queue_roots: try_opt!(Slicable::decode(input)),
fees: try_opt!(Slicable::decode(input)),
parachain_index: Slicable::decode(input)?,
collator: Slicable::decode(input)?,
head_data: Slicable::decode(input).map(HeadData)?,
balance_uploads: Slicable::decode(input)?,
egress_queue_roots: Slicable::decode(input)?,
fees: Slicable::decode(input)?,
})
}
}
@@ -219,7 +219,7 @@ impl Ord for CandidateReceipt {
/// Parachain ingress queue message.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Consolidated ingress queue data.
@@ -227,34 +227,34 @@ pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>
/// This is just an ordered vector of other parachains' egress queues,
/// obtained according to the routing rules.
#[derive(Default, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct ConsolidatedIngress(pub Vec<(Id, Vec<Message>)>);
/// Parachain block data.
///
/// contains everything required to validate para-block, may contain block and witness data
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain header raw bytes wrapper type.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain head data included in the chain.
#[derive(PartialEq, Eq, Clone, PartialOrd, Ord)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain validation code.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Activitiy bit field
#[derive(PartialEq, Eq, Clone, Default)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Activity {
@@ -344,7 +344,7 @@ mod tests {
fn test_candidate() {
assert_eq!(ser::to_string_pretty(&Candidate {
parachain_index: 5.into(),
collator_signature: 10.into(),
collator_signature: primitives::hash::H512::from(10).into(),
unprocessed_ingress: ConsolidatedIngress(vec![
(Id(1), vec![Message(vec![2])]),
(Id(2), vec![Message(vec![2]), Message(vec![3])]),
@@ -1,487 +0,0 @@
// Copyright 2017 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Transaction type.
use rstd::vec::Vec;
use codec::{Input, Slicable};
use primitives::bft::MisbehaviorReport;
use ::Signature;
#[cfg(feature = "std")]
use std::fmt;
use block::Number as BlockNumber;
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[repr(u8)]
enum InternalFunctionId {
/// Set the system's code.
SystemSetCode = 0x00,
/// Set the session length.
SessionSetLength = 0x10,
/// Force a new session.
SessionForceNewSession = 0x11,
/// Set the number of sessions per era.
StakingSetSessionsPerEra = 0x20,
/// Set the minimum bonding duration for staking.
StakingSetBondingDuration = 0x21,
/// Set the validator count for staking.
StakingSetValidatorCount = 0x22,
/// Force a new staking era.
StakingForceNewEra = 0x23,
/// Set the per-mille of validator approval required for governance changes.
GovernanceSetApprovalPpmRequired = 0x30,
}
impl InternalFunctionId {
/// Derive `Some` value from a `u8`, or `None` if it's invalid.
fn from_u8(value: u8) -> Option<InternalFunctionId> {
let functions = [
InternalFunctionId::SystemSetCode,
InternalFunctionId::SessionSetLength,
InternalFunctionId::SessionForceNewSession,
InternalFunctionId::StakingSetSessionsPerEra,
InternalFunctionId::StakingSetBondingDuration,
InternalFunctionId::StakingSetValidatorCount,
InternalFunctionId::StakingForceNewEra,
InternalFunctionId::GovernanceSetApprovalPpmRequired,
];
functions.iter().map(|&f| f).find(|&f| value == f as u8)
}
}
/// Internal functions that can be dispatched to.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub enum Proposal {
/// Set the system's code.
SystemSetCode(Vec<u8>),
/// Set the session length.
SessionSetLength(BlockNumber),
/// Force a new session.
SessionForceNewSession,
/// Set the number of sessions per era.
StakingSetSessionsPerEra(BlockNumber),
/// Set the minimum bonding duration for staking.
StakingSetBondingDuration(BlockNumber),
/// Set the validator count for staking.
StakingSetValidatorCount(u32),
/// Force a new staking era.
StakingForceNewEra,
/// Set the per-mille of validator approval required for governance changes.
GovernanceSetApprovalPpmRequired(u32),
}
impl Slicable for Proposal {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
let id = InternalFunctionId::from_u8(input.read_byte()?)?;
let function = match id {
InternalFunctionId::SystemSetCode =>
Proposal::SystemSetCode(try_opt!(Slicable::decode(input))),
InternalFunctionId::SessionSetLength =>
Proposal::SessionSetLength(try_opt!(Slicable::decode(input))),
InternalFunctionId::SessionForceNewSession => Proposal::SessionForceNewSession,
InternalFunctionId::StakingSetSessionsPerEra =>
Proposal::StakingSetSessionsPerEra(try_opt!(Slicable::decode(input))),
InternalFunctionId::StakingSetBondingDuration =>
Proposal::StakingSetBondingDuration(try_opt!(Slicable::decode(input))),
InternalFunctionId::StakingSetValidatorCount =>
Proposal::StakingSetValidatorCount(try_opt!(Slicable::decode(input))),
InternalFunctionId::StakingForceNewEra => Proposal::StakingForceNewEra,
InternalFunctionId::GovernanceSetApprovalPpmRequired =>
Proposal::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::decode(input))),
};
Some(function)
}
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
match *self {
Proposal::SystemSetCode(ref data) => {
v.push(InternalFunctionId::SystemSetCode as u8);
data.using_encoded(|s| v.extend(s));
}
Proposal::SessionSetLength(ref data) => {
v.push(InternalFunctionId::SessionSetLength as u8);
data.using_encoded(|s| v.extend(s));
}
Proposal::SessionForceNewSession => {
v.push(InternalFunctionId::SessionForceNewSession as u8);
}
Proposal::StakingSetSessionsPerEra(ref data) => {
v.push(InternalFunctionId::StakingSetSessionsPerEra as u8);
data.using_encoded(|s| v.extend(s));
}
Proposal::StakingSetBondingDuration(ref data) => {
v.push(InternalFunctionId::StakingSetBondingDuration as u8);
data.using_encoded(|s| v.extend(s));
}
Proposal::StakingSetValidatorCount(ref data) => {
v.push(InternalFunctionId::StakingSetValidatorCount as u8);
data.using_encoded(|s| v.extend(s));
}
Proposal::StakingForceNewEra => {
v.push(InternalFunctionId::StakingForceNewEra as u8);
}
Proposal::GovernanceSetApprovalPpmRequired(ref data) => {
v.push(InternalFunctionId::GovernanceSetApprovalPpmRequired as u8);
data.using_encoded(|s| v.extend(s));
}
}
v
}
}
/// Public functions that can be dispatched to.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[repr(u8)]
enum FunctionId {
/// Set the timestamp.
TimestampSet = 0x00,
/// Set temporary session key as a validator.
SessionSetKey = 0x10,
/// Staking subsystem: begin staking.
StakingStake = 0x20,
/// Staking subsystem: stop staking.
StakingUnstake = 0x21,
/// Staking subsystem: transfer stake.
StakingTransfer = 0x22,
/// Report misbehavior.
StakingReportMisbehavior = 0x23,
/// Make a proposal for the governance system.
GovernancePropose = 0x30,
/// Approve a proposal for the governance system.
GovernanceApprove = 0x31,
}
impl FunctionId {
/// Derive `Some` value from a `u8`, or `None` if it's invalid.
fn from_u8(value: u8) -> Option<FunctionId> {
use self::*;
let functions = [
FunctionId::StakingStake,
FunctionId::StakingUnstake,
FunctionId::StakingTransfer,
FunctionId::StakingReportMisbehavior,
FunctionId::SessionSetKey,
FunctionId::TimestampSet,
FunctionId::GovernancePropose,
FunctionId::GovernanceApprove,
];
functions.iter().map(|&f| f).find(|&f| value == f as u8)
}
}
/// Inherent functions on the runtime.
/// These must be called each block by the `EVERYBODY` account.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub enum InherentFunction {
/// Set the timestamp.
TimestampSet(u64),
}
impl InherentFunction {
/// Get the number of inherent functions.
pub fn count() -> u64 {
1
}
/// Get the index.
pub fn index(&self) -> u64 {
match *self {
InherentFunction::TimestampSet(_) => 0,
}
}
}
/// Functions on the runtime.
#[derive(Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub enum Function {
/// An inherent function.
Inherent(InherentFunction),
/// Set temporary session key as a validator.
SessionSetKey(::SessionKey),
/// Staking subsystem: begin staking.
StakingStake,
/// Staking subsystem: stop staking.
StakingUnstake,
/// Staking subsystem: transfer stake.
StakingTransfer(::AccountId, u64),
/// Staking subsystem: report misbehavior of a validator.
ReportMisbehavior(MisbehaviorReport),
/// Make a proposal for the governance system.
GovernancePropose(Proposal),
/// Approve a proposal for the governance system.
GovernanceApprove(BlockNumber),
}
impl Function {
/// The number of inherent functions.
pub fn inherent_functions() -> u64 { InherentFunction::count() }
/// Whether this function is "inherent": that it must be part of every
/// block at the given index and no other.
///
/// Transactions containing inherent functions should not be signed.
pub fn is_inherent(&self) -> bool {
match *self {
Function::Inherent(_) => true,
_ => false,
}
}
/// If this function is inherent, returns the index it should occupy
/// in the block. Otherwise returns `None`.
pub fn inherent_index(&self) -> Option<u64> {
match *self {
Function::Inherent(ref inner) => Some(inner.index()),
_ => None,
}
}
}
impl Slicable for Function {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
let id = FunctionId::from_u8(input.read_byte()?)?;
Some(match id {
FunctionId::TimestampSet =>
Function::Inherent(InherentFunction::TimestampSet(try_opt!(Slicable::decode(input)))),
FunctionId::SessionSetKey =>
Function::SessionSetKey(try_opt!(Slicable::decode(input))),
FunctionId::StakingStake => Function::StakingStake,
FunctionId::StakingUnstake => Function::StakingUnstake,
FunctionId::StakingTransfer => {
let to = try_opt!(Slicable::decode(input));
let amount = try_opt!(Slicable::decode(input));
Function::StakingTransfer(to, amount)
}
FunctionId::StakingReportMisbehavior => Function::ReportMisbehavior(MisbehaviorReport::decode(input)?),
FunctionId::GovernancePropose =>
Function::GovernancePropose(try_opt!(Slicable::decode(input))),
FunctionId::GovernanceApprove =>
Function::GovernanceApprove(try_opt!(Slicable::decode(input))),
})
}
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
match *self {
Function::Inherent(InherentFunction::TimestampSet(ref data)) => {
v.push(FunctionId::TimestampSet as u8);
data.using_encoded(|s| v.extend(s));
}
Function::SessionSetKey(ref data) => {
v.push(FunctionId::SessionSetKey as u8);
data.using_encoded(|s| v.extend(s));
}
Function::StakingStake => {
v.push(FunctionId::StakingStake as u8);
}
Function::StakingUnstake => {
v.push(FunctionId::StakingUnstake as u8);
}
Function::ReportMisbehavior(ref report) => {
v.push(FunctionId::StakingReportMisbehavior as u8);
report.using_encoded(|s| v.extend(s));
}
Function::StakingTransfer(ref to, ref amount) => {
v.push(FunctionId::StakingTransfer as u8);
to.using_encoded(|s| v.extend(s));
amount.using_encoded(|s| v.extend(s));
}
Function::GovernancePropose(ref data) => {
v.push(FunctionId::GovernancePropose as u8);
data.using_encoded(|s| v.extend(s));
}
Function::GovernanceApprove(ref data) => {
v.push(FunctionId::GovernanceApprove as u8);
data.using_encoded(|s| v.extend(s));
}
}
v
}
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(self.encode().as_slice())
}
}
/// A vetted and verified transaction from the external world.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Transaction {
/// Who signed it (note this is not a signature).
pub signed: super::AccountId,
/// The number of transactions have come before from the same signer.
pub nonce: super::TxOrder,
/// The function that should be called.
pub function: Function,
}
impl Slicable for Transaction {
fn decode<I: Input>(input: &mut I) -> Option<Self> {
Some(Transaction {
signed: try_opt!(Slicable::decode(input)),
nonce: try_opt!(Slicable::decode(input)),
function: try_opt!(Slicable::decode(input)),
})
}
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
self.signed.using_encoded(|s| v.extend(s));
self.nonce.using_encoded(|s| v.extend(s));
self.function.using_encoded(|s| v.extend(s));
v
}
}
/// A transactions right from the external world. Unchecked.
#[derive(Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct UncheckedTransaction {
/// The actual transaction information.
pub transaction: Transaction,
/// The signature; should be an Ed25519 signature applied to the serialised `transaction` field.
pub signature: Signature,
}
impl UncheckedTransaction {
/// Whether the transaction is well-formed. In particular checks that
/// inherent transactions have the correct signed and signature fields.
///
/// Does not check signatures on other transactions.
pub fn is_well_formed(&self) -> bool {
if self.transaction.function.is_inherent() {
self.transaction.signed == ::EVERYBODY && self.signature == Signature::zero()
} else {
true
}
}
/// Whether this transaction invokes an inherent function.
pub fn is_inherent(&self) -> bool {
self.transaction.function.is_inherent()
}
/// Create a new inherent-style transaction from the given function.
pub fn inherent(function: InherentFunction) -> Self {
UncheckedTransaction {
transaction: Transaction {
function: Function::Inherent(function),
nonce: 0,
signed: ::EVERYBODY
},
signature: Signature::zero(),
}
}
}
impl Slicable for UncheckedTransaction {
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 = try_opt!(Slicable::decode(input));
Some(UncheckedTransaction {
transaction: try_opt!(Slicable::decode(input)),
signature: try_opt!(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.transaction.signed.using_encoded(|s| v.extend(s));
self.transaction.nonce.using_encoded(|s| v.extend(s));
self.transaction.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
}
}
impl PartialEq for UncheckedTransaction {
fn eq(&self, other: &Self) -> bool {
self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction
}
}
#[cfg(feature = "std")]
impl fmt::Debug for UncheckedTransaction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UncheckedTransaction({:?})", self.transaction)
}
}
#[cfg(test)]
mod tests {
use super::*;
use primitives;
use ::codec::Slicable;
use primitives::hexdisplay::HexDisplay;
#[test]
fn serialize_unchecked() {
let tx = UncheckedTransaction {
transaction: Transaction {
signed: [1; 32],
nonce: 999u64,
function: Function::Inherent(InherentFunction::TimestampSet(135135)),
},
signature: primitives::hash::H512([0; 64]),
};
// 71000000
// 0101010101010101010101010101010101010101010101010101010101010101
// e703000000000000
// 00
// df0f0200
// 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
let v = Slicable::encode(&tx);
println!("{}", HexDisplay::from(&v));
assert_eq!(UncheckedTransaction::decode(&mut &v[..]).unwrap(), tx);
}
}
@@ -23,22 +23,22 @@ use parachain;
/// Parachain outgoing message.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct EgressPost(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Balance upload.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct BalanceUpload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Balance download.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
pub struct BalanceDownload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// The result of parachain validation.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct ValidationResult {