diff --git a/substrate/state_machine/src/lib.rs b/substrate/state_machine/src/lib.rs index cee96a36ad..d1357592d4 100644 --- a/substrate/state_machine/src/lib.rs +++ b/substrate/state_machine/src/lib.rs @@ -134,10 +134,10 @@ pub trait Externalities { /// Get the current set of authorities from storage. fn authorities(&self) -> Result, Self::Error> { - (0..self.storage(b"con\0aut\0len")?.into_iter() + (0..self.storage(b"con:aut:len")?.into_iter() .rev() .fold(0, |acc, &i| (acc << 8) + (i as u32))) - .map(|i| self.storage(&to_keyed_vec(i, b"con\0aut\0".to_vec()))) + .map(|i| self.storage(&to_keyed_vec(i, b"con:aut:".to_vec()))) .collect() } } @@ -177,7 +177,7 @@ pub fn execute( overlay: &mut *overlay }; // make a copy. - let code = externalities.storage(b"\0code").unwrap_or(&[]).to_vec(); + let code = externalities.storage(b":code").unwrap_or(&[]).to_vec(); exec.call( &mut externalities, @@ -253,17 +253,17 @@ mod tests { assert_eq!(ext.authorities(), Ok(vec![])); - ext.set_storage(b"con\0aut\0len".to_vec(), vec![0u8; 4]); + ext.set_storage(b"con:aut:len".to_vec(), vec![0u8; 4]); assert_eq!(ext.authorities(), Ok(vec![])); - ext.set_storage(b"con\0aut\0len".to_vec(), vec![1u8, 0, 0, 0]); + ext.set_storage(b"con:aut:len".to_vec(), vec![1u8, 0, 0, 0]); assert_eq!(ext.authorities(), Ok(vec![&[][..]])); - ext.set_storage(b"con\0aut\0\0\0\0\0".to_vec(), b"first".to_vec()); + ext.set_storage(b"con:aut:::::".to_vec(), b"first".to_vec()); assert_eq!(ext.authorities(), Ok(vec![&b"first"[..]])); - ext.set_storage(b"con\0aut\0len".to_vec(), vec![2u8, 0, 0, 0]); - ext.set_storage(b"con\0aut\0\x01\0\0\0".to_vec(), b"second".to_vec()); + ext.set_storage(b"con:aut:len".to_vec(), vec![2u8, 0, 0, 0]); + ext.set_storage(b"con:aut:\x01:::".to_vec(), b"second".to_vec()); assert_eq!(ext.authorities(), Ok(vec![&b"first"[..], &b"second"[..]])); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs index 02bf288493..757c032f03 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/consensus.rs @@ -5,7 +5,7 @@ use primitives::SessionKey; struct AuthorityStorageVec {} impl StorageVec for AuthorityStorageVec { type Item = SessionKey; - const PREFIX: &'static[u8] = b"con\0aut\0"; + const PREFIX: &'static[u8] = b"con:aut:"; } /// Get the current set of authorities. These are the session keys. diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 687dedfc5b..cc572ea842 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -7,7 +7,7 @@ use runtime::{system, staking, consensus}; struct ValidatorStorageVec {} impl StorageVec for ValidatorStorageVec { type Item = AccountID; - const PREFIX: &'static[u8] = b"ses\0key\0"; + const PREFIX: &'static[u8] = b"ses:key:"; } // TRANSACTION API (available to all transactors) @@ -16,7 +16,7 @@ impl StorageVec for ValidatorStorageVec { /// 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")); + key.store(&validator.to_keyed_vec(b"ses:nxt:")); } // PUBLIC API (available to other runtime modules) @@ -37,27 +37,27 @@ pub fn set_validators(new: &[AccountID]) { /// The number of blocks in each session. pub fn length() -> BlockNumber { - Storable::lookup_default(b"ses\0len") + Storable::lookup_default(b"ses:len") } /// The current era index. pub fn current_index() -> BlockNumber { - Storable::lookup_default(b"ses\0ind") + Storable::lookup_default(b"ses:ind") } /// Set the current era index. pub fn set_current_index(new: BlockNumber) { - new.store(b"ses\0ind"); + new.store(b"ses:ind"); } /// The block number at which the era length last changed. pub fn last_length_change() -> BlockNumber { - Storable::lookup_default(b"ses\0llc") + Storable::lookup_default(b"ses:llc") } /// Set a new era length. Won't kick in until the next era change (at current length). pub fn set_length(new: BlockNumber) { - new.store(b"ses\0nln"); + new.store(b"ses:nln"); } /// Hook to be called after transaction processing. @@ -78,15 +78,15 @@ fn rotate_session() { set_current_index(current_index() + 1); // Enact era length change. - if let Some(next_len) = u64::lookup(b"ses\0nln") { - next_len.store(b"ses\0len"); - system::block_number().store(b"ses\0llc"); - kill(b"ses\0nln"); + if let Some(next_len) = u64::lookup(b"ses:nln") { + next_len.store(b"ses:len"); + system::block_number().store(b"ses:llc"); + kill(b"ses:nln"); } // Update any changes in session keys. validators().iter().enumerate().for_each(|(i, v)| { - let k = v.to_keyed_vec(b"ses\0nxt\0"); + let k = v.to_keyed_vec(b"ses:nxt:"); if let Some(n) = Storable::lookup(&k) { consensus::set_authority(i as u32, &n); kill(&k); @@ -106,15 +106,15 @@ mod tests { fn simple_setup() -> TestExternalities { TestExternalities { storage: map![ - twox_128(b"ses\0len").to_vec() => vec![].join(&2u64), + twox_128(b"ses:len").to_vec() => vec![].join(&2u64), // the validators (10, 20, ...) - twox_128(b"ses\0key\0len").to_vec() => vec![].join(&2u32), - twox_128(&0u32.to_keyed_vec(b"ses\0key\0")).to_vec() => vec![10; 32], - twox_128(&1u32.to_keyed_vec(b"ses\0key\0")).to_vec() => vec![20; 32], + twox_128(b"ses:key:len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"ses:key:")).to_vec() => vec![10; 32], + twox_128(&1u32.to_keyed_vec(b"ses:key:")).to_vec() => vec![20; 32], // initial session keys (11, 21, ...) - twox_128(b"con\0aut\0len").to_vec() => vec![].join(&2u32), - twox_128(&0u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![11; 32], - twox_128(&1u32.to_keyed_vec(b"con\0aut\0")).to_vec() => vec![21; 32] + twox_128(b"con:aut:len").to_vec() => vec![].join(&2u32), + twox_128(&0u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![11; 32], + twox_128(&1u32.to_keyed_vec(b"con:aut:")).to_vec() => vec![21; 32] ], } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index 64b64521bd..1406cd96ce 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -1,16 +1,30 @@ use keyedvec::KeyedVec; -use storable::Storable; +use storable::{Storable, StorageVec}; 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. +type Liquidity = u64; + +struct IntentionStorageVec {} +impl StorageVec for IntentionStorageVec { + type Item = AccountID; + const PREFIX: &'static[u8] = b"ses:wil:"; +} + +// Each identity's stake may be in one of three bondage states, given by an integer: +// - n | n <= system::block_number(): inactive: free to be transferred. +// - ~0: active: currently representing a validator. +// - n | n > system::block_number(): deactivating: recently representing a validator and not yet +// ready for transfer. /// The length of a staking era in sessions. -pub fn lockup_eras() -> BlockNumber { - Storable::lookup_default(b"sta\0lpe") +pub fn eras_per_lockup() -> BlockNumber { + Storable::lookup_default(b"sta:epl") +} + +/// The length of a staking era in sessions. +pub fn validator_count() -> usize { + Storable::lookup_default(b"sta:vac") } /// The length of a staking era in blocks. @@ -20,27 +34,27 @@ pub fn era_length() -> BlockNumber { /// The length of a staking era in sessions. pub fn sessions_per_era() -> BlockNumber { - Storable::lookup_default(b"sta\0spe") + Storable::lookup_default(b"sta:spe") } /// The current era index. pub fn current_era() -> BlockNumber { - Storable::lookup_default(b"sta\0era") + Storable::lookup_default(b"sta:era") } /// Set the current era index. pub fn set_current_era(new: BlockNumber) { - new.store(b"sta\0era"); + new.store(b"sta:era"); } /// The block number at which the era length last changed. pub fn last_era_length_change() -> BlockNumber { - Storable::lookup_default(b"sta\0lec") + Storable::lookup_default(b"sta:lec") } /// Set a new era length. Won't kick in until the next era change (at current length). pub fn set_sessions_per_era(new: BlockNumber) { - new.store(b"sta\0nse"); + new.store(b"sta:nse"); } /// The era has changed - enact new staking set. @@ -51,28 +65,48 @@ fn new_era() { set_current_era(current_era() + 1); // Enact era length change. - let next_spe: u64 = Storable::lookup_default(b"sta\0nse"); + let next_spe: u64 = Storable::lookup_default(b"sta:nse"); if next_spe > 0 && next_spe != sessions_per_era() { - next_spe.store(b"sta\0spe"); - system::block_number().store(b"sta\0lec"); + next_spe.store(b"sta:spe"); + system::block_number().store(b"sta:lec"); } // TODO: evaluate desired staking amounts and nominations and optimise to find the best // combination of validators, then use session::set_validators(). + + // for now, this just orders would-be stakers by their balances and chooses the top-most + // validator_count() of them. + let mut intentions = IntentionStorageVec::items() + .into_iter() + .map(|v| (balance(&v), v)) + .collect::>(); + intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1)); + session::set_validators( + &intentions.into_iter() + .map(|(_, v)| v) + .take(validator_count()) + .collect::>() + ); } /// The balance of a given account. -pub fn balance_inactive(who: &AccountID) -> Balance { - Storable::lookup_default(&who.to_keyed_vec(b"sta\0bal\0")) +pub fn balance(who: &AccountID) -> Balance { + Storable::lookup_default(&who.to_keyed_vec(b"sta:bal:")) +} + +/// The liquidity-state of a given account. +pub fn bondage(who: &AccountID) -> Liquidity { + Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:")) } /// Transfer some unlocked staking balance to another staker. -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 = Storable::lookup_default(&from_key); +pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { + let from_key = transactor.to_keyed_vec(b"sta:bal:"); + let from_balance = Balance::lookup_default(&from_key); assert!(from_balance >= value); - let to_key = dest.to_keyed_vec(b"sta\0bal\0"); + let to_key = dest.to_keyed_vec(b"sta:bal:"); let to_balance: Balance = Storable::lookup_default(&to_key); + assert!(bondage(transactor) <= bondage(dest)); assert!(to_balance + value > to_balance); // no overflow (from_balance - value).store(&from_key); (to_balance + value).store(&to_key); @@ -81,15 +115,22 @@ pub fn transfer_inactive(transactor: &AccountID, dest: &AccountID, value: Balanc /// Declare the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. -pub fn stake(_transactor: &AccountID) { - // TODO: record the desire for `_transactor` to activate their stake. +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()); + intentions.push(transactor.clone()); + IntentionStorageVec::set_items(&intentions); } /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. -pub fn unstake(_transactor: &AccountID) { - // TODO: record the desire for `_transactor` to deactivate their stake. +pub fn unstake(transactor: &AccountID) { + let mut intentions = IntentionStorageVec::items(); + // TODO: use swap remove. + let intentions = intentions.into_iter().filter(|t| t != transactor).collect::>(); + IntentionStorageVec::set_items(&intentions); } /// Hook to be called after to transaction processing. @@ -113,8 +154,8 @@ mod tests { #[test] fn staking_eras_work() { let mut t = TestExternalities { storage: map![ - twox_128(b"ses\0len").to_vec() => vec![].join(&1u64), - twox_128(b"sta\0spe").to_vec() => vec![].join(&2u64) + twox_128(b"ses:len").to_vec() => vec![].join(&1u64), + twox_128(b"sta:spe").to_vec() => vec![].join(&2u64) ], }; with_externalities(&mut t, || { assert_eq!(staking::era_length(), 2u64); @@ -180,12 +221,12 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![].join(&42u64) + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { - assert_eq!(staking::balance_inactive(&one), 42); - assert_eq!(staking::balance_inactive(&two), 0); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 0); }); } @@ -195,13 +236,13 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![].join(&111u64) + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![].join(&111u64) ], }; with_externalities(&mut t, || { - staking::transfer_inactive(&one, &two, 69); - assert_eq!(staking::balance_inactive(&one), 42); - assert_eq!(staking::balance_inactive(&two), 69); + staking::transfer(&one, &two, 69); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 0bf300d2b3..f96bc40c93 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -12,7 +12,7 @@ pub fn block_number() -> BlockNumber { /// Get the block hash of a given block (uses storage). pub fn block_hash(number: BlockNumber) -> Hash { - Storable::lookup_default(&number.to_keyed_vec(b"sys\0old\0")) + Storable::lookup_default(&number.to_keyed_vec(b"sys:old:")) } /// Deposits a log and ensures it matches the blocks log data. @@ -44,7 +44,7 @@ pub fn execute_block(mut block: Block) { // so will wait until a little later. // store the header hash in storage. - let header_hash_key = header.number.to_keyed_vec(b"sys\0old\0"); + let header_hash_key = header.number.to_keyed_vec(b"sys:old:"); header.blake2_256().store(&header_hash_key); // execute transactions @@ -69,7 +69,7 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { let ref tx = utx.transaction; // check nonce - let nonce_key = tx.signed.to_keyed_vec(b"sys\0non\0"); + let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); let expected_nonce: TxOrder = Storable::lookup_default(&nonce_key); assert!(tx.nonce == expected_nonce, "All transactions should have the correct nonce"); @@ -82,7 +82,7 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { /// Set the new code. pub fn set_code(new: &[u8]) { - new.store(b"\0code"); + new.store(b":code"); } fn final_checks(_block: &Block) { @@ -109,14 +109,14 @@ mod tests { let two = two(); let mut t = TestExternalities { storage: map![ - twox_128(&one.to_keyed_vec(b"sta\0bal\0")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ], }; let tx = UncheckedTransaction { transaction: Transaction { signed: one.clone(), nonce: 0, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: vec![].join(&two).join(&69u64), }, signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), @@ -128,8 +128,8 @@ mod tests { with_externalities(&mut t, || { system::execute_transaction(&tx); - assert_eq!(staking::balance_inactive(&one), 42); - assert_eq!(staking::balance_inactive(&two), 69); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); }); } } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index 10708a5a3c..c6a3ac2a96 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -2,11 +2,11 @@ use primitives::Timestamp; use storable::Storable; pub fn get() -> Timestamp { - Storable::lookup_default(b"tim\0val") + Storable::lookup_default(b"tim:val") } pub fn set(now: Timestamp) { - now.store(b"tim\0val") + now.store(b"tim:val") } #[cfg(test)] @@ -20,7 +20,7 @@ mod tests { #[test] fn timestamp_works() { let mut t = TestExternalities { storage: map![ - twox_128(b"tim\0val").to_vec() => vec![].join(&42u64) + twox_128(b"tim:val").to_vec() => vec![].join(&42u64) ], }; with_externalities(&mut t, || { diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index 45dcea876b..f0be93c4af 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -8,7 +8,7 @@ use runtime::{staking, session, timestamp}; pub enum Function { StakingStake, StakingUnstake, - StakingTransferInactive, + StakingTransfer, SessionSetKey, TimestampSet, } @@ -18,7 +18,7 @@ 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::StakingTransferInactive as u8 => Some(Function::StakingTransferInactive), + x if x == Function::StakingTransfer as u8 => Some(Function::StakingTransfer), x if x == Function::SessionSetKey as u8 => Some(Function::SessionSetKey), x if x == Function::TimestampSet as u8 => Some(Function::TimestampSet), _ => None, @@ -37,10 +37,10 @@ impl Function { Function::StakingUnstake => { staking::unstake(transactor); } - Function::StakingTransferInactive => { + Function::StakingTransfer => { let dest = params.read().unwrap(); let value = params.read().unwrap(); - staking::transfer_inactive(transactor, &dest, value); + staking::transfer(transactor, &dest, value); } Function::SessionSetKey => { let session = params.read().unwrap(); diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index fb983bf84e..dbe75aad11 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -261,7 +261,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }; let serialised = tx.to_vec(); @@ -282,7 +282,7 @@ mod tests { let tx = Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }; let data = [ @@ -352,7 +352,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64], @@ -416,7 +416,7 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 69, - function: Function::StakingTransferInactive, + function: Function::StakingTransfer, input_data: Vec::new().join(&two).join(&69u64), }, signature: [1u8; 64],