diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index b791fefdb7..4a1302a756 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -12,7 +12,7 @@ mod codec; mod support; mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; -pub use support::{primitives, function, environment, storage}; +pub use support::{primitives, function, environment, storage, storagevec}; #[cfg(test)] pub use support::{testing, statichex}; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index f8991e8871..b773e7e1e6 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -1,35 +1,26 @@ use runtime_support::Vec; -use keyedvec::KeyedVec; -use storage::Storage; -use primitives::{AccountID, SessionKey, BlockNumber}; -use runtime::{system, staking}; +use storagevec::StorageVec; +use primitives::SessionKey; -pub fn set_authority(index: u32, authority: AccountID) { - authority.store(&index.to_keyed_vec(b"con\0aut\0")); -} - -fn authority(index: u32) -> AccountID { - Storage::into(&index.to_keyed_vec(b"con\0aut\0")) -} - -pub fn set_authority_count(count: u32) { - (count..authority_count()).for_each(|i| set_authority(i, SessionKey::default())); - count.store(b"con\0aut\0len"); -} - -fn authority_count() -> u32 { - Storage::into(b"con\0aut\0len") +struct AuthorityStorageVec {} +impl StorageVec for AuthorityStorageVec { + type Item = SessionKey; + const PREFIX: &'static[u8] = b"con\0aut\0"; } /// Get the current set of authorities. These are the session keys. -pub fn authorities() -> Vec { - (0..authority_count()).into_iter().map(authority).collect() +pub fn authorities() -> Vec { + AuthorityStorageVec::items() } /// Set the current set of authorities' session keys. /// /// Called by `next_session` only. -pub fn set_authorities(authorities: &[AccountID]) { - set_authority_count(authorities.len() as u32); - authorities.iter().enumerate().for_each(|(v, &i)| set_authority(v as u32, i)); +pub fn set_authorities(authorities: &[SessionKey]) { + AuthorityStorageVec::set_items(authorities); +} + +/// Set a single authority by index. +pub fn set_authority(index: u32, key: &SessionKey) { + AuthorityStorageVec::set_item(index, key); } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs index 8e60ec431c..55a4801a5b 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/mod.rs @@ -8,3 +8,5 @@ pub mod staking; pub mod timestamp; #[allow(unused)] pub mod session; + +// TODO: governance, polkadao diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 2ed6c7a0a2..8e133ad563 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -1,31 +1,38 @@ use runtime_support::Vec; use keyedvec::KeyedVec; use storage::Storage; +use storagevec::StorageVec; use primitives::{AccountID, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; +struct ValidatorStorageVec {} +impl StorageVec for ValidatorStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"ses\0key\0"; +} + // TRANSACTION API (available to all transactors) -/// Sets the session key of `_transactor` to `_session`. This doesn't take effect until the next +/// Sets the session key of `_validator` to `_key`. 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. +pub fn set_key(validator: &AccountID, key: &SessionKey) { + // set new value for next session + key.store(&validator.to_keyed_vec(b"ses\0nxt\0")); } // 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 { - // TODO: derive from the actual validator set - consensus::authorities() +/// Get the current set of authorities. These are the session keys. +fn validators() -> Vec { + ValidatorStorageVec::items() } /// Set the current set of validators. /// -/// Called by staking::next_era() only. +/// 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]) { - // TODO: set the actual validators + ValidatorStorageVec::set_items(new); consensus::set_authorities(new); } @@ -56,4 +63,10 @@ pub fn post_transactions() { /// Move onto next session: register the new authority set. fn next_session() { // TODO: Call set_authorities() with any new authorities. + validators().iter().enumerate().for_each(|(i, v)| { + let k = v.to_keyed_vec(b"ses\0nxt\0"); + if let Some(n) = Storage::try_into(&k) { + consensus::set_authority(i as u32, &n); + } + }) } diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 11cb23e997..e4dae46c40 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -2,6 +2,7 @@ pub mod primitives; pub mod function; pub mod environment; pub mod storage; +pub mod storagevec; #[cfg(test)] pub mod statichex; diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index becb4f7fb2..7c9696bc11 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -3,14 +3,14 @@ use endiansensitive::EndianSensitive; use runtime_support; pub trait Storage { - fn into(_key: &[u8]) -> Self where Self: Sized { unimplemented!() } + fn into(key: &[u8]) -> Self where Self: Sized + Default { Self::try_into(key).unwrap_or_else(Default::default) } + fn try_into(_key: &[u8]) -> Option where Self: Sized { unimplemented!() } fn store(&self, key: &[u8]); } impl Storage for T { - fn into(key: &[u8]) -> Self { + fn try_into(key: &[u8]) -> Option { Slicable::set_as_slice(|out| runtime_support::read_storage(key, out) == out.len()) - .unwrap_or_else(Default::default) } fn store(&self, key: &[u8]) { self.as_slice_then(|slice| runtime_support::set_storage(key, slice)); diff --git a/substrate/wasm-runtime/polkadot/src/support/storagevec.rs b/substrate/wasm-runtime/polkadot/src/support/storagevec.rs new file mode 100644 index 0000000000..ac0ded3a56 --- /dev/null +++ b/substrate/wasm-runtime/polkadot/src/support/storagevec.rs @@ -0,0 +1,38 @@ +use runtime_support::Vec; +use keyedvec::KeyedVec; +use storage::Storage; + +/// A trait to conveniently store a vector of storable data. +// TODO: add iterator support +pub trait StorageVec { + type Item: Default + Sized + Storage; + const PREFIX: &'static [u8]; + + /// Get the current set of items. + fn items() -> Vec { + (0..Self::count()).into_iter().map(Self::item).collect() + } + + /// Set the current set of items. + fn set_items(items: &[Self::Item]) { + Self::set_count(items.len() as u32); + items.iter().enumerate().for_each(|(v, ref i)| Self::set_item(v as u32, i)); + } + + fn set_item(index: u32, item: &Self::Item) { + item.store(&index.to_keyed_vec(Self::PREFIX)); + } + + fn item(index: u32) -> Self::Item { + Storage::into(&index.to_keyed_vec(Self::PREFIX)) + } + + fn set_count(count: u32) { + (count..Self::count()).for_each(|i| Self::set_item(i, &Self::Item::default())); + count.store(&b"len".to_keyed_vec(Self::PREFIX)); + } + + fn count() -> u32 { + Storage::into(&b"len".to_keyed_vec(Self::PREFIX)) + } +}