Split out substrate-primitives from polkadot-primitives.

Bottom half minus tests builds.
This commit is contained in:
Gav
2018-02-07 15:24:54 +01:00
parent 26b4b56402
commit 9fe85fc9f4
50 changed files with 1102 additions and 928 deletions
@@ -18,11 +18,9 @@
#[cfg(feature = "std")]
use bytes;
use bytes::Vec;
use rstd::vec::Vec;
use codec::Slicable;
use hash::H256;
use parachain;
use relay::transaction::UncheckedTransaction;
/// Used to refer to a block number.
pub type Number = u64;
@@ -33,9 +31,26 @@ pub type HeaderHash = H256;
/// Hash used to refer to a transaction hash.
pub type TransactionHash = H256;
/// Simple generic transaction type.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Transaction(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl Slicable for Transaction {
fn from_slice(value: &mut &[u8]) -> Option<Self> {
Vec::<u8>::from_slice(value).map(Transaction)
}
fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.as_slice_then(f)
}
}
impl ::codec::NonTrivialSlicable for Transaction { }
/// Execution log (event)
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[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 {
@@ -51,8 +66,8 @@ impl Slicable for Log {
impl ::codec::NonTrivialSlicable for Log { }
/// The digest of a block, useful for light-clients.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[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>,
@@ -68,14 +83,14 @@ impl Slicable for Digest {
}
}
/// A Polkadot relay chain block.
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
/// A Substrate relay chain block.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct Block {
/// The block header.
pub header: Header,
/// All relay-chain transactions.
pub transactions: Vec<UncheckedTransaction>,
pub transactions: Vec<Transaction>,
}
impl Slicable for Block {
@@ -103,8 +118,8 @@ impl Slicable for Block {
/// A relay chain block header.
///
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[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 {
@@ -161,19 +176,6 @@ impl Slicable for Header {
}
}
/// A relay chain block body.
///
/// Included candidates should be sorted by parachain ID, and without duplicate
/// IDs.
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Body {
/// Parachain proposal blocks.
pub candidates: Vec<parachain::Candidate>,
}
#[cfg(test)]
mod tests {
use super::*;
@@ -205,28 +207,4 @@ mod tests {
let v = header.to_vec();
assert_eq!(Header::from_slice(&mut &v[..]).unwrap(), header);
}
#[test]
fn test_body_serialization() {
assert_eq!(ser::to_string_pretty(&Body {
candidates: vec![
parachain::Candidate {
parachain_index: 10.into(),
collator_signature: Default::default(),
unprocessed_ingress: Default::default(),
block: ::parachain::BlockData(vec![1, 3, 5, 8]),
}
],
}), r#"{
"candidates": [
{
"parachainIndex": 10,
"collatorSignature": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"unprocessedIngress": [],
"block": "0x01030508"
}
]
}"#);
}
}
+4 -1
View File
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Simply type for representing Vec<u8> with regards to serde.
use core::fmt;
use serde::{de, Serializer, Deserializer};
@@ -60,7 +62,8 @@ pub fn serialize_uint<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
}
/// Expected length of bytes vector.
#[derive(Debug, PartialEq, Eq)]
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ExpectedLen {
/// Any length in bytes.
#[cfg_attr(not(feature = "std"), allow(unused))]
+8 -4
View File
@@ -16,18 +16,22 @@
//! A fixed hash type.
#[cfg(feature = "std")]
use serde::{Serialize, Serializer, Deserialize, Deserializer};
#[cfg(feature = "std")]
use bytes;
macro_rules! impl_serde {
macro_rules! impl_rest {
($name: ident, $len: expr) => {
#[cfg(feature = "std")]
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
bytes::serialize(&self.0, serializer)
}
}
#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Exact($len))
@@ -48,11 +52,11 @@ macro_rules! impl_serde {
}
construct_hash!(H160, 20);
impl_serde!(H160, 20);
construct_hash!(H256, 32);
impl_serde!(H256, 32);
construct_hash!(H512, 64);
impl_serde!(H512, 64);
impl_rest!(H160, 20);
impl_rest!(H256, 32);
impl_rest!(H512, 64);
#[cfg(test)]
mod tests {
+30 -27
View File
@@ -22,38 +22,37 @@
#![cfg_attr(not(feature = "std"), feature(alloc))]
extern crate rustc_hex;
extern crate serde;
extern crate byteorder;
#[cfg(feature = "std")]
extern crate twox_hash;
#[cfg(feature = "std")]
extern crate blake2_rfc;
#[macro_use]
extern crate crunchy;
#[macro_use]
extern crate fixed_hash;
#[macro_use]
extern crate uint as uint_crate;
extern crate substrate_codec as codec;
#[cfg(feature = "std")]
extern crate serde;
#[cfg(feature = "std")]
extern crate twox_hash;
#[cfg(feature = "std")]
extern crate blake2_rfc;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate uint as uint_crate;
#[cfg(feature = "std")]
extern crate core;
extern crate substrate_codec as codec;
#[macro_use]
extern crate substrate_runtime_std as rstd;
#[cfg(test)]
extern crate substrate_serializer;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
// TODO: factor out to separate crate.
macro_rules! try_opt {
($e: expr) => {
@@ -64,23 +63,27 @@ macro_rules! try_opt {
}
}
mod bytes;
pub mod contract;
pub mod hash;
#[cfg(feature = "std")]
pub mod bytes;
#[cfg(feature = "std")]
pub mod hashing;
#[cfg(feature = "std")]
pub use hashing::{blake2_256, twox_128, twox_256};
#[cfg(feature = "std")]
pub mod hexdisplay;
pub mod parachain;
pub mod relay;
pub mod storage;
pub mod hash;
pub mod uint;
pub mod validator;
pub mod block;
#[cfg(test)]
mod tests;
#[cfg(feature = "std")]
pub mod hashing;
pub use self::hash::{H160, H256};
pub use self::uint::{U256, U512};
#[cfg(feature = "std")]
pub use hashing::{blake2_256, twox_128, twox_256};
pub use block::{Block, Header};
/// An identifier for an authority in the consensus algorithm. The same as ed25519::Public.
pub type AuthorityId = [u8; 32];
-172
View File
@@ -1,172 +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/>.
//! Parachain data types.
#[cfg(feature = "std")]
use bytes;
use bytes::Vec;
/// Unique identifier of a parachain.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Id(u64);
impl From<Id> for u64 {
fn from(x: Id) -> Self { x.0 }
}
impl From<u64> for Id {
fn from(x: u64) -> Self { Id(x) }
}
impl ::codec::Slicable for Id {
fn from_slice(value: &mut &[u8]) -> Option<Self> {
u64::from_slice(value).map(Id)
}
fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.as_slice_then(f)
}
}
/// Candidate parachain block.
///
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct Candidate {
/// The ID of the parachain this is a proposal for.
pub parachain_index: Id,
/// Collator's signature
pub collator_signature: ::relay::Signature,
/// Unprocessed ingress queue.
///
/// Ordered by parachain ID and block number.
pub unprocessed_ingress: ConsolidatedIngress,
/// Block data
pub block: BlockData,
}
/// Candidate receipt type.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct CandidateReceipt {
/// The ID of the parachain this is a candidate for.
pub parachain_index: Id,
/// The collator's relay-chain account ID
pub collator: ::relay::AccountId,
/// The head-data
pub head_data: HeadData,
/// Balance uploads to the relay chain.
pub balance_uploads: Vec<(::relay::AccountId, ::uint::U256)>,
/// Egress queue roots.
pub egress_queue_roots: Vec<(Id, ::hash::H256)>,
/// Fees paid from the chain to the relay chain validators
pub fees: ::uint::U256,
}
/// Parachain ingress queue message.
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Consolidated ingress queue data.
///
/// This is just an ordered vector of other parachains' egress queues,
/// obtained according to the routing rules.
#[derive(Debug, Default, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
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(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain header raw bytes wrapper type.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain head data included in the chain.
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Parachain validation code.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Activitiy bit field
#[derive(Debug, PartialEq, Eq, Clone, Default)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
impl ::codec::Slicable for Activity {
fn from_slice(value: &mut &[u8]) -> Option<Self> {
Vec::<u8>::from_slice(value).map(Activity)
}
fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.as_slice_then(f)
}
}
#[cfg(test)]
mod tests {
use super::*;
use substrate_serializer as ser;
#[test]
fn test_candidate() {
assert_eq!(ser::to_string_pretty(&Candidate {
parachain_index: 5.into(),
collator_signature: 10.into(),
unprocessed_ingress: ConsolidatedIngress(vec![
(Id(1), vec![Message(vec![2])]),
(Id(2), vec![Message(vec![2]), Message(vec![3])]),
]),
block: BlockData(vec![1, 2, 3]),
}), r#"{
"parachainIndex": 5,
"collatorSignature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a",
"unprocessedIngress": [
[
1,
[
"0x02"
]
],
[
2,
[
"0x02",
"0x03"
]
]
],
"block": "0x010203"
}"#);
}
}
-33
View File
@@ -1,33 +0,0 @@
//! Relay chain primitives.
pub mod block;
pub mod transaction;
pub use self::block::*;
pub use self::transaction::*;
pub use self::block::Number as BlockNumber;
/// 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];
/// Alias to Ed25519 pubkey that identifies an account on the relay chain.
pub type AccountId = [u8; 32];
/// The Ed25519 pub key of an session that belongs to an authority of the relay chain. This is
/// used as what the external environment/consensus algorithm calls an "authority".
pub type SessionKey = AccountId;
/// Indentifier for a chain.
pub type ChainID = u64;
/// Index of a transaction in the relay chain.
pub type TxOrder = u64;
/// A hash of some data used by the relay chain.
pub type Hash = ::hash::H256;
/// Alias to 520-bit hash when used in the context of a signature on the relay chain.
pub type Signature = ::hash::H512;
@@ -1,389 +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 bytes::Vec;
use codec::Slicable;
#[cfg(feature = "std")]
use std::fmt;
#[cfg(not(feature = "std"))]
use alloc::fmt;
use relay::block::Number as BlockNumber;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[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(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum InternalFunction {
/// 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),
}
/// An internal function.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Proposal {
/// The privileged function to call.
pub function: InternalFunction,
}
impl Slicable for Proposal {
fn from_slice(value: &mut &[u8]) -> Option<Self> {
let id = try_opt!(u8::from_slice(value).and_then(InternalFunctionId::from_u8));
let function = match id {
InternalFunctionId::SystemSetCode =>
InternalFunction::SystemSetCode(try_opt!(Slicable::from_slice(value))),
InternalFunctionId::SessionSetLength =>
InternalFunction::SessionSetLength(try_opt!(Slicable::from_slice(value))),
InternalFunctionId::SessionForceNewSession => InternalFunction::SessionForceNewSession,
InternalFunctionId::StakingSetSessionsPerEra =>
InternalFunction::StakingSetSessionsPerEra(try_opt!(Slicable::from_slice(value))),
InternalFunctionId::StakingSetBondingDuration =>
InternalFunction::StakingSetBondingDuration(try_opt!(Slicable::from_slice(value))),
InternalFunctionId::StakingSetValidatorCount =>
InternalFunction::StakingSetValidatorCount(try_opt!(Slicable::from_slice(value))),
InternalFunctionId::StakingForceNewEra => InternalFunction::StakingForceNewEra,
InternalFunctionId::GovernanceSetApprovalPpmRequired =>
InternalFunction::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::from_slice(value))),
};
Some(Proposal { function })
}
fn to_vec(&self) -> Vec<u8> {
let mut v = Vec::new();
match self.function {
InternalFunction::SystemSetCode(ref data) => {
(InternalFunctionId::SystemSetCode as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
InternalFunction::SessionSetLength(ref data) => {
(InternalFunctionId::SessionSetLength as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
InternalFunction::SessionForceNewSession => {
(InternalFunctionId::SessionForceNewSession as u8).as_slice_then(|s| v.extend(s));
}
InternalFunction::StakingSetSessionsPerEra(ref data) => {
(InternalFunctionId::StakingSetSessionsPerEra as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
InternalFunction::StakingSetBondingDuration(ref data) => {
(InternalFunctionId::StakingSetBondingDuration as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
InternalFunction::StakingSetValidatorCount(ref data) => {
(InternalFunctionId::StakingSetValidatorCount as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
InternalFunction::StakingForceNewEra => {
(InternalFunctionId::StakingForceNewEra as u8).as_slice_then(|s| v.extend(s));
}
InternalFunction::GovernanceSetApprovalPpmRequired(ref data) => {
(InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
}
v
}
fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(self.to_vec().as_slice())
}
}
/// Public functions that can be dispatched to.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[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,
/// 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::SessionSetKey, FunctionId::TimestampSet,
FunctionId::GovernancePropose, FunctionId::GovernanceApprove];
functions.iter().map(|&f| f).find(|&f| value == f as u8)
}
}
/// Functions on the runtime.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub enum Function {
/// Set the timestamp.
TimestampSet(u64),
/// Set temporary session key as a validator.
SessionSetKey(::relay::SessionKey),
/// Staking subsystem: begin staking.
StakingStake,
/// Staking subsystem: stop staking.
StakingUnstake,
/// Staking subsystem: transfer stake.
StakingTransfer(::relay::AccountId, u64),
/// Make a proposal for the governance system.
GovernancePropose(Proposal),
/// Approve a proposal for the governance system.
GovernanceApprove(BlockNumber),
}
impl Slicable for Function {
fn from_slice(value: &mut &[u8]) -> Option<Self> {
let id = try_opt!(u8::from_slice(value).and_then(FunctionId::from_u8));
Some(match id {
FunctionId::TimestampSet =>
Function::TimestampSet(try_opt!(Slicable::from_slice(value))),
FunctionId::SessionSetKey =>
Function::SessionSetKey(try_opt!(Slicable::from_slice(value))),
FunctionId::StakingStake => Function::StakingStake,
FunctionId::StakingUnstake => Function::StakingUnstake,
FunctionId::StakingTransfer => {
let to = try_opt!(Slicable::from_slice(value));
let amount = try_opt!(Slicable::from_slice(value));
Function::StakingTransfer(to, amount)
}
FunctionId::GovernancePropose =>
Function::GovernancePropose(try_opt!(Slicable::from_slice(value))),
FunctionId::GovernanceApprove =>
Function::GovernanceApprove(try_opt!(Slicable::from_slice(value))),
})
}
fn to_vec(&self) -> Vec<u8> {
let mut v = Vec::new();
match *self {
Function::TimestampSet(ref data) => {
(FunctionId::TimestampSet as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
Function::SessionSetKey(ref data) => {
(FunctionId::SessionSetKey as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
Function::StakingStake => {
(FunctionId::StakingStake as u8).as_slice_then(|s| v.extend(s));
}
Function::StakingUnstake => {
(FunctionId::StakingUnstake as u8).as_slice_then(|s| v.extend(s));
}
Function::StakingTransfer(ref to, ref amount) => {
(FunctionId::StakingTransfer as u8).as_slice_then(|s| v.extend(s));
to.as_slice_then(|s| v.extend(s));
amount.as_slice_then(|s| v.extend(s));
}
Function::GovernancePropose(ref data) => {
(FunctionId::GovernancePropose as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
Function::GovernanceApprove(ref data) => {
(FunctionId::GovernanceApprove as u8).as_slice_then(|s| v.extend(s));
data.as_slice_then(|s| v.extend(s));
}
}
v
}
fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(self.to_vec().as_slice())
}
}
/// A vetted and verified transaction from the external world.
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
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 from_slice(value: &mut &[u8]) -> Option<Self> {
Some(Transaction {
signed: try_opt!(Slicable::from_slice(value)),
nonce: try_opt!(Slicable::from_slice(value)),
function: try_opt!(Slicable::from_slice(value)),
})
}
fn to_vec(&self) -> Vec<u8> {
let mut v = Vec::new();
self.signed.as_slice_then(|s| v.extend(s));
self.nonce.as_slice_then(|s| v.extend(s));
self.function.as_slice_then(|s| v.extend(s));
v
}
fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(self.to_vec().as_slice())
}
}
/// 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: super::Signature,
}
impl Slicable for UncheckedTransaction {
fn from_slice(value: &mut &[u8]) -> Option<Self> {
Some(UncheckedTransaction {
transaction: try_opt!(Transaction::from_slice(value)),
signature: try_opt!(Slicable::from_slice(value)),
})
}
fn to_vec(&self) -> Vec<u8> {
let mut v = Vec::new();
self.transaction.signed.as_slice_then(|s| v.extend(s));
self.transaction.nonce.as_slice_then(|s| v.extend(s));
self.transaction.function.as_slice_then(|s| v.extend(s));
self.signature.as_slice_then(|s| v.extend(s));
v
}
fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
f(self.to_vec().as_slice())
}
}
impl ::codec::NonTrivialSlicable for UncheckedTransaction {}
impl PartialEq for UncheckedTransaction {
fn eq(&self, other: &Self) -> bool {
self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction
}
}
impl fmt::Debug for UncheckedTransaction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "UncheckedTransaction({:?})", self.transaction)
}
}
#[cfg(test)]
mod tests {
use ::codec::Slicable;
use super::*;
#[test]
fn serialize_unchecked() {
let tx = UncheckedTransaction {
transaction: Transaction {
signed: [1; 32],
nonce: 999u64,
function: Function::TimestampSet(135135),
},
signature: ::hash::H512([0; 64]),
};
let v = Slicable::to_vec(&tx);
assert_eq!(UncheckedTransaction::from_slice(&mut &v[..]).unwrap(), tx);
}
}
@@ -18,14 +18,14 @@
#[cfg(feature = "std")]
use bytes;
use bytes::Vec;
use rstd::vec::Vec;
/// Contract storage key.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct StorageKey(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Contract storage entry data.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
pub struct StorageData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
-212
View File
@@ -15,215 +15,3 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Tests.
use codec::Slicable;
use relay::{AccountId, Block, Header, Digest, Log, UncheckedTransaction, Transaction, Function};
#[test]
fn serialise_transaction_works() {
let one: AccountId = [1u8; 32];
let two: AccountId = [2u8; 32];
let tx = Transaction {
signed: one.clone(),
nonce: 69,
function: Function::StakingTransfer(two, 69),
};
let serialised = tx.to_vec();
assert_eq!(serialised, vec![
1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
69, 0, 0, 0, 0, 0, 0, 0,
34,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
69, 0, 0, 0, 0, 0, 0, 0
]);
}
#[test]
fn deserialise_transaction_works() {
let one: AccountId = [1u8; 32];
let two: AccountId = [2u8; 32];
let tx = Transaction {
signed: one.clone(),
nonce: 69,
function: Function::StakingTransfer(two, 69),
};
let data = [
1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
69, 0, 0, 0, 0, 0, 0, 0,
34,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
69, 0, 0, 0, 0, 0, 0, 0
];
let deserialised = Transaction::from_slice(&mut &data[..]).unwrap();
assert_eq!(deserialised, tx);
}
#[test]
fn serialise_header_works() {
let h = Header {
parent_hash: [4u8; 32].into(),
number: 42,
state_root: [5u8; 32].into(),
transaction_root: [6u8; 32].into(),
digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], },
};
let serialised = h.to_vec();
assert_eq!(serialised, vec![
4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
42, 0, 0, 0, 0, 0, 0, 0,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2, 0, 0, 0,
7, 0, 0, 0,
111, 110, 101, 32, 108, 111, 103,
11, 0, 0, 0,
97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103
]);
}
#[test]
fn deserialise_header_works() {
let h = Header {
parent_hash: [4u8; 32].into(),
number: 42,
state_root: [5u8; 32].into(),
transaction_root: [6u8; 32].into(),
digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], },
};
let data = [
4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
42, 0, 0, 0, 0, 0, 0, 0,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2, 0, 0, 0,
7, 0, 0, 0,
111, 110, 101, 32, 108, 111, 103,
11, 0, 0, 0,
97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103
];
let deserialised = Header::from_slice(&mut &data[..]).unwrap();
assert_eq!(deserialised, h);
}
#[test]
fn serialise_block_works() {
let one: AccountId = [1u8; 32];
let two: AccountId = [2u8; 32];
let tx1 = UncheckedTransaction {
transaction: Transaction {
signed: one.clone(),
nonce: 69,
function: Function::StakingTransfer(two, 69),
},
signature: [1u8; 64].into(),
};
let tx2 = UncheckedTransaction {
transaction: Transaction {
signed: two.clone(),
nonce: 42,
function: Function::StakingStake,
},
signature: [2u8; 64].into(),
};
let h = Header {
parent_hash: [4u8; 32].into(),
number: 42,
state_root: [5u8; 32].into(),
transaction_root: [6u8; 32].into(),
digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], },
};
let b = Block {
header: h,
transactions: vec![tx1, tx2],
};
let serialised = b.to_vec();
assert_eq!(serialised, vec![
// header
4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
42, 0, 0, 0, 0, 0, 0, 0,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2, 0, 0, 0,
7, 0, 0, 0,
111, 110, 101, 32, 108, 111, 103,
11, 0, 0, 0,
97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103,
// transactions
2, 0, 0, 0,
// tx1
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
69, 0, 0, 0, 0, 0, 0, 0,
34,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
69, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// tx2
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
42, 0, 0, 0, 0, 0, 0, 0,
32,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
]);
}
#[test]
fn deserialise_block_works() {
let one: AccountId = [1u8; 32];
let two: AccountId = [2u8; 32];
let tx1 = UncheckedTransaction {
transaction: Transaction {
signed: one.clone(),
nonce: 69,
function: Function::StakingTransfer(two, 69),
},
signature: [1u8; 64].into(),
};
let tx2 = UncheckedTransaction {
transaction: Transaction {
signed: two.clone(),
nonce: 42,
function: Function::StakingStake,
},
signature: [2u8; 64].into(),
};
let h = Header {
parent_hash: [4u8; 32].into(),
number: 42,
state_root: [5u8; 32].into(),
transaction_root: [6u8; 32].into(),
digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], },
};
let b = Block {
header: h,
transactions: vec![tx1, tx2],
};
let data = [
// header
4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
42, 0, 0, 0, 0, 0, 0, 0,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2, 0, 0, 0,
7, 0, 0, 0,
111, 110, 101, 32, 108, 111, 103,
11, 0, 0, 0,
97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103,
// transactions
2, 0, 0, 0,
// tx1
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
69, 0, 0, 0, 0, 0, 0, 0,
34,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
69, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// tx2
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
42, 0, 0, 0, 0, 0, 0, 0,
32,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
];
let deserialised = Block::from_slice(&mut &data[..]).unwrap();
assert_eq!(deserialised, b);
}
+5 -1
View File
@@ -16,12 +16,15 @@
//! An unsigned fixed-size integer.
#[cfg(feature = "std")]
use serde::{Serialize, Serializer, Deserialize, Deserializer};
#[cfg(feature = "std")]
use bytes;
macro_rules! impl_serde {
($name: ident, $len: expr) => {
#[cfg(feature = "std")]
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
let mut bytes = [0u8; $len * 8];
@@ -30,6 +33,7 @@ macro_rules! impl_serde {
}
}
#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Between(0, $len * 8))
@@ -40,8 +44,8 @@ macro_rules! impl_serde {
}
construct_uint!(U256, 4);
impl_serde!(U256, 4);
construct_uint!(U512, 8);
impl_serde!(U256, 4);
impl_serde!(U512, 8);
#[cfg(test)]
-76
View File
@@ -1,76 +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/>.
//! Validator primitives.
#[cfg(feature = "std")]
use bytes;
use bytes::Vec;
use parachain;
/// Parachain outgoing message.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct EgressPost(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Balance upload.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct BalanceUpload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// Balance download.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct BalanceDownload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
/// The result of parachain validation.
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
#[cfg_attr(feature = "std", serde(deny_unknown_fields))]
pub struct ValidationResult {
/// New head data that should be included in the relay chain state.
pub head_data: parachain::HeadData,
/// Outgoing messages (a vec for each parachain).
pub egress_queues: Vec<Vec<EgressPost>>,
/// Balance uploads
pub balance_uploads: Vec<BalanceUpload>,
}
#[cfg(test)]
mod tests {
use super::*;
use substrate_serializer as ser;
#[test]
fn test_validation_result() {
assert_eq!(ser::to_string_pretty(&ValidationResult {
head_data: parachain::HeadData(vec![1]),
egress_queues: vec![vec![EgressPost(vec![1])]],
balance_uploads: vec![BalanceUpload(vec![2])],
}), r#"{
"headData": "0x01",
"egressQueues": [
[
"0x01"
]
],
"balanceUploads": [
"0x02"
]
}"#);
}
}