extract out all primitives

This commit is contained in:
Robert Habermeier
2018-02-01 11:13:55 +01:00
parent a3b9c2af7d
commit 188332cc4b
17 changed files with 386 additions and 87 deletions
+22 -3
View File
@@ -16,9 +16,10 @@
//! Block and header type definitions.
use bytes;
use bytes::{self, Vec};
use hash::H256;
use parachain;
use transaction::UncheckedTransaction;
/// Used to refer to a block number.
pub type Number = u64;
@@ -33,6 +34,22 @@ pub type TransactionHash = H256;
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Log(#[serde(with="bytes")] pub Vec<u8>);
/// A Polkadot relay chain block.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Block {
/// The block header.
pub header: Header,
/// All relay-chain transactions.
pub transactions: Vec<UncheckedTransaction>,
}
/// The digest of a block, useful for light-clients.
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Digest {
/// All logs that have happened in the block.
pub logs: Vec<Log>,
}
/// A relay chain block header.
///
/// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header
@@ -46,10 +63,12 @@ pub struct Header {
pub number: Number,
/// State root after this transition.
pub state_root: H256,
/// The root of the trie that represents this block's transactions, indexed by a 32-byte integer.
pub transaction_root: H256,
/// Parachain activity bitfield
pub parachain_activity: parachain::Activity,
/// Logs (generated by execution)
pub logs: Vec<Log>,
/// The digest of activity on the block.
pub digest: Digest,
}
/// A relay chain block body.
+4 -4
View File
@@ -57,7 +57,7 @@ pub fn blake2_128(data: &[u8]) -> [u8; 16] {
/// Do a XX 128-bit hash and place result in `dest`.
pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) {
use ::std::hash::Hasher;
use ::core::hash::Hasher;
let mut h0 = twox_hash::XxHash::with_seed(0);
let mut h1 = twox_hash::XxHash::with_seed(1);
h0.write(data);
@@ -71,14 +71,14 @@ pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) {
/// Do a XX 128-bit hash and return result.
pub fn twox_128(data: &[u8]) -> [u8; 16] {
let mut r: [u8; 16] = unsafe { ::std::mem::uninitialized() };
let mut r: [u8; 16] = [0; 16];
twox_128_into(data, &mut r);
r
}
/// Do a XX 256-bit hash and place result in `dest`.
pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) {
use ::std::hash::Hasher;
use ::core::hash::Hasher;
use byteorder::{ByteOrder, LittleEndian};
let mut h0 = twox_hash::XxHash::with_seed(0);
let mut h1 = twox_hash::XxHash::with_seed(1);
@@ -100,7 +100,7 @@ pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) {
/// Do a XX 256-bit hash and return result.
pub fn twox_256(data: &[u8]) -> [u8; 32] {
let mut r: [u8; 32] = unsafe { ::std::mem::uninitialized() };
let mut r: [u8; 32] = [0; 32];
twox_256_into(data, &mut r);
r
}
+1 -1
View File
@@ -25,7 +25,7 @@ impl<'a> HexDisplay<'a> {
}
impl<'a> ::core::fmt::Display for HexDisplay<'a> {
fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
fn fmt(&self, fmtr: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> {
for byte in self.0 {
try!( fmtr.write_fmt(format_args!("{:02x}", byte)));
}
+33 -8
View File
@@ -53,23 +53,48 @@ extern crate alloc;
mod bytes;
pub mod block;
pub mod contract;
pub mod ed25519;
pub mod hash;
pub mod hashing;
pub mod hexdisplay;
pub mod parachain;
pub mod proposal;
pub mod runtime_function;
pub mod transaction;
pub mod uint;
pub mod validator;
pub mod ed25519;
pub mod hexdisplay;
pub mod hashing;
/// Alias to 160-bit hash when used in the context of an account address.
pub type Address = hash::H160;
/// Alias to 520-bit hash when used in the context of a signature.
pub type Signature = hash::H512;
pub use self::hash::{H160, H256};
pub use self::uint::{U256, U512};
pub use hashing::{blake2_256, twox_128, twox_256};
/// 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.
pub type AccountId = [u8; 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];
/// Alias to 520-bit hash when used in the context of a signature.
pub type Signature = hash::H512;
/// A hash function.
pub fn hash(data: &[u8]) -> hash::H256 {
blake2_256(data).into()
+2 -2
View File
@@ -57,11 +57,11 @@ pub struct CandidateReceipt {
/// The ID of the parachain this is a candidate for.
pub parachain_index: Id,
/// The collator's account ID
pub collator: ::Address,
pub collator: ::AccountId,
/// The head-data
pub head_data: HeadData,
/// Balance uploads to the relay chain.
pub balance_uploads: Vec<(::Address, ::uint::U256)>,
pub balance_uploads: Vec<(::AccountId, ::uint::U256)>,
/// Egress queue roots.
pub egress_queue_roots: Vec<(Id, ::hash::H256)>,
/// Fees paid from the chain to the relay chain validators
+89
View File
@@ -0,0 +1,89 @@
// 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/>.
//! Proposals for relay-chain governance.
//!
//! This describes a combination of a function ID and data that can be used to call into
//! an internal function.
use bytes;
/// Internal functions that can be dispatched to.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
pub enum InternalFunction {
/// Set the system's code.
SystemSetCode = 0,
/// Set the number of sessions per era.
StakingSetSessionsPerEra = 1,
/// Set the minimum bonding duration for staking.
StakingSetBondingDuration = 2,
/// Set the validator count for staking.
StakingSetValidatorCount = 3,
/// Set the per-mille of validator approval required for governance changes.
GovernanceSetApprovalPpmRequired = 4,
/// Set the session length.
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.
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Proposal {
/// The privileged function to call.
pub function: InternalFunction,
/// The serialised data to call it with.
#[serde(with = "bytes")]
pub input_data: Vec<u8>,
}
#[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);
}
}
@@ -0,0 +1,54 @@
// 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/>.
//! Polkadot runtime functions.
//! This describes a function that can be called from an external transaction.
/// Public functions that can be dispatched to.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[repr(u8)]
pub enum Function {
/// Staking subsystem: begin staking.
StakingStake = 0,
/// Staking subsystem: stop staking.
StakingUnstake = 1,
/// Staking subsystem: transfer stake.
StakingTransfer = 2,
/// Set temporary session key as a validator.
SessionSetKey = 3,
/// Set the timestamp.
TimestampSet = 4,
/// Make a proposal for the governance system.
GovernancePropose = 5,
/// Approve a proposal for the governance system.
GovernanceApprove = 6,
}
impl Function {
/// Derive `Some` value from a `u8`, or `None` if it's invalid.
pub fn from_u8(value: u8) -> Option<Function> {
match value {
0 => Some(Function::StakingStake),
1 => Some(Function::StakingUnstake),
2 => Some(Function::StakingTransfer),
3 => Some(Function::SessionSetKey),
4 => Some(Function::TimestampSet),
5 => Some(Function::GovernancePropose),
6 => Some(Function::GovernanceApprove),
_ => None,
}
}
}
+61
View File
@@ -0,0 +1,61 @@
// 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::{self, Vec};
use runtime_function::Function;
#[cfg(feature = "std")]
use std::fmt;
#[cfg(not(feature = "std"))]
use alloc::fmt;
/// A vetted and verified transaction from the external world.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
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.
#[serde(with = "bytes")]
pub input_data: Vec<u8>,
}
/// A transactions right from the external world. Unchecked.
#[derive(Eq, Clone, Serialize, Deserialize)]
pub struct UncheckedTransaction {
/// The actual transaction information.
pub transaction: Transaction,
/// The signature; should be an Ed25519 signature applied to the serialised `transaction` field.
pub signature: ::Signature,
}
impl 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)
}
}
-20
View File
@@ -44,26 +44,6 @@ pub struct ValidationResult {
pub balance_uploads: Vec<BalanceUpload>,
}
// TODO [ToDr] This shouldn't be here!
/// Validator logic.
pub trait Validator {
/// Validation error.
type Error: ::std::error::Error;
/// Validates if the provided proof holds given a current ingress queue.
///
/// In case of success produces egress posts.
fn validate(
&self,
code: &[u8],
// TODO [ToDr] actually consolidate
consolidated_ingress: &[(u64, Vec<parachain::Message>)],
balance_downloads: &[BalanceDownload],
block_data: &parachain::BlockData,
previous_head_data: &parachain::HeadData,
) -> Result<ValidationResult, Self::Error>;
}
#[cfg(test)]
mod tests {
use super::*;
+2 -2
View File
@@ -12,11 +12,11 @@ pwasm-alloc = { path = "../wasm-runtime/pwasm-alloc", version = "0.1" }
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", optional = true }
polkadot-primitives = { path = "../primitives", version = "0.1", default_features = false }
triehash = { version = "0.1", optional = true }
[features]
default = ["std"]
std = ["environmental", "polkadot-state-machine", "polkadot-primitives", "triehash"]
std = ["environmental", "polkadot-state-machine", "triehash", "polkadot-primitives/std"]
nightly = []
strict = []
+46 -2
View File
@@ -28,8 +28,6 @@ include!("../with_std.rs");
#[cfg(not(feature = "std"))]
include!("../without_std.rs");
/// Prelude of common useful imports.
///
/// This should include only things which are in the normal std prelude.
@@ -37,3 +35,49 @@ pub mod prelude {
pub use ::vec::Vec;
pub use ::boxed::Box;
}
/// Type definitions and helpers for transactions.
pub mod transaction {
pub use primitives::transaction::{Transaction, UncheckedTransaction};
#[cfg(feature = "std")]
use std::ops;
#[cfg(not(feature = "std"))]
use core::ops;
/// A type-safe indicator that a transaction has been checked.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct CheckedTransaction(UncheckedTransaction);
impl CheckedTransaction {
/// Get a reference to the checked signature.
pub fn signature(&self) -> &[u8; 64] {
&self.0.signature
}
}
impl ops::Deref for CheckedTransaction {
type Target = Transaction;
fn deref(&self) -> &Transaction {
&self.0.transaction
}
}
/// Check the signature on a 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) {
Ok(CheckedTransaction(tx))
} else {
Err(tx)
}
}
}
/// Check a transaction
pub struct CheckedTransaction(primitives::UncheckedTransaction);
+3 -11
View File
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
#[macro_use]
extern crate environmental;
@@ -32,18 +31,14 @@ pub use std::boxed;
pub use std::slice;
pub use std::mem;
// re-export hashing functions.
pub use primitives::{blake2_256, twox_128, twox_256};
pub use polkadot_state_machine::{Externalities, ExternalitiesError, TestExternalities};
use primitives::hexdisplay::HexDisplay;
// TODO: use the real error, not NoError.
#[derive(Debug)]
/// As it says - an empty type we use for errors.
pub struct NoError;
impl fmt::Display for NoError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") }
}
environmental!(ext : trait Externalities);
/// Get `key` from storage and return a `Vec`, empty if there's a problem.
@@ -97,9 +92,6 @@ pub fn enumerated_trie_root(serialised_values: &[&[u8]]) -> [u8; 32] {
triehash::ordered_trie_root(serialised_values.iter().map(|s| s.to_vec())).0
}
/// Conduct a Keccak-256 hash of the given data.
pub use primitives::{blake2_256, twox_128, twox_256};
/// Verify a ed25519 signature.
pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool {
ed25519::verify(&sig[..], msg, &pubkey[..])
+2
View File
@@ -6,6 +6,8 @@ extern crate pwasm_libc;
#[cfg(feature = "nightly")]
extern crate pwasm_alloc;
extern crate polkadot_primitives as primitives;;
pub use alloc::vec;
pub use alloc::boxed;
pub use alloc::rc;
@@ -18,9 +18,9 @@
use runtime_std::prelude::*;
/// The digest of a block, useful for light-clients.
#[derive(Clone, Default)]
#[cfg_attr(feature = "std", derive(PartialEq, Debug))]
/// The digest of a block, useful for light-clients.
pub struct Digest {
/// All logs that have happened in the block.
pub logs: Vec<Vec<u8>>,
@@ -85,38 +85,6 @@ impl Slicable for Proposal {
}
}
impl Proposal {
pub fn enact(&self) {
let mut params = StreamReader::new(&self.input_data);
match self.function {
InternalFunction::SystemSetCode => {
let code: Vec<u8> = params.read().unwrap();
system::privileged::set_code(&code);
}
InternalFunction::StakingSetSessionsPerEra => {
let value = params.read().unwrap();
staking::privileged::set_sessions_per_era(value);
}
InternalFunction::StakingSetBondingDuration => {
let value = params.read().unwrap();
staking::privileged::set_bonding_duration(value);
}
InternalFunction::StakingSetValidatorCount => {
let value = params.read().unwrap();
staking::privileged::set_validator_count(value);
}
InternalFunction::GovernanceSetApprovalPpmRequired => {
let value = params.read().unwrap();
governance::privileged::set_approval_ppm_required(value);
}
InternalFunction::SessionSetLength => {
let value = params.read().unwrap();
session::privileged::set_length(value);
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
@@ -109,6 +109,36 @@ pub mod internal {
}
}
}
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();
system::privileged::set_code(&code);
}
InternalFunction::StakingSetSessionsPerEra => {
let value = params.read().unwrap();
staking::privileged::set_sessions_per_era(value);
}
InternalFunction::StakingSetBondingDuration => {
let value = params.read().unwrap();
staking::privileged::set_bonding_duration(value);
}
InternalFunction::StakingSetValidatorCount => {
let value = params.read().unwrap();
staking::privileged::set_validator_count(value);
}
InternalFunction::GovernanceSetApprovalPpmRequired => {
let value = params.read().unwrap();
governance::privileged::set_approval_ppm_required(value);
}
InternalFunction::SessionSetLength => {
let value = params.read().unwrap();
session::privileged::set_length(value);
}
}
}
}
#[cfg(test)]
@@ -49,6 +49,8 @@ pub mod privileged {
pub mod internal {
use super::*;
struct CheckedTransaction(UncheckedTransaction);
/// Deposits a log and ensures it matches the blocks log data.
pub fn deposit_log(log: &[u8]) {
with_env(|e| {
@@ -115,7 +117,40 @@ pub mod internal {
storage::put(&nonce_key, &(expected_nonce + 1));
// decode parameters and dispatch
tx.function.dispatch(&tx.signed, &tx.input_data);
dispatch_function(&tx.function, &tx.signed, &tx.input_data);
}
fn dispatch_function(function: &Function, transactor: &AccountId, data: &[u8]) {
let mut params = ::runtime_codec::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);
}
}
}
}