mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 05:41:07 +00:00
Introduce module structure over comments.
This commit is contained in:
@@ -29,88 +29,6 @@ pub type Balance = u64;
|
||||
/// The amount of bonding period left in an account. Measured in eras.
|
||||
pub type Bondage = u64;
|
||||
|
||||
struct IntentionStorageVec {}
|
||||
impl StorageVec for IntentionStorageVec {
|
||||
type Item = AccountID;
|
||||
const PREFIX: &'static[u8] = b"sta:wil:";
|
||||
}
|
||||
|
||||
// Each identity's stake may be in one of three bondage states, given by an integer:
|
||||
// - n | n <= current_era(): inactive: free to be transferred.
|
||||
// - ~0: active: currently representing a validator.
|
||||
// - n | n > current_era(): deactivating: recently representing a validator and not yet
|
||||
// ready for transfer.
|
||||
|
||||
// TRANSACTION API
|
||||
|
||||
/// Transfer some unlocked staking balance to another staker.
|
||||
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: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);
|
||||
}
|
||||
|
||||
/// Declare the desire to stake for the transactor.
|
||||
///
|
||||
/// Effects will be felt at the beginning of the next era.
|
||||
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.");
|
||||
intentions.push(transactor.clone());
|
||||
IntentionStorageVec::set_items(&intentions);
|
||||
u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:"));
|
||||
}
|
||||
|
||||
/// Retract the desire to stake for the transactor.
|
||||
///
|
||||
/// Effects will be felt at the beginning of the next era.
|
||||
pub fn unstake(transactor: &AccountID) {
|
||||
let mut intentions = IntentionStorageVec::items();
|
||||
if let Some(position) = intentions.iter().position(|t| t == transactor) {
|
||||
intentions.swap_remove(position);
|
||||
} else {
|
||||
panic!("Cannot unstake if not already staked.");
|
||||
}
|
||||
IntentionStorageVec::set_items(&intentions);
|
||||
(current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:"));
|
||||
}
|
||||
|
||||
// PRIVILEDGED API
|
||||
|
||||
/// Set the number of sessions in an era.
|
||||
pub fn set_sessions_per_era(new: BlockNumber) {
|
||||
new.store(b"sta:nse");
|
||||
}
|
||||
|
||||
/// The length of the bonding duration in eras.
|
||||
pub fn set_bonding_duration(new: BlockNumber) {
|
||||
new.store(b"sta:loc");
|
||||
}
|
||||
|
||||
/// The length of a staking era in sessions.
|
||||
pub fn set_validator_count(new: usize) {
|
||||
(new as u32).store(b"sta:vac");
|
||||
}
|
||||
|
||||
// INTERNAL API
|
||||
|
||||
/// Hook to be called after to transaction processing.
|
||||
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 {
|
||||
new_era();
|
||||
}
|
||||
}
|
||||
|
||||
// INSPECTION API
|
||||
|
||||
/// The length of the bonding duration in eras.
|
||||
pub fn bonding_duration() -> BlockNumber {
|
||||
Storable::lookup_default(b"sta:loc")
|
||||
@@ -151,7 +69,91 @@ pub fn bondage(who: &AccountID) -> Bondage {
|
||||
Storable::lookup_default(&who.to_keyed_vec(b"sta:bon:"))
|
||||
}
|
||||
|
||||
// PRIVATE
|
||||
// Each identity's stake may be in one of three bondage states, given by an integer:
|
||||
// - n | n <= current_era(): inactive: free to be transferred.
|
||||
// - ~0: active: currently representing a validator.
|
||||
// - n | n > current_era(): deactivating: recently representing a validator and not yet
|
||||
// ready for transfer.
|
||||
|
||||
pub mod public {
|
||||
use super::*;
|
||||
|
||||
/// Transfer some unlocked staking balance to another staker.
|
||||
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: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);
|
||||
}
|
||||
|
||||
/// Declare the desire to stake for the transactor.
|
||||
///
|
||||
/// Effects will be felt at the beginning of the next era.
|
||||
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.");
|
||||
intentions.push(transactor.clone());
|
||||
IntentionStorageVec::set_items(&intentions);
|
||||
u64::max_value().store(&transactor.to_keyed_vec(b"sta:bon:"));
|
||||
}
|
||||
|
||||
/// Retract the desire to stake for the transactor.
|
||||
///
|
||||
/// Effects will be felt at the beginning of the next era.
|
||||
pub fn unstake(transactor: &AccountID) {
|
||||
let mut intentions = IntentionStorageVec::items();
|
||||
if let Some(position) = intentions.iter().position(|t| t == transactor) {
|
||||
intentions.swap_remove(position);
|
||||
} else {
|
||||
panic!("Cannot unstake if not already staked.");
|
||||
}
|
||||
IntentionStorageVec::set_items(&intentions);
|
||||
(current_era() + bonding_duration()).store(&transactor.to_keyed_vec(b"sta:bon:"));
|
||||
}
|
||||
}
|
||||
|
||||
pub mod privileged {
|
||||
use super::*;
|
||||
|
||||
/// Set the number of sessions in an era.
|
||||
pub fn set_sessions_per_era(new: BlockNumber) {
|
||||
new.store(b"sta:nse");
|
||||
}
|
||||
|
||||
/// The length of the bonding duration in eras.
|
||||
pub fn set_bonding_duration(new: BlockNumber) {
|
||||
new.store(b"sta:loc");
|
||||
}
|
||||
|
||||
/// The length of a staking era in sessions.
|
||||
pub fn set_validator_count(new: usize) {
|
||||
(new as u32).store(b"sta:vac");
|
||||
}
|
||||
}
|
||||
|
||||
pub mod internal {
|
||||
use super::*;
|
||||
|
||||
/// Hook to be called after to transaction processing.
|
||||
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 {
|
||||
new_era();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct IntentionStorageVec {}
|
||||
impl StorageVec for IntentionStorageVec {
|
||||
type Item = AccountID;
|
||||
const PREFIX: &'static[u8] = b"sta:wil:";
|
||||
}
|
||||
|
||||
/// The era has changed - enact new staking set.
|
||||
///
|
||||
@@ -159,7 +161,7 @@ pub fn bondage(who: &AccountID) -> Bondage {
|
||||
/// get a chance to set their session keys.
|
||||
fn new_era() {
|
||||
// Inform governance module that it's the end of an era
|
||||
governance::end_of_an_era();
|
||||
governance::internal::end_of_an_era();
|
||||
|
||||
// Increment current era.
|
||||
(current_era() + 1).store(b"sta:era");
|
||||
@@ -172,7 +174,7 @@ fn new_era() {
|
||||
}
|
||||
|
||||
// evaluate desired staking amounts and nominations and optimise to find the best
|
||||
// combination of validators, then use session::set_validators().
|
||||
// combination of validators, then use session::internal::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()
|
||||
@@ -180,7 +182,7 @@ fn new_era() {
|
||||
.map(|v| (balance(&v), v))
|
||||
.collect::<Vec<_>>();
|
||||
intentions.sort_unstable_by(|&(b1, _), &(b2, _)| b2.cmp(&b1));
|
||||
session::set_validators(
|
||||
session::internal::set_validators(
|
||||
&intentions.into_iter()
|
||||
.map(|(_, v)| v)
|
||||
.take(validator_count())
|
||||
@@ -190,13 +192,16 @@ fn new_era() {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::internal::*;
|
||||
use super::public::*;
|
||||
use super::privileged::*;
|
||||
|
||||
use runtime_std::{with_externalities, twox_128};
|
||||
use keyedvec::KeyedVec;
|
||||
use joiner::Joiner;
|
||||
use testing::{one, two, TestExternalities};
|
||||
use codec::{KeyedVec, Joiner};
|
||||
use support::{one, two, TestExternalities, with_env};
|
||||
use primitives::AccountID;
|
||||
use runtime::{staking, session};
|
||||
use environment::with_env;
|
||||
|
||||
#[test]
|
||||
fn staking_should_work() {
|
||||
@@ -220,54 +225,54 @@ mod tests {
|
||||
], };
|
||||
|
||||
with_externalities(&mut t, || {
|
||||
assert_eq!(staking::era_length(), 2u64);
|
||||
assert_eq!(staking::validator_count(), 2usize);
|
||||
assert_eq!(staking::bonding_duration(), 3u64);
|
||||
assert_eq!(era_length(), 2u64);
|
||||
assert_eq!(validator_count(), 2usize);
|
||||
assert_eq!(bonding_duration(), 3u64);
|
||||
assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]);
|
||||
|
||||
// Block 1: Add three validators. No obvious change.
|
||||
with_env(|e| e.block_number = 1);
|
||||
staking::stake(&one);
|
||||
staking::stake(&two);
|
||||
staking::stake(&four);
|
||||
staking::check_new_era();
|
||||
stake(&one);
|
||||
stake(&two);
|
||||
stake(&four);
|
||||
check_new_era();
|
||||
assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]);
|
||||
|
||||
// Block 2: New validator set now.
|
||||
with_env(|e| e.block_number = 2);
|
||||
staking::check_new_era();
|
||||
check_new_era();
|
||||
assert_eq!(session::validators(), vec![four.clone(), two.clone()]);
|
||||
|
||||
// Block 3: Unstake highest, introduce another staker. No change yet.
|
||||
with_env(|e| e.block_number = 3);
|
||||
staking::stake(&three);
|
||||
staking::unstake(&four);
|
||||
staking::check_new_era();
|
||||
stake(&three);
|
||||
unstake(&four);
|
||||
check_new_era();
|
||||
|
||||
// Block 4: New era - validators change.
|
||||
with_env(|e| e.block_number = 4);
|
||||
staking::check_new_era();
|
||||
check_new_era();
|
||||
assert_eq!(session::validators(), vec![three.clone(), two.clone()]);
|
||||
|
||||
// Block 5: Transfer stake from highest to lowest. No change yet.
|
||||
with_env(|e| e.block_number = 5);
|
||||
staking::transfer(&four, &one, 40);
|
||||
staking::check_new_era();
|
||||
transfer(&four, &one, 40);
|
||||
check_new_era();
|
||||
|
||||
// Block 6: Lowest now validator.
|
||||
with_env(|e| e.block_number = 6);
|
||||
staking::check_new_era();
|
||||
check_new_era();
|
||||
assert_eq!(session::validators(), vec![one.clone(), three.clone()]);
|
||||
|
||||
// Block 7: Unstake three. No change yet.
|
||||
with_env(|e| e.block_number = 7);
|
||||
staking::unstake(&three);
|
||||
staking::check_new_era();
|
||||
unstake(&three);
|
||||
check_new_era();
|
||||
assert_eq!(session::validators(), vec![one.clone(), three.clone()]);
|
||||
|
||||
// Block 8: Back to one and two.
|
||||
with_env(|e| e.block_number = 8);
|
||||
staking::check_new_era();
|
||||
check_new_era();
|
||||
assert_eq!(session::validators(), vec![one.clone(), two.clone()]);
|
||||
});
|
||||
}
|
||||
@@ -279,60 +284,60 @@ mod tests {
|
||||
twox_128(b"sta:spe").to_vec() => vec![].join(&2u64)
|
||||
], };
|
||||
with_externalities(&mut t, || {
|
||||
assert_eq!(staking::era_length(), 2u64);
|
||||
assert_eq!(staking::sessions_per_era(), 2u64);
|
||||
assert_eq!(staking::last_era_length_change(), 0u64);
|
||||
assert_eq!(staking::current_era(), 0u64);
|
||||
assert_eq!(era_length(), 2u64);
|
||||
assert_eq!(sessions_per_era(), 2u64);
|
||||
assert_eq!(last_era_length_change(), 0u64);
|
||||
assert_eq!(current_era(), 0u64);
|
||||
|
||||
// Block 1: No change.
|
||||
with_env(|e| e.block_number = 1);
|
||||
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);
|
||||
check_new_era();
|
||||
assert_eq!(sessions_per_era(), 2u64);
|
||||
assert_eq!(last_era_length_change(), 0u64);
|
||||
assert_eq!(current_era(), 0u64);
|
||||
|
||||
// Block 2: Simple era change.
|
||||
with_env(|e| e.block_number = 2);
|
||||
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);
|
||||
check_new_era();
|
||||
assert_eq!(sessions_per_era(), 2u64);
|
||||
assert_eq!(last_era_length_change(), 0u64);
|
||||
assert_eq!(current_era(), 1u64);
|
||||
|
||||
// Block 3: Schedule an era length change; no visible changes.
|
||||
with_env(|e| e.block_number = 3);
|
||||
staking::set_sessions_per_era(3);
|
||||
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);
|
||||
set_sessions_per_era(3);
|
||||
check_new_era();
|
||||
assert_eq!(sessions_per_era(), 2u64);
|
||||
assert_eq!(last_era_length_change(), 0u64);
|
||||
assert_eq!(current_era(), 1u64);
|
||||
|
||||
// Block 4: Era change kicks in.
|
||||
with_env(|e| e.block_number = 4);
|
||||
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);
|
||||
check_new_era();
|
||||
assert_eq!(sessions_per_era(), 3u64);
|
||||
assert_eq!(last_era_length_change(), 4u64);
|
||||
assert_eq!(current_era(), 2u64);
|
||||
|
||||
// Block 5: No change.
|
||||
with_env(|e| e.block_number = 5);
|
||||
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);
|
||||
check_new_era();
|
||||
assert_eq!(sessions_per_era(), 3u64);
|
||||
assert_eq!(last_era_length_change(), 4u64);
|
||||
assert_eq!(current_era(), 2u64);
|
||||
|
||||
// Block 6: No change.
|
||||
with_env(|e| e.block_number = 6);
|
||||
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);
|
||||
check_new_era();
|
||||
assert_eq!(sessions_per_era(), 3u64);
|
||||
assert_eq!(last_era_length_change(), 4u64);
|
||||
assert_eq!(current_era(), 2u64);
|
||||
|
||||
// Block 7: Era increment.
|
||||
with_env(|e| e.block_number = 7);
|
||||
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);
|
||||
check_new_era();
|
||||
assert_eq!(sessions_per_era(), 3u64);
|
||||
assert_eq!(last_era_length_change(), 4u64);
|
||||
assert_eq!(current_era(), 3u64);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -346,8 +351,8 @@ mod tests {
|
||||
], };
|
||||
|
||||
with_externalities(&mut t, || {
|
||||
assert_eq!(staking::balance(&one), 42);
|
||||
assert_eq!(staking::balance(&two), 0);
|
||||
assert_eq!(balance(&one), 42);
|
||||
assert_eq!(balance(&two), 0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -361,9 +366,9 @@ mod tests {
|
||||
], };
|
||||
|
||||
with_externalities(&mut t, || {
|
||||
staking::transfer(&one, &two, 69);
|
||||
assert_eq!(staking::balance(&one), 42);
|
||||
assert_eq!(staking::balance(&two), 69);
|
||||
transfer(&one, &two, 69);
|
||||
assert_eq!(balance(&one), 42);
|
||||
assert_eq!(balance(&two), 69);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -378,8 +383,8 @@ mod tests {
|
||||
], };
|
||||
|
||||
with_externalities(&mut t, || {
|
||||
staking::stake(&one);
|
||||
staking::transfer(&one, &two, 69);
|
||||
stake(&one);
|
||||
transfer(&one, &two, 69);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user