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
@@ -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)