diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 500594e31a..b791fefdb7 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -8,6 +8,7 @@ extern crate runtime_support; extern crate rustc_hex; mod codec; +#[macro_use] mod support; mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 1112d45249..0a736b3b47 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -4,6 +4,16 @@ use storage::Storage; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; +// TRANSACTION API (available to all transactors) + +/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next +/// session. +pub fn set_key(_transactor: &AccountID, _session: &AccountID) { + // TODO: record the new session key for `_transactor`, ready for the next session. +} + +// PUBLIC API (available to other runtime modules) + /// Get the current set of validators. These are the long-term identifiers for the validators /// and will be mapped to a session key with the most recent `set_next_session_key`. pub fn validators() -> Vec { @@ -24,17 +34,6 @@ pub fn length() -> BlockNumber { Storage::into(b"con\0bps") } -/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next -/// session. -pub fn set_key(_transactor: &AccountID, _session: &AccountID) { - // TODO: record the new session key for `_transactor`, ready for the next session. -} - -/// Move onto next session: register the new authority set. -pub fn next_session() { - // TODO: Call set_authorities() with any new authorities. -} - /// Hook to be called prior to transaction processing. pub fn pre_transactions() { staking::pre_transactions(); @@ -51,3 +50,10 @@ pub fn post_transactions() { next_session(); } } + +// PRIVATE (not available) + +/// Move onto next session: register the new authority set. +fn next_session() { + // TODO: Call set_authorities() with any new authorities. +} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 366ad0668b..9b06602c84 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -3,6 +3,11 @@ use storage::Storage; use primitives::{BlockNumber, Balance, AccountID}; use runtime::{system, session}; +// Each validator's stake has one amount in each of three states: +// - inactive: free to be transferred +// - active: currently representing a validator +// - deactivating: recently representing a validator and not yet ready for transfer + /// The length of a staking era in blocks. pub fn era_length() -> BlockNumber { sessions_per_era() * session::length() @@ -13,21 +18,26 @@ pub fn sessions_per_era() -> BlockNumber { Storage::into(b"sta\0spe") } +/// The length of a staking era in sessions. +pub fn lockup_eras() -> BlockNumber { + Storage::into(b"sta\0lpe") +} + /// The era has changed - enact new staking set. /// /// NOTE: This always happens on a session change. -pub fn next_era() { +fn next_era() { // TODO: evaluate desired staking amounts and nominations and optimise to find the best // combination of validators, then use session::set_validators(). } /// The balance of a given account. -pub fn balance(who: &AccountID) -> Balance { +pub fn balance_inactive(who: &AccountID) -> Balance { Storage::into(&who.to_keyed_vec(b"sta\0bal\0")) } /// Transfer some unlocked staking balance to another staker. -pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) { +pub fn transfer_inactive(transactor: &AccountID, dest: &AccountID, value: Balance) { let from_key = transactor.to_keyed_vec(b"sta\0bal\0"); let from_balance: Balance = Storage::into(&from_key); assert!(from_balance >= value); @@ -42,14 +52,14 @@ pub fn transfer_stake(transactor: &AccountID, dest: &AccountID, value: Balance) /// /// Effects will be felt at the beginning of the next era. pub fn stake(_transactor: &AccountID) { - unimplemented!() + // TODO: record the desire for `_transactor` to activate their stake. } /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. pub fn unstake(_transactor: &AccountID) { - unimplemented!() + // TODO: record the desire for `_transactor` to deactivate their stake. } /// Hook to be called prior to transaction processing. @@ -88,8 +98,8 @@ mod tests { ], }; with_externalities(&mut t, || { - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 0); + assert_eq!(staking::balance_inactive(&one), 42); + assert_eq!(staking::balance_inactive(&two), 0); }); } @@ -103,9 +113,9 @@ mod tests { ], }; with_externalities(&mut t, || { - staking::transfer_stake(&one, &two, 69); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); + staking::transfer_inactive(&one, &two, 69); + assert_eq!(staking::balance_inactive(&one), 42); + assert_eq!(staking::balance_inactive(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 690e1db527..d7abd1835a 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -60,12 +60,6 @@ pub fn execute_block(mut block: Block) { // so will wait until a little later. } -fn final_checks(_block: &Block) { - with_env(|e| { - assert_eq!(e.next_log_index, e.digest.logs.len()); - }); -} - /// Execute a given transaction. pub fn execute_transaction(utx: &UncheckedTransaction) { // Verify the signature is good. @@ -90,45 +84,23 @@ pub fn set_code(new: &[u8]) { new.store(b"\0code"); } +fn final_checks(_block: &Block) { + with_env(|e| { + assert_eq!(e.next_log_index, e.digest.logs.len()); + }); +} + #[cfg(test)] mod tests { use joiner::Joiner; use function::Function; use keyedvec::KeyedVec; use slicable::Slicable; - use std::collections::HashMap; - use runtime_support::{NoError, with_externalities, Externalities}; - use primitives::{AccountID, UncheckedTransaction, Transaction, Hashable}; + use runtime_support::with_externalities; + use primitives::{UncheckedTransaction, Transaction}; use statichex::StaticHexInto; use runtime::{system, staking}; - use testing::HexDisplay; - - #[derive(Debug, Default)] - struct TestExternalities { - storage: HashMap, Vec>, - } - impl Externalities for TestExternalities { - type Error = NoError; - - fn storage(&self, key: &[u8]) -> Result<&[u8], NoError> { - Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) - } - - fn set_storage(&mut self, key: Vec, value: Vec) { - self.storage.insert(key, value); - } - - fn chain_id(&self) -> u64 { 42 } - } - - macro_rules! map { - ($( $name:expr => $value:expr ),*) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ) - } - - fn one() -> AccountID { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert() } - fn two() -> AccountID { "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert() } + use testing::{TestExternalities, HexDisplay, one, two}; #[test] fn staking_balance_transfer_dispatch_works() { @@ -143,7 +115,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 0, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: vec![].join(&two).join(&69u64), }, signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), @@ -155,8 +127,8 @@ mod tests { with_externalities(&mut t, || { system::execute_transaction(&tx); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); + assert_eq!(staking::balance_inactive(&one), 42); + assert_eq!(staking::balance_inactive(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 6d694c88ae..09c1d5bcbe 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -1,10 +1,36 @@ use primitives::Timestamp; use storage::Storage; -pub fn timestamp() -> Timestamp { +pub fn get() -> Timestamp { Storage::into(b"tim\0val") } -pub fn set_timestamp(now: Timestamp) { +pub fn set(now: Timestamp) { now.store(b"tim\0val") } + +#[cfg(test)] +mod tests { + use joiner::Joiner; + use function::Function; + use keyedvec::KeyedVec; + use slicable::Slicable; + use runtime_support::with_externalities; + use primitives::{UncheckedTransaction, Transaction}; + use statichex::StaticHexInto; + use runtime::{system, timestamp}; + use testing::{TestExternalities, HexDisplay, one, two}; + + #[test] + fn timestamp_works() { + let mut t = TestExternalities { storage: map![ + b"tim\0val".to_vec() => vec![].join(&42u64) + ], }; + + with_externalities(&mut t, || { + assert_eq!(timestamp::get(), 42); + timestamp::set(69); + assert_eq!(timestamp::get(), 69); + }); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index 995ec3c459..45dcea876b 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -1,6 +1,6 @@ -use runtime::{staking, session}; use primitives::AccountID; use streamreader::StreamReader; +use runtime::{staking, session, timestamp}; /// The functions that a transaction can call (and be dispatched to). #[cfg_attr(test, derive(PartialEq, Debug))] @@ -8,8 +8,9 @@ use streamreader::StreamReader; pub enum Function { StakingStake, StakingUnstake, - StakingTransferStake, + StakingTransferInactive, SessionSetKey, + TimestampSet, } impl Function { @@ -17,8 +18,9 @@ impl Function { match value { x if x == Function::StakingStake as u8 => Some(Function::StakingStake), x if x == Function::StakingUnstake as u8 => Some(Function::StakingUnstake), - x if x == Function::StakingTransferStake as u8 => Some(Function::StakingTransferStake), + x if x == Function::StakingTransferInactive as u8 => Some(Function::StakingTransferInactive), x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), + x if x == Function::TimestampSet as u8 => Some(Function::TimestampSet), _ => None, } } @@ -35,15 +37,19 @@ impl Function { Function::StakingUnstake => { staking::unstake(transactor); } - Function::StakingTransferStake => { + Function::StakingTransferInactive => { let dest = params.read().unwrap(); let value = params.read().unwrap(); - staking::transfer_stake(transactor, &dest, value); + staking::transfer_inactive(transactor, &dest, value); } Function::SessionSetKey => { let session = params.read().unwrap(); session::set_key(transactor, &session); } + Function::TimestampSet => { + let t = params.read().unwrap(); + timestamp::set(t); + } } } } diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 732552effd..11cb23e997 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -6,4 +6,5 @@ pub mod storage; #[cfg(test)] pub mod statichex; #[cfg(test)] +#[macro_use] pub mod testing; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index 4cf9dd9d32..ecac3fbbd4 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -253,7 +253,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }; let serialised = tx.to_vec(); @@ -274,7 +274,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }; let data = [ @@ -344,7 +344,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64], @@ -408,7 +408,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferStake, + function: Function::StakingTransferInactive, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64], diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index 5338add635..a617405e79 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -1,5 +1,7 @@ use runtime_support::{NoError, Externalities}; use std::collections::HashMap; +use primitives::AccountID; +use statichex::StaticHexInto; #[derive(Debug, Default)] pub struct TestExternalities { @@ -20,6 +22,20 @@ impl Externalities for TestExternalities { fn chain_id(&self) -> u64 { 42 } } +#[macro_export] +macro_rules! map { + ($( $name:expr => $value:expr ),*) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ) +} + +pub fn one() -> AccountID { + "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert() +} +pub fn two() -> AccountID { + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert() +} + pub struct HexDisplay<'a>(&'a [u8]); impl<'a> HexDisplay<'a> {