diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 66309becaf..ee88937ead 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -40,27 +40,20 @@ pub fn length() -> BlockNumber { Storable::lookup_default(b"ses\0bps") } -/// Hook to be called prior to transaction processing. -pub fn pre_transactions() { - staking::pre_transactions(); -} - -/// Hook to be called after to transaction processing. -pub fn post_transactions() { - staking::post_transactions(); - +/// Hook to be called after transaction processing. +pub fn check_rotate_session() { // do this last, after the staking system has had chance to switch out the authorities for the // new set. // check block number and call next_session if necessary. if system::block_number() % length() == 0 { - next_session(); + rotate_session(); } } -// PRIVATE (not available) +// PRIVATE (not available for use externally) /// Move onto next session: register the new authority set. -fn next_session() { +fn rotate_session() { validators().iter().enumerate().for_each(|(i, v)| { let k = v.to_keyed_vec(b"ses\0nxt\0"); if let Some(n) = Storable::lookup(&k) { @@ -70,4 +63,56 @@ fn next_session() { }); } -// TODO: tests +#[cfg(test)] +mod tests { + use runtime_support::with_externalities; + use keyedvec::KeyedVec; + use joiner::Joiner; + use testing::{one, two, TestExternalities}; + use primitives::AccountID; + use runtime::{consensus, session}; + use environment::with_env; + + #[test] + fn session_change_should_work() { + let mut t = TestExternalities { storage: map![ + b"ses\0bps".to_vec() => vec![].join(&2u64), + // the validators (10, 20, ...) + b"ses\0key\0len".to_vec() => vec![].join(&2u32), + 0u32.to_keyed_vec(b"ses\0key\0") => vec![10; 32], + 1u32.to_keyed_vec(b"ses\0key\0") => vec![20; 32], + // initial session keys (11, 21, ...) + b"con\0aut\0len".to_vec() => vec![].join(&2u32), + 0u32.to_keyed_vec(b"con\0aut\0") => vec![11; 32], + 1u32.to_keyed_vec(b"con\0aut\0") => vec![21; 32] + ], }; + with_externalities(&mut t, || { + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + assert_eq!(session::length(), 2u64); + assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); + + // Block 1: No change + with_env(|e| e.block_number = 1); + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + // Block 2: Session rollover, but no change. + with_env(|e| e.block_number = 2); + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + // Block 3: Set new key for validator 2; no visible change. + with_env(|e| e.block_number = 3); + session::set_key(&[20; 32], &[22; 32]); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [21u8; 32]]); + + // Block 4: Session rollover, authority 2 changes. + with_env(|e| e.block_number = 4); + session::check_rotate_session(); + assert_eq!(consensus::authorities(), vec![[11u8; 32], [22u8; 32]]); + }); + } +} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 29d6ac0272..127b7041ad 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -46,7 +46,7 @@ pub fn set_sessions_per_era(new: BlockNumber) { /// The era has changed - enact new staking set. /// /// NOTE: This always happens on a session change. -fn next_era() { +fn new_era() { // Increment current era. set_current_era(current_era() + 1); @@ -92,15 +92,11 @@ pub fn unstake(_transactor: &AccountID) { // TODO: record the desire for `_transactor` to deactivate their stake. } -/// Hook to be called prior to transaction processing. -pub fn pre_transactions() { -} - /// Hook to be called after to transaction processing. -pub fn post_transactions() { - // check block number and call next_era if necessary. +pub fn check_new_era() { + // check block number and call new_era if necessary. if (system::block_number() - last_era_length_change()) % era_length() == 0 { - next_era(); + new_era(); } } @@ -128,14 +124,14 @@ mod tests { // Block 1: No change. with_env(|e| e.block_number = 1); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 2u64); assert_eq!(staking::last_era_length_change(), 0u64); assert_eq!(staking::current_era(), 0u64); // Block 2: Simple era change. with_env(|e| e.block_number = 2); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 2u64); assert_eq!(staking::last_era_length_change(), 0u64); assert_eq!(staking::current_era(), 1u64); @@ -143,35 +139,35 @@ mod tests { // Block 3: Schedule an era length change; no visible changes. with_env(|e| e.block_number = 3); staking::set_sessions_per_era(3); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 2u64); assert_eq!(staking::last_era_length_change(), 0u64); assert_eq!(staking::current_era(), 1u64); // Block 4: Era change kicks in. with_env(|e| e.block_number = 4); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 2u64); // Block 5: No change. with_env(|e| e.block_number = 5); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 2u64); // Block 6: No change. with_env(|e| e.block_number = 6); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 2u64); // Block 7: Era increment. with_env(|e| e.block_number = 7); - staking::post_transactions(); + staking::check_new_era(); assert_eq!(staking::sessions_per_era(), 3u64); assert_eq!(staking::last_era_length_change(), 4u64); assert_eq!(staking::current_era(), 3u64); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index f6be199625..0b3b8a590b 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -3,7 +3,7 @@ use runtime_support::{Vec, swap}; use storable::Storable; use keyedvec::KeyedVec; use environment::with_env; -use runtime::session; +use runtime::{staking, session}; /// The current block number being processed. Set by `execute_block`. pub fn block_number() -> BlockNumber { @@ -48,9 +48,10 @@ pub fn execute_block(mut block: Block) { header.keccak256().store(&header_hash_key); // execute transactions - session::pre_transactions(); block.transactions.iter().for_each(execute_transaction); - session::post_transactions(); + + staking::check_new_era(); + session::check_rotate_session(); // any final checks final_checks(&block);