integrate new primitives with native-runtime

This commit is contained in:
Robert Habermeier
2018-02-05 17:40:49 +01:00
parent 2bc7c57359
commit b58df7892f
31 changed files with 179 additions and 976 deletions
+2
View File
@@ -817,6 +817,7 @@ name = "native-runtime"
version = "0.1.0"
dependencies = [
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"polkadot-primitives 0.1.0",
"polkadot-runtime-codec 0.1.0",
"polkadot-runtime-std 0.1.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1100,6 +1101,7 @@ version = "0.1.0"
dependencies = [
"environmental 0.1.0",
"polkadot-primitives 0.1.0",
"polkadot-runtime-codec 0.1.0",
"polkadot-state-machine 0.1.0",
"pwasm-alloc 0.1.0",
"pwasm-libc 0.1.0",
+2 -2
View File
@@ -115,8 +115,8 @@ impl<B, E> Client<B, E> where
parent_hash: Default::default(),
number: 0,
state_root: Default::default(),
parachain_activity: Default::default(),
logs: Default::default(),
transaction_root: Default::default(),
digest: Default::default(),
};
let mut tx = backend.begin_transaction(BlockId::Hash(block::HeaderHash::default()))?;
+2 -1
View File
@@ -6,9 +6,10 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" }
polkadot-runtime-std = { path = "../runtime-std", version = "0.1" }
polkadot-primitives = { path = "../primitives", version = "0.1" }
rustc-hex = "1.0"
hex-literal = "0.1.0"
[features]
default = ["std"]
std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std"]
std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std", "polkadot-primitives/std"]
+2 -2
View File
@@ -18,7 +18,7 @@
use std::borrow::Borrow;
use primitives::parachain::Id as ParachainId;
use primitives::Address;
use primitives::AccountId;
use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body};
use service::Role as RoleFlags;
@@ -150,7 +150,7 @@ pub struct Status {
/// Signatue of `best_hash` made with validator address. Required for the validator role.
pub validator_signature: Option<Signature>,
/// Validator address. Required for the validator role.
pub validator_id: Option<Address>,
pub validator_id: Option<AccountId>,
/// Parachain id. Required for the collator role.
pub parachain_id: Option<ParachainId>,
}
+1 -1
View File
@@ -229,7 +229,7 @@ mod test {
let pair = Pair::from_seed(b"12345678901234567890123456789012");
let public = pair.public();
assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into());
let message: Vec<u8> = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap();
let message: Vec<u8> = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee000000000000000002d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap();
let signature = pair.sign(&message[..]);
assert!(signature.verify(&message[..], &public));
}
+1 -1
View File
@@ -101,7 +101,7 @@ pub type BlockNumber = u64;
pub type TxOrder = u64;
/// A hash of some data.
pub type Hash = [u8; 32];
pub type Hash = hash::H256;
/// Alias to 520-bit hash when used in the context of a signature.
pub type Signature = hash::H512;
+48 -11
View File
@@ -16,7 +16,7 @@
//! Transaction type.
use bytes::{self, Vec};
use bytes::Vec;
use codec::Slicable;
use runtime_function::Function;
@@ -35,9 +35,30 @@ pub struct Transaction {
pub nonce: ::TxOrder,
/// The function that should be called.
pub function: Function,
/// Serialised input data to the function.
#[serde(with = "bytes")]
pub input_data: Vec<u8>,
}
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.
@@ -52,12 +73,7 @@ pub struct UncheckedTransaction {
impl Slicable for UncheckedTransaction {
fn from_slice(value: &mut &[u8]) -> Option<Self> {
Some(UncheckedTransaction {
transaction: Transaction {
signed: try_opt!(Slicable::from_slice(value)),
nonce: try_opt!(Slicable::from_slice(value)),
function: try_opt!(Slicable::from_slice(value)),
input_data: try_opt!(Slicable::from_slice(value)),
},
transaction: try_opt!(Transaction::from_slice(value)),
signature: try_opt!(Slicable::from_slice(value)),
})
}
@@ -68,7 +84,6 @@ impl Slicable for UncheckedTransaction {
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.transaction.input_data.as_slice_then(|s| v.extend(s));
self.signature.as_slice_then(|s| v.extend(s));
v
@@ -92,3 +107,25 @@ impl fmt::Debug for UncheckedTransaction {
write!(f, "UncheckedTransaction({:?})", self.transaction)
}
}
#[cfg(test)]
mod tests {
use ::codec::Slicable;
use runtime_function::Function;
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);
}
}
+2 -2
View File
@@ -28,8 +28,8 @@ fn should_return_header() {
parent_hash: 0.into(),
number: 0,
state_root: 0.into(),
parachain_activity: Default::default(),
logs: vec![],
transaction_root: Default::default(),
digest: Default::default(),
}
);
+2 -1
View File
@@ -13,10 +13,11 @@ pwasm-libc = { path = "../wasm-runtime/pwasm-libc", version = "0.1" }
environmental = { path = "../environmental", version = "0.1", optional = true }
polkadot-state-machine = { path = "../state-machine", version = "0.1", optional = true }
polkadot-primitives = { path = "../primitives", version = "0.1", default_features = false }
polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1", default_features = false }
triehash = { version = "0.1", optional = true }
[features]
default = ["std"]
std = ["environmental", "polkadot-state-machine", "triehash", "polkadot-primitives/std"]
std = ["environmental", "polkadot-state-machine", "triehash", "polkadot-primitives/std", "polkadot-runtime-codec/std"]
nightly = []
strict = []
+6 -6
View File
@@ -22,6 +22,8 @@
#![cfg_attr(feature = "std", doc = "Polkadot runtime standard library as compiled when linked with Rust's standard library.")]
#![cfg_attr(not(feature = "std"), doc = "Polkadot's runtime standard library as compiled without Rust's standard library.")]
extern crate polkadot_runtime_codec as codec;
#[cfg(feature = "std")]
include!("../with_std.rs");
@@ -39,6 +41,7 @@ pub mod prelude {
/// Type definitions and helpers for transactions.
pub mod transaction {
pub use primitives::transaction::{Transaction, UncheckedTransaction};
use primitives::Signature;
#[cfg(feature = "std")]
use std::ops;
@@ -52,7 +55,7 @@ pub mod transaction {
impl CheckedTransaction {
/// Get a reference to the checked signature.
pub fn signature(&self) -> &[u8; 64] {
pub fn signature(&self) -> &Signature {
&self.0.signature
}
}
@@ -69,15 +72,12 @@ pub mod transaction {
///
/// On failure, return the transaction back.
pub fn check(tx: UncheckedTransaction) -> Result<CheckedTransaction, UncheckedTransaction> {
// TODO: requires canonical serialization of transaction.
let msg = unimplemented!();
if ed25519_verify(&tx.signature, &msg, &tx.transaction.signed) {
let msg = ::codec::Slicable::to_vec(&tx.transaction);
if ::ed25519_verify(&tx.signature.0, &msg, &tx.transaction.signed) {
Ok(CheckedTransaction(tx))
} else {
Err(tx)
}
}
}
/// Check a transaction
pub struct CheckedTransaction(primitives::UncheckedTransaction);
-1
View File
@@ -21,7 +21,6 @@ extern crate polkadot_state_machine;
extern crate polkadot_primitives as primitives;
extern crate triehash;
use std::fmt;
use primitives::ed25519;
pub use std::vec;
+3 -5
View File
@@ -20,7 +20,7 @@ use primitives::{validator, parachain};
use serde::de::DeserializeOwned;
use serializer;
use error::{Error, ErrorKind, Result};
use error::{ErrorKind, Result};
use parachains::{ParachainCode, ParaChain1};
/// A dummy validator implementation.
@@ -40,10 +40,8 @@ impl Validator {
}
}
impl validator::Validator for Validator {
type Error = Error;
fn validate(
impl Validator {
pub fn validate(
&self,
code: &[u8],
consolidated_ingress: &[(u64, Vec<parachain::Message>)],
+8 -7
View File
@@ -25,6 +25,7 @@ extern crate polkadot_runtime_std as runtime_std;
extern crate rustc_hex;
extern crate polkadot_runtime_codec as codec;
extern crate polkadot_primitives as primitives;
#[cfg(test)]
#[macro_use]
@@ -32,24 +33,24 @@ extern crate hex_literal;
#[macro_use]
pub mod support;
pub mod primitives;
pub mod runtime;
use runtime_std::prelude::*;
use codec::Slicable;
use primitives::{Block, UncheckedTransaction};
use primitives::transaction::UncheckedTransaction;
use primitives::block::Block;
/// Execute a block, with `input` being the canonical serialisation of the block. Returns the
/// empty vector.
pub fn execute_block(input: &[u8]) -> Vec<u8> {
runtime::system::internal::execute_block(Block::from_slice(input).unwrap());
pub fn execute_block(mut input: &[u8]) -> Vec<u8> {
runtime::system::internal::execute_block(Block::from_slice(&mut input).unwrap());
Vec::new()
}
/// Execute a given, serialised, transaction. Returns the empty vector.
pub fn execute_transaction(input: &[u8]) -> Vec<u8> {
let utx = UncheckedTransaction::from_slice(input).unwrap();
runtime::system::internal::execute_transaction(&utx);
pub fn execute_transaction(mut input: &[u8]) -> Vec<u8> {
let utx = UncheckedTransaction::from_slice(&mut input).unwrap();
runtime::system::internal::execute_transaction(utx);
Vec::new()
}
@@ -1,58 +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 type.
use runtime_std::prelude::*;
use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable};
use primitives::{Header, UncheckedTransaction};
/// A Polkadot relay chain block.
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct Block {
/// The header of the block.
pub header: Header,
/// All transactions.
pub transactions: Vec<UncheckedTransaction>,
}
impl Slicable for Block {
fn from_slice(value: &[u8]) -> Option<Self> {
let mut reader = StreamReader::new(value);
Some(Block {
header: reader.read()?,
transactions: reader.read()?,
})
}
fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: F) -> Option<Self> {
unimplemented!();
}
fn to_vec(&self) -> Vec<u8> {
Vec::new()
.join(&self.header)
.join(&self.transactions)
}
fn size_of(data: &[u8]) -> Option<usize> {
let first_part = Header::size_of(data)?;
let second_part = <Vec<UncheckedTransaction>>::size_of(&data[first_part..])?;
Some(first_part + second_part)
}
}
impl NonTrivialSlicable for Block {}
@@ -1,27 +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/>.
//! Digest type.
use runtime_std::prelude::*;
/// The digest of a block, useful for light-clients.
#[derive(Clone, Default)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct Digest {
/// All logs that have happened in the block.
pub logs: Vec<Vec<u8>>,
}
@@ -1,86 +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/>.
//! Function data: This describes a function that can be called from an external transaction.
use primitives::AccountID;
use codec::StreamReader;
use runtime::{staking, session, timestamp, governance};
/// Public functions that can be dispatched to.
#[derive(Clone, Copy)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
#[repr(u8)]
pub enum Function {
StakingStake = 0,
StakingUnstake = 1,
StakingTransfer = 2,
SessionSetKey = 3,
TimestampSet = 4,
GovernancePropose = 5,
GovernanceApprove = 6,
}
impl Function {
/// Derive `Some` value from a `u8`, or `None` if it's invalid.
pub fn from_u8(value: u8) -> Option<Function> {
use self::*;
let functions = [Function::StakingStake, Function::StakingUnstake,
Function::StakingTransfer, Function::SessionSetKey, Function::TimestampSet,
Function::GovernancePropose, Function::GovernanceApprove];
if (value as usize) < functions.len() {
Some(functions[value as usize])
} else {
None
}
}
}
impl Function {
/// Dispatch the function.
pub fn dispatch(&self, transactor: &AccountID, data: &[u8]) {
let mut params = StreamReader::new(data);
match *self {
Function::StakingStake => {
staking::public::stake(transactor);
}
Function::StakingUnstake => {
staking::public::unstake(transactor);
}
Function::StakingTransfer => {
let dest = params.read().unwrap();
let value = params.read().unwrap();
staking::public::transfer(transactor, &dest, value);
}
Function::SessionSetKey => {
let session = params.read().unwrap();
session::public::set_key(transactor, &session);
}
Function::TimestampSet => {
let t = params.read().unwrap();
timestamp::public::set(t);
}
Function::GovernancePropose => {
let proposal = params.read().unwrap();
governance::public::propose(transactor, &proposal);
}
Function::GovernanceApprove => {
let era_index = params.read().unwrap();
governance::public::approve(transactor, era_index);
}
}
}
}
@@ -1,72 +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 header type.
use runtime_std::prelude::*;
use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable};
use runtime_std::mem;
use primitives::{BlockNumber, Hash, Digest};
#[derive(Clone)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
/// The header for a block.
pub struct Header {
/// The parent block's "hash" (actually the Blake2-256 hash of its serialised header).
pub parent_hash: Hash,
/// The block's number (how many ancestors does it have?).
pub number: BlockNumber,
/// The root of the trie that represents this block's final storage map.
pub state_root: Hash,
/// The root of the trie that represents this block's transactions, indexed by a 32-bit integer.
pub transaction_root: Hash,
/// The digest for this block.
pub digest: Digest,
}
impl Slicable for Header {
fn from_slice(value: &[u8]) -> Option<Self> {
let mut reader = StreamReader::new(value);
Some(Header {
parent_hash: reader.read()?,
number: reader.read()?,
state_root: reader.read()?,
transaction_root: reader.read()?,
digest: Digest { logs: reader.read()?, },
})
}
fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: F) -> Option<Self> {
unimplemented!();
}
fn to_vec(&self) -> Vec<u8> {
Vec::new()
.join(&self.parent_hash)
.join(&self.number)
.join(&self.state_root)
.join(&self.transaction_root)
.join(&self.digest.logs)
}
fn size_of(data: &[u8]) -> Option<usize> {
let first_part = mem::size_of::<Hash>() + mem::size_of::<BlockNumber>() + mem::size_of::<Hash>() + mem::size_of::<Hash>();
let second_part = <Vec<Vec<u8>>>::size_of(&data[first_part..])?;
Some(first_part + second_part)
}
}
impl NonTrivialSlicable for Header {}
@@ -1,41 +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/>.
//! Miscellaneous small types.
/// The Ed25519 pubkey that identifies an account.
pub type AccountID = [u8; 32];
/// 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];
/// The Ed25519 pub key of an session that belongs to an authority. 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 block in the chain.
pub type BlockNumber = u64;
/// Index of a transaction.
pub type TxOrder = u64;
/// A hash of some data.
pub type Hash = [u8; 32];
@@ -1,38 +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/>.
//! Primitive types for the runtime.
mod misc;
mod proposal;
mod function;
mod digest;
mod header;
mod transaction;
mod uncheckedtransaction;
mod block;
#[cfg(test)]
mod tests;
pub use self::misc::{AccountID, EVERYBODY, SessionKey, ChainID, BlockNumber, TxOrder, Hash};
pub use self::proposal::{Proposal, InternalFunction};
pub use self::function::Function;
pub use self::digest::Digest;
pub use self::header::Header;
pub use self::transaction::Transaction;
pub use self::uncheckedtransaction::UncheckedTransaction;
pub use self::block::Block;
@@ -1,105 +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/>.
//! Proposal: This describes a combination of a function ID and data that can be used to call into
//! an internal function.
use runtime_std::prelude::*;
use runtime_std::mem;
use codec::{Slicable, Joiner, StreamReader};
use runtime::{system, governance, staking, session};
/// Internal functions that can be dispatched to.
#[derive(Clone, Copy)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
#[repr(u8)]
pub enum InternalFunction {
SystemSetCode = 0,
StakingSetSessionsPerEra = 1,
StakingSetBondingDuration = 2,
StakingSetValidatorCount = 3,
GovernanceSetApprovalPpmRequired = 4,
SessionSetLength = 5,
}
impl InternalFunction {
/// Derive `Some` value from a `u8`, or `None` if it's invalid.
pub fn from_u8(value: u8) -> Option<InternalFunction> {
use self::*;
let functions = [
InternalFunction::SystemSetCode,
InternalFunction::StakingSetSessionsPerEra,
InternalFunction::StakingSetBondingDuration,
InternalFunction::StakingSetValidatorCount,
InternalFunction::GovernanceSetApprovalPpmRequired,
InternalFunction::SessionSetLength
];
if (value as usize) < functions.len() {
Some(functions[value as usize])
} else {
None
}
}
}
/// An internal function.
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct Proposal {
/// The priviledged function to call.
pub function: InternalFunction,
/// The serialised data to call it with.
pub input_data: Vec<u8>,
}
impl Slicable for Proposal {
fn set_as_slice<F: Fn(&mut[u8], usize) -> bool>(fill_slice: F) -> Option<Self> {
Some(Proposal {
function: InternalFunction::from_u8(Slicable::set_as_slice(&fill_slice)?)?,
input_data: Slicable::set_as_slice(|s, o| fill_slice(s, o + 1))?,
})
}
fn to_vec(&self) -> Vec<u8> {
Vec::new()
.join(&(self.function as u8))
.join(&self.input_data)
}
fn size_of(data: &[u8]) -> Option<usize> {
let first_part = mem::size_of::<u8>();
let second_part = <Vec<u8>>::size_of(&data[first_part..])?;
Some(first_part + second_part)
}
}
#[cfg(test)]
mod test {
use super::*;
use support::StaticHexInto;
#[test]
fn slicing_should_work() {
let p = Proposal {
function: InternalFunction::SystemSetCode,
input_data: b"Hello world".to_vec(),
};
let v = p.to_vec();
assert_eq!(v, "000b00000048656c6c6f20776f726c64".convert::<Vec<u8>>());
let o = Proposal::from_slice(&v).unwrap();
assert_eq!(p, o);
}
}
@@ -1,241 +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/>.
//! Tests.
use super::*;
use runtime_std::prelude::*;
use codec::{Joiner, Slicable};
use primitives::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,
input_data: Vec::new().join(&two).join(&69u64),
};
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,
2,
40, 0, 0, 0,
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,
input_data: Vec::new().join(&two).join(&69u64),
};
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,
2,
40, 0, 0, 0,
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(&data).unwrap();
assert_eq!(deserialised, tx);
}
#[test]
fn serialise_header_works() {
let h = Header {
parent_hash: [4u8; 32],
number: 42,
state_root: [5u8; 32],
transaction_root: [6u8; 32],
digest: Digest { logs: vec![ b"one log".to_vec(), 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,
26, 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],
number: 42,
state_root: [5u8; 32],
transaction_root: [6u8; 32],
digest: Digest { logs: vec![ b"one log".to_vec(), 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,
26, 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(&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,
input_data: Vec::new().join(&two).join(&69u64),
},
signature: [1u8; 64],
};
let tx2 = UncheckedTransaction {
transaction: Transaction {
signed: two.clone(),
nonce: 42,
function: Function::StakingStake,
input_data: Vec::new(),
},
signature: [2u8; 64],
};
let h = Header {
parent_hash: [4u8; 32],
number: 42,
state_root: [5u8; 32],
transaction_root: [6u8; 32],
digest: Digest { logs: vec![ b"one log".to_vec(), 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,
26, 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, 1, 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, 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,
69, 0, 0, 0, 0, 0, 0, 0,
2,
40, 0, 0, 0,
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,
// 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, 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,
42, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0
]);
}
#[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,
input_data: Vec::new().join(&two).join(&69u64),
},
signature: [1u8; 64],
};
let tx2 = UncheckedTransaction {
transaction: Transaction {
signed: two.clone(),
nonce: 42,
function: Function::StakingStake,
input_data: Vec::new(),
},
signature: [2u8; 64],
};
let h = Header {
parent_hash: [4u8; 32],
number: 42,
state_root: [5u8; 32],
transaction_root: [6u8; 32],
digest: Digest { logs: vec![ b"one log".to_vec(), 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,
26, 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, 1, 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, 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,
69, 0, 0, 0, 0, 0, 0, 0,
2,
40, 0, 0, 0,
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,
// 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, 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,
42, 0, 0, 0, 0, 0, 0, 0,
0,
0, 0, 0, 0
];
let deserialised = Block::from_slice(&data).unwrap();
assert_eq!(deserialised, b);
}
@@ -1,67 +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 runtime_std::prelude::*;
use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable};
use primitives::{AccountID, TxOrder, Function};
use runtime_std::mem;
/// A vetted and verified transaction from the external world.
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
pub struct Transaction {
/// Who signed it (note this is not a signature).
pub signed: AccountID,
/// The number of transactions have come before from the same signer.
pub nonce: TxOrder,
/// The function that should be called.
pub function: Function,
/// Serialised input data to the function.
pub input_data: Vec<u8>,
}
impl Slicable for Transaction {
fn from_slice(value: &[u8]) -> Option<Self> {
let mut reader = StreamReader::new(value);
Some(Transaction {
signed: reader.read()?,
nonce: reader.read()?,
function: Function::from_u8(reader.read()?)?,
input_data: reader.read()?,
})
}
fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: F) -> Option<Self> {
unimplemented!();
}
fn to_vec(&self) -> Vec<u8> {
Vec::new()
.join(&self.signed)
.join(&self.nonce)
.join(&(self.function as u8))
.join(&self.input_data)
}
fn size_of(data: &[u8]) -> Option<usize> {
let first_part = mem::size_of::<AccountID>() + mem::size_of::<TxOrder>() + mem::size_of::<u8>();
let second_part = <Vec<u8>>::size_of(&data[first_part..])?;
Some(first_part + second_part)
}
}
impl NonTrivialSlicable for Transaction {}
@@ -1,83 +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/>.
//! Unchecked Transaction type.
use runtime_std::{mem, ed25519_verify};
use runtime_std::prelude::*;
use codec::{Slicable, NonTrivialSlicable, StreamReader, Joiner};
use primitives::Transaction;
#[cfg(feature = "std")]
use std::fmt;
/// A transactions right from the external world. Unchecked.
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: [u8; 64],
}
impl UncheckedTransaction {
/// Verify the signature.
pub fn ed25519_verify(&self) -> bool {
let msg = self.transaction.to_vec();
ed25519_verify(&self.signature, &msg, &self.transaction.signed)
}
}
#[cfg(feature = "std")]
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)
}
}
impl Slicable for UncheckedTransaction {
fn from_slice(value: &[u8]) -> Option<Self> {
let mut reader = StreamReader::new(value);
Some(UncheckedTransaction {
signature: reader.read()?,
transaction: reader.read()?,
})
}
fn set_as_slice<F: Fn(&mut [u8], usize) -> bool>(_fill_slice: F) -> Option<Self> {
unimplemented!();
}
fn to_vec(&self) -> Vec<u8> {
Vec::new()
.join(&self.signature)
.join(&self.transaction)
}
fn size_of(data: &[u8]) -> Option<usize> {
let first_part = mem::size_of::<[u8; 64]>();
let second_part = <Transaction>::size_of(&data[first_part..])?;
Some(first_part + second_part)
}
}
impl NonTrivialSlicable for UncheckedTransaction {}
@@ -28,7 +28,8 @@
use runtime_std::prelude::*;
use codec::KeyedVec;
use support::storage;
use primitives::{AccountID, Hash, BlockNumber, Proposal};
use primitives::{AccountId, Hash, BlockNumber};
use primitives::proposal::Proposal;
use runtime::{staking, system, session};
const APPROVALS_REQUIRED: &[u8] = b"gov:apr";
@@ -52,7 +53,7 @@ pub mod public {
/// Propose a sensitive action to be taken. Any action that is enactable by `Proposal` is valid.
/// Proposal is by the `transactor` and will automatically count as an approval. Transactor must
/// be a current validator. It is illegal to propose when there is already a proposal in effect.
pub fn propose(validator: &AccountID, proposal: &Proposal) {
pub fn propose(validator: &AccountId, proposal: &Proposal) {
if storage::exists(CURRENT_PROPOSAL) {
panic!("there may only be one proposal per era.");
}
@@ -62,7 +63,7 @@ pub mod public {
/// Approve the current era's proposal. Transactor must be a validator. This may not be done more
/// than once for any validator in an era.
pub fn approve(validator: &AccountID, era_index: BlockNumber) {
pub fn approve(validator: &AccountId, era_index: BlockNumber) {
if era_index != staking::current_era() {
panic!("approval vote applied on non-current era.")
}
@@ -94,6 +95,7 @@ pub mod privileged {
pub mod internal {
use super::*;
use primitives::proposal::{Proposal, InternalFunction};
/// Current era is ending; we should finish up any proposals.
pub fn end_of_an_era() {
@@ -105,36 +107,29 @@ pub mod internal {
.take(approvals_required as usize)
.count() as u32;
if approved == approvals_required {
proposal.enact();
enact_proposal(proposal);
}
}
}
fn enact_proposal(proposal: Proposal) {
let mut params = StreamReader::new(&self.input_data);
match self.function {
InternalFunction::SystemSetCode => {
let code: Vec<u8> = params.read().unwrap();
match proposal.function {
InternalFunction::SystemSetCode(code) => {
system::privileged::set_code(&code);
}
InternalFunction::StakingSetSessionsPerEra => {
let value = params.read().unwrap();
InternalFunction::StakingSetSessionsPerEra(value) => {
staking::privileged::set_sessions_per_era(value);
}
InternalFunction::StakingSetBondingDuration => {
let value = params.read().unwrap();
InternalFunction::StakingSetBondingDuration(value) => {
staking::privileged::set_bonding_duration(value);
}
InternalFunction::StakingSetValidatorCount => {
let value = params.read().unwrap();
InternalFunction::StakingSetValidatorCount(value) => {
staking::privileged::set_validator_count(value);
}
InternalFunction::GovernanceSetApprovalPpmRequired => {
let value = params.read().unwrap();
governance::privileged::set_approval_ppm_required(value);
InternalFunction::GovernanceSetApprovalPpmRequired(value) => {
self::privileged::set_approval_ppm_required(value);
}
InternalFunction::SessionSetLength => {
let value = params.read().unwrap();
InternalFunction::SessionSetLength(value) => {
session::privileged::set_length(value);
}
}
@@ -147,7 +142,8 @@ mod tests {
use runtime_std::{with_externalities, twox_128, TestExternalities};
use codec::{KeyedVec, Joiner};
use support::{one, two, with_env};
use primitives::{AccountID, InternalFunction};
use primitives::AccountId;
use primitives::proposal::InternalFunction;
use runtime::{staking, session};
fn new_test_ext() -> TestExternalities {
@@ -189,8 +185,7 @@ mod tests {
// Block 1: Make proposal. Approve it. Era length changes.
with_env(|e| e.block_number = 1);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
public::approve(&two, 1);
staking::internal::check_new_era();
@@ -215,8 +210,7 @@ mod tests {
// Block 1: Make proposal. Fail it.
with_env(|e| e.block_number = 1);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
staking::internal::check_new_era();
assert_eq!(staking::era_length(), 1);
@@ -224,8 +218,7 @@ mod tests {
// Block 2: Make proposal. Approve it. It should change era length.
with_env(|e| e.block_number = 2);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
public::approve(&two, 2);
staking::internal::check_new_era();
@@ -250,8 +243,7 @@ mod tests {
// Block 1: Make proposal. Will have only 1 vote. No change.
with_env(|e| e.block_number = 1);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
staking::internal::check_new_era();
assert_eq!(staking::era_length(), 1);
@@ -276,8 +268,7 @@ mod tests {
// Block 1: Make proposal. Will have only 1 vote. No change.
with_env(|e| e.block_number = 1);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
public::approve(&two, 0);
staking::internal::check_new_era();
@@ -303,8 +294,7 @@ mod tests {
// Block 1: Make proposal. Will have only 1 vote. No change.
with_env(|e| e.block_number = 1);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
public::approve(&two, 1);
public::approve(&two, 1);
@@ -331,12 +321,10 @@ mod tests {
// Block 1: Make proposal. Will have only 1 vote. No change.
with_env(|e| e.block_number = 1);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
public::propose(&two, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
staking::internal::check_new_era();
assert_eq!(staking::era_length(), 1);
@@ -385,8 +373,7 @@ mod tests {
// Block 1: Make proposal. Will have only 1 vote. No change.
with_env(|e| e.block_number = 1);
public::propose(&one, &Proposal {
function: InternalFunction::StakingSetSessionsPerEra,
input_data: vec![].join(&2u64),
function: InternalFunction::StakingSetSessionsPerEra(2),
});
public::approve(&four, 1);
staking::internal::check_new_era();
@@ -20,7 +20,7 @@
use runtime_std::prelude::*;
use codec::KeyedVec;
use support::{storage, StorageVec};
use primitives::{AccountID, SessionKey, BlockNumber};
use primitives::{AccountId, SessionKey, BlockNumber};
use runtime::{system, staking, consensus};
const SESSION_LENGTH: &[u8] = b"ses:len";
@@ -31,12 +31,12 @@ const NEXT_SESSION_LENGTH: &[u8] = b"ses:nln";
struct ValidatorStorageVec {}
impl StorageVec for ValidatorStorageVec {
type Item = AccountID;
type Item = AccountId;
const PREFIX: &'static[u8] = b"ses:val:";
}
/// Get the current set of authorities. These are the session keys.
pub fn validators() -> Vec<AccountID> {
pub fn validators() -> Vec<AccountId> {
ValidatorStorageVec::items()
}
@@ -65,7 +65,7 @@ pub mod public {
/// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next
/// session.
pub fn set_key(validator: &AccountID, key: &SessionKey) {
pub fn set_key(validator: &AccountId, key: &SessionKey) {
// set new value for next session
storage::put(&validator.to_keyed_vec(NEXT_KEY_FOR), key);
}
@@ -89,7 +89,7 @@ pub mod internal {
///
/// Called by staking::next_era() only. `next_session` should be called after this in order to
/// update the session keys to the next validator set.
pub fn set_validators(new: &[AccountID]) {
pub fn set_validators(new: &[AccountId]) {
ValidatorStorageVec::set_items(new);
consensus::internal::set_authorities(new);
}
@@ -135,7 +135,7 @@ mod tests {
use runtime_std::{with_externalities, twox_128, TestExternalities};
use codec::{KeyedVec, Joiner};
use support::{one, two, with_env};
use primitives::AccountID;
use primitives::AccountId;
use runtime::{consensus, session};
fn simple_setup() -> TestExternalities {
@@ -20,7 +20,7 @@ use runtime_std::prelude::*;
use runtime_std::cell::RefCell;
use codec::KeyedVec;
use support::{storage, StorageVec};
use primitives::{BlockNumber, AccountID};
use primitives::{BlockNumber, AccountId};
use runtime::{system, session, governance};
/// The balance of an account.
@@ -31,7 +31,7 @@ pub type Bondage = u64;
struct IntentionStorageVec {}
impl StorageVec for IntentionStorageVec {
type Item = AccountID;
type Item = AccountId;
const PREFIX: &'static[u8] = b"sta:wil:";
}
@@ -75,12 +75,12 @@ pub fn last_era_length_change() -> BlockNumber {
}
/// The balance of a given account.
pub fn balance(who: &AccountID) -> Balance {
pub fn balance(who: &AccountId) -> Balance {
storage::get_or_default(&who.to_keyed_vec(BALANCE_OF))
}
/// The liquidity-state of a given account.
pub fn bondage(who: &AccountID) -> Bondage {
pub fn bondage(who: &AccountId) -> Bondage {
storage::get_or_default(&who.to_keyed_vec(BONDAGE_OF))
}
@@ -94,7 +94,7 @@ pub mod public {
use super::*;
/// Transfer some unlocked staking balance to another staker.
pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) {
pub fn transfer(transactor: &AccountId, dest: &AccountId, value: Balance) {
let from_key = transactor.to_keyed_vec(BALANCE_OF);
let from_balance = storage::get_or_default::<Balance>(&from_key);
assert!(from_balance >= value);
@@ -109,7 +109,7 @@ pub mod public {
/// Declare the desire to stake for the transactor.
///
/// Effects will be felt at the beginning of the next era.
pub fn stake(transactor: &AccountID) {
pub fn stake(transactor: &AccountId) {
let mut intentions = IntentionStorageVec::items();
// can't be in the list twice.
assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked.");
@@ -121,7 +121,7 @@ pub mod public {
/// Retract the desire to stake for the transactor.
///
/// Effects will be felt at the beginning of the next era.
pub fn unstake(transactor: &AccountID) {
pub fn unstake(transactor: &AccountId) {
let mut intentions = IntentionStorageVec::items();
if let Some(position) = intentions.iter().position(|t| t == transactor) {
intentions.swap_remove(position);
@@ -147,8 +147,8 @@ pub mod privileged {
}
/// The length of a staking era in sessions.
pub fn set_validator_count(new: usize) {
storage::put(VALIDATOR_COUNT, &(new as u32));
pub fn set_validator_count(new: u32) {
storage::put(VALIDATOR_COUNT, &new);
}
}
@@ -209,7 +209,7 @@ mod tests {
use runtime_std::{with_externalities, twox_128, TestExternalities};
use codec::{KeyedVec, Joiner};
use support::{one, two, with_env};
use primitives::AccountID;
use primitives::AccountId;
use runtime::{staking, session};
#[test]
@@ -21,7 +21,10 @@ use runtime_std::prelude::*;
use runtime_std::{mem, print, storage_root, enumerated_trie_root};
use codec::{KeyedVec, Slicable};
use support::{Hashable, storage, with_env};
use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder};
use primitives::{AccountId, Hash, TxOrder};
use primitives::block::{Block, Number as BlockNumber};
use primitives::transaction::UncheckedTransaction;
use primitives::runtime_function::Function;
use runtime::{staking, session};
const BLOCK_HASH_AT: &[u8] = b"sys:old:";
@@ -54,7 +57,7 @@ pub mod internal {
/// Deposits a log and ensures it matches the blocks log data.
pub fn deposit_log(log: &[u8]) {
with_env(|e| {
assert_eq!(log, &e.digest.logs[e.next_log_index][..]);
assert_eq!(log, &e.digest.logs[e.next_log_index].0[..]);
e.next_log_index += 1;
});
}
@@ -79,11 +82,10 @@ pub mod internal {
// check transaction trie root represents the transactions.
let txs = block.transactions.iter().map(Slicable::to_vec).collect::<Vec<_>>();
let txs_root = enumerated_trie_root(&txs.iter().map(Vec::as_slice).collect::<Vec<_>>());
// println!("TR: {}", ::support::HexDisplay::from(&txs_root));
assert!(header.transaction_root == txs_root, "Transaction trie root must be valid.");
assert!(header.transaction_root.0 == txs_root, "Transaction trie root must be valid.");
// execute transactions
block.transactions.iter().for_each(execute_transaction);
block.transactions.iter().cloned().for_each(execute_transaction);
staking::internal::check_new_era();
session::internal::check_rotate_session();
@@ -93,7 +95,7 @@ pub mod internal {
// check storage root.
assert!(header.state_root == storage_root(), "Storage root must match that calculated.");
assert!(header.state_root.0 == storage_root(), "Storage root must match that calculated.");
// store the header hash in storage; we can't do it before otherwise there would be a
// cyclic dependency.
@@ -102,11 +104,14 @@ pub mod internal {
}
/// Execute a given transaction.
pub fn execute_transaction(utx: &UncheckedTransaction) {
// Verify the signature is good.
assert!(utx.ed25519_verify(), "All transactions should be properly signed");
pub fn execute_transaction(utx: UncheckedTransaction) {
use runtime_std::transaction;
let ref tx = utx.transaction;
// Verify the signature is good.
let tx = match transaction::check(utx) {
Ok(tx) => tx,
Err(_) => panic!("All transactions should be properly signed"),
};
// check nonce
let nonce_key = tx.signed.to_keyed_vec(b"sys:non:");
@@ -117,38 +122,31 @@ pub mod internal {
storage::put(&nonce_key, &(expected_nonce + 1));
// decode parameters and dispatch
dispatch_function(&tx.function, &tx.signed, &tx.input_data);
dispatch_function(&tx.function, &tx.signed);
}
fn dispatch_function(function: &Function, transactor: &AccountId, data: &[u8]) {
let mut params = ::runtime_codec::StreamReader::new(data);
match *self {
fn dispatch_function(function: &Function, transactor: &AccountId) {
match *function {
Function::StakingStake => {
staking::public::stake(transactor);
::runtime::staking::public::stake(transactor);
}
Function::StakingUnstake => {
staking::public::unstake(transactor);
::runtime::staking::public::unstake(transactor);
}
Function::StakingTransfer => {
let dest = params.read().unwrap();
let value = params.read().unwrap();
staking::public::transfer(transactor, &dest, value);
Function::StakingTransfer(dest, value) => {
::runtime::staking::public::transfer(transactor, &dest, value);
}
Function::SessionSetKey => {
let session = params.read().unwrap();
session::public::set_key(transactor, &session);
Function::SessionSetKey(session) => {
::runtime::session::public::set_key(transactor, &session);
}
Function::TimestampSet => {
let t = params.read().unwrap();
timestamp::public::set(t);
Function::TimestampSet(t) => {
::runtime::timestamp::public::set(t);
}
Function::GovernancePropose => {
let proposal = params.read().unwrap();
governance::public::propose(transactor, &proposal);
Function::GovernancePropose(ref proposal) => {
::runtime::governance::public::propose(transactor, proposal);
}
Function::GovernanceApprove => {
let era_index = params.read().unwrap();
governance::public::approve(transactor, era_index);
Function::GovernanceApprove(era_index) => {
::runtime::governance::public::approve(transactor, era_index);
}
}
}
@@ -168,7 +166,10 @@ mod tests {
use runtime_std::{with_externalities, twox_128, TestExternalities};
use codec::{Joiner, KeyedVec, Slicable};
use support::{StaticHexInto, HexDisplay, one, two};
use primitives::{UncheckedTransaction, Transaction, Function, Header, Digest};
use primitives::transaction::{UncheckedTransaction, Transaction};
use primitives::runtime_function::Function;
use primitives::block::{Header, Digest};
use primitives::hash::{H256, H512};
use runtime::staking;
#[test]
@@ -184,18 +185,15 @@ mod tests {
transaction: Transaction {
signed: one.clone(),
nonce: 0,
function: Function::StakingTransfer,
input_data: vec![].join(&two).join(&69u64),
function: Function::StakingTransfer(two, 69),
},
signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(),
signature: "b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".parse().unwrap(),
};
// tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000
// sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a
println!("tx is {}", HexDisplay::from(&tx.transaction.to_vec()));
// sig: b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00
with_externalities(&mut t, || {
execute_transaction(&tx);
execute_transaction(tx);
assert_eq!(staking::balance(&one), 42);
assert_eq!(staking::balance(&two), 69);
});
@@ -236,17 +234,16 @@ mod tests {
transaction: Transaction {
signed: one.clone(),
nonce: 0,
function: Function::StakingTransfer,
input_data: vec![].join(&two).join(&69u64),
function: Function::StakingTransfer(two, 69),
},
signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(),
signature: "b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".parse().unwrap(),
};
let h = Header {
parent_hash: [69u8; 32],
parent_hash: H256([69u8; 32]),
number: 1,
state_root: hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db"),
transaction_root: hex!("91fab88ad8c30a6d05ad8e0cf9ab139bf1b8cdddc69abd51cdfa6d2699038af1"),
state_root: H256(hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db")),
transaction_root: H256(hex!("c4b361b976b3aa90f9f0cdd32f4afc80dd96f200145a687196388a00363c2235")),
digest: Digest { logs: vec![], },
};
@@ -274,19 +271,18 @@ mod tests {
transaction: Transaction {
signed: one.clone(),
nonce: 0,
function: Function::StakingTransfer,
input_data: vec![].join(&two).join(&69u64),
function: Function::StakingTransfer(two, 69),
},
signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(),
signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".parse().unwrap(),
};
// tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000
// sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a
let h = Header {
parent_hash: [69u8; 32],
parent_hash: H256([69u8; 32]),
number: 1,
state_root: [0u8; 32],
transaction_root: [0u8; 32], // Unchecked currently.
state_root: H256([0u8; 32]),
transaction_root: H256([0u8; 32]), // Unchecked currently.
digest: Digest { logs: vec![], },
};
@@ -17,12 +17,10 @@
//! Timestamp manager: just handles the current timestamp.
use support::storage;
use primitives::Timestamp;
const CURRENT_TIMESTAMP: &[u8] = b"tim:val";
/// Representation of a time.
pub type Timestamp = u64;
/// Get the current time.
pub fn get() -> Timestamp {
storage::get_or_default(CURRENT_TIMESTAMP)
@@ -21,7 +21,7 @@ use runtime_std::mem;
use runtime_std::cell::RefCell;
use runtime_std::rc::Rc;
use primitives::{BlockNumber, Digest};
use primitives::block::{Number as BlockNumber, Digest};
#[derive(Default)]
/// The information that can be accessed globally.
@@ -24,9 +24,8 @@ use codec::{Slicable, KeyedVec};
/// Return the value of the item in storage under `key`, or `None` if there is no explicit entry.
pub fn get<T: Slicable + Sized>(key: &[u8]) -> Option<T> {
Slicable::set_as_slice(|out, offset|
runtime_std::read_storage(&twox_128(key)[..], out, offset) >= out.len()
)
let raw = runtime_std::storage(&twox_128(key)[..]);
Slicable::from_slice(&mut &raw[..])
}
/// Return the value of the item in storage under `key`, or the type's default if there is no
@@ -216,10 +215,12 @@ mod tests {
#[test]
fn proposals_can_be_stored() {
use primitives::{Proposal, InternalFunction};
use primitives::proposal::{Proposal, InternalFunction};
let mut t = TestExternalities { storage: HashMap::new(), };
with_externalities(&mut t, || {
let x = Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: b"Hello world".to_vec() };
let x = Proposal {
function: InternalFunction::StakingSetSessionsPerEra(25519),
};
put(b":test", &x);
let y: Proposal = get(b":test").unwrap();
assert_eq!(x, y);
@@ -16,7 +16,7 @@
//! Testing helpers.
use primitives::AccountID;
use primitives::AccountId;
use super::statichex::StaticHexInto;
#[macro_export]
@@ -27,11 +27,11 @@ macro_rules! map {
}
/// One account (to which we know the secret key).
pub fn one() -> AccountID {
pub fn one() -> AccountId {
"2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert()
}
/// Another account (secret key known).
pub fn two() -> AccountID {
pub fn two() -> AccountId {
"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert()
}