Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
aa83f22
initial doc for the staking module
kianenigma Mar 9, 2019
b9d09bb
Remove md style links.
kianenigma Mar 9, 2019
7df2b19
Remove todos.
kianenigma Mar 9, 2019
28b959b
Add rust code types
kianenigma Mar 9, 2019
91be68b
Rename and fix review notes.
kianenigma Mar 11, 2019
5912ff5
Add new md file
kianenigma Mar 11, 2019
64ca546
Final touches.
kianenigma Mar 11, 2019
a8ba78e
Migrate compleatly to rustdoc
kianenigma Mar 11, 2019
982d7e8
Update link
kianenigma Mar 11, 2019
4a572a2
Fix heading
kianenigma Mar 11, 2019
ea5ae00
Merge branch 'master' into kiz-document-staking
kianenigma Mar 12, 2019
89682a6
Final touches wrt the new template.
kianenigma Mar 12, 2019
956ec96
Remove empty prereq.
kianenigma Mar 12, 2019
2879e1d
Fix more reviews
kianenigma Mar 12, 2019
105723b
Some final nits.
kianenigma Mar 12, 2019
531ae73
Merge branch 'master' of github.com:paritytech/substrate into kiz-doc…
kianenigma Mar 14, 2019
5567859
Fix some side issues.
kianenigma Mar 14, 2019
e739361
Fix another set of reviews
kianenigma Mar 15, 2019
4eb568c
Fix + stabilize leftover reivews.
kianenigma Mar 15, 2019
9b026cc
Remove unused test parameters
kianenigma Mar 15, 2019
a8075c7
Fix typo.
kianenigma Mar 15, 2019
a33205b
Merge redundant loops
kianenigma Mar 15, 2019
07f9710
Merge branch 'kiz-document-staking' into kiz-staking-enhance
kianenigma Mar 15, 2019
cfb39b9
Adds phantom self-vote
kianenigma Mar 16, 2019
a4c298c
Fix broken tests.
kianenigma Mar 17, 2019
5eb6f24
Refactor some names to match the reference.
kianenigma Mar 17, 2019
c4bdb81
Remove redundant inner loops from election round.
kianenigma Mar 18, 2019
03d7583
Introduce phragmen post-processing.
kianenigma Mar 19, 2019
bf8212f
Some fixes and todos.
kianenigma Mar 19, 2019
85f1294
Fix some tests with new phragmen params
kianenigma Mar 21, 2019
eb6d9b5
master.into()
kianenigma Mar 21, 2019
54c1417
Fix test
gavofyork Mar 21, 2019
abc1685
Bump spec
gavofyork Mar 21, 2019
0cdc3c1
Fix wasm build
gavofyork Mar 21, 2019
0d429d8
Fix tests and phragmen fallback. Avoid double-controlling
gavofyork Mar 22, 2019
ae0f53e
Fix and rebuild wasm
gavofyork Mar 22, 2019
7b301ad
Whitespaces, whitespaces everywhere.
kianenigma Mar 22, 2019
1488960
Merge remote-tracking branch 'origin/master' into kiz-staking-enhance
gavofyork Mar 22, 2019
f6b9fbc
Rebuild
gavofyork Mar 22, 2019
c26f890
Disable post-processing.
kianenigma Mar 22, 2019
f40f671
Merge test conflicts.
kianenigma Mar 22, 2019
b399c8a
Identify by stash, not controller account.
gavofyork Mar 22, 2019
d3e5539
Couple of fixes
gavofyork Mar 22, 2019
fcce528
Fix first test
gavofyork Mar 22, 2019
202f67b
Merge branch 'kiz-staking-enhance' of github.com:paritytech/substrate…
gavofyork Mar 22, 2019
6c64125
Fix invulnerability_should_work
gavofyork Mar 22, 2019
badd121
Fix a couple more tests
gavofyork Mar 22, 2019
7b83e30
Fix more tests
gavofyork Mar 22, 2019
a9a3a92
Fix more tests
gavofyork Mar 22, 2019
f14977d
Fix more tests
gavofyork Mar 22, 2019
a41aeec
Fix some tests
kianenigma Mar 22, 2019
f584fd1
Merge branch 'kiz-staking-enhance' of github.com:paritytech/substrate…
kianenigma Mar 22, 2019
817d538
Fix update-ledger.
gavofyork Mar 22, 2019
1257dfe
Merge remote-tracking branch 'origin/kiz-staking-enhance' into kiz-st…
gavofyork Mar 22, 2019
a879983
Fix update-ledger.
gavofyork Mar 22, 2019
0d6136d
Fix another test
gavofyork Mar 22, 2019
0dbff72
Fix another test
gavofyork Mar 22, 2019
184cb5c
Fix rest of staking tests
gavofyork Mar 22, 2019
1b4b05f
Remove printlns
gavofyork Mar 22, 2019
1be69c2
Rebuild wasm
gavofyork Mar 22, 2019
d380360
Merge remote-tracking branch 'origin/master' into kiz-staking-enhance
gavofyork Mar 22, 2019
f255ef5
Fix & tests for auth/val syncing
gavofyork Mar 22, 2019
fd5b2cd
Merge remote-tracking branch 'origin/master' into kiz-staking-enhance
gavofyork Mar 22, 2019
e20b766
Fix up threading for tests
gavofyork Mar 22, 2019
4d8a2fd
Remove superfluous asserts
gavofyork Mar 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix tests and phragmen fallback. Avoid double-controlling
  • Loading branch information
gavofyork committed Mar 22, 2019
commit 0d429d8ae16d91604da28d95786e738dab00d616
1 change: 0 additions & 1 deletion core/sr-std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ pub mod prelude {
pub use crate::boxed::Box;
pub use crate::cmp::{Eq, PartialEq};
pub use crate::clone::Clone;
pub use crate::alloc::prelude::*;

// Re-export `vec!` macro here, but not in `std` mode, since
// std's prelude already brings `vec!` into the scope.
Expand Down
74 changes: 53 additions & 21 deletions srml/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,10 @@ decl_module! {

let controller = T::Lookup::lookup(controller)?;

if <Ledger<T>>::exists(&controller) {
return Err("controller already paired")
}

// You're auto-bonded forever, here. We might improve this by only bonding when
// you actually validate/nominate.
<Bonded<T>>::insert(&stash, controller.clone());
Expand Down Expand Up @@ -665,6 +669,25 @@ decl_module! {
<Payee<T>>::insert(&controller, payee);
}

/// (Re-)set the payment target for a controller.
///
/// Effects will be felt at the beginning of the next era.
///
/// The dispatch origin for this call must be _Signed_ by the controller, not the stash.
fn set_controller(origin, controller: <T::Lookup as StaticLookup>::Source) {
let stash = ensure_signed(origin)?;
let old_controller = Self::bonded(&stash).ok_or("not a stash")?;
let controller = T::Lookup::lookup(controller)?;
if <Ledger<T>>::exists(&controller) {
return Err("controller already paired")
}
if controller != old_controller {
<Bonded<T>>::insert(&stash, &controller);
if let Some(l) = <Ledger<T>>::take(&old_controller) { <Ledger<T>>::insert(&controller, l) };
<Payee<T>>::insert(&controller, <Payee<T>>::take(&old_controller));
}
}

/// Set the number of sessions in an era.
fn set_sessions_per_era(#[compact] new: T::BlockNumber) {
<NextSessionsPerEra<T>>::put(new);
Expand Down Expand Up @@ -887,7 +910,7 @@ impl<T: Trait> Module<T> {
let nominators = || <Nominators<T>>::enumerate();
let stash_of = |w: &T::AccountId| -> BalanceOf<T> { Self::stash_balance(w) };
let min_validator_count = Self::minimum_validator_count() as usize;
let elected_candidates = elect::<T, _, _, _, _>(
let maybe_elected_candidates = elect::<T, _, _, _, _>(
rounds,
validators,
nominators,
Expand All @@ -900,31 +923,40 @@ impl<T: Trait> Module<T> {
}
);

// Clear Stakers and reduce their slash_count.
for v in <session::Module<T>>::validators().iter() {
<Stakers<T>>::remove(v);
let slash_count = <SlashCount<T>>::take(v);
if slash_count > 1 {
<SlashCount<T>>::insert(v, slash_count - 1);
if let Some(elected_candidates) = maybe_elected_candidates {
// Clear Stakers and reduce their slash_count.
for v in <session::Module<T>>::validators().iter() {
<Stakers<T>>::remove(v);
let slash_count = <SlashCount<T>>::take(v);
if slash_count > 1 {
<SlashCount<T>>::insert(v, slash_count - 1);
}
}
}

// Populate Stakers and figure out the minimum stake behind a slot.
let mut slot_stake = elected_candidates[0].exposure.total;
for c in &elected_candidates {
if c.exposure.total < slot_stake {
slot_stake = c.exposure.total;
// Populate Stakers and figure out the minimum stake behind a slot.
let mut slot_stake = elected_candidates[0].exposure.total;
for c in &elected_candidates {
if c.exposure.total < slot_stake {
slot_stake = c.exposure.total;
}
<Stakers<T>>::insert(c.who.clone(), c.exposure.clone());
}
<Stakers<T>>::insert(c.who.clone(), c.exposure.clone());
}
<SlotStake<T>>::put(&slot_stake);
<SlotStake<T>>::put(&slot_stake);

// Set the new validator set.
<session::Module<T>>::set_validators(
&elected_candidates.into_iter().map(|i| i.who).collect::<Vec<_>>()
);
// Set the new validator set.
<session::Module<T>>::set_validators(
&elected_candidates.into_iter().map(|i| i.who).collect::<Vec<_>>()
);

slot_stake
slot_stake
} else {
// There were not enough candidates for even our minimal level of functionality.
// This is bad.
// We should probably disable all functionality except for block production
// and let the chain keep producing blocks until we can decide on a sufficiently
// substantial set.
Self::slot_stake()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One suggestion from @rphmeier which I think went missing here: Even when we are naively choosing the previous set, take() only validator_count from it. It might be that we had more than what we need and at least we can kick out the extra one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would only happen if minimum_validator_count increased. which seems like even more of an edge case than this. it also substantially complicates things.

}
}

/// Call when a validator is determined to be offline. `count` is the
Expand Down
11 changes: 4 additions & 7 deletions srml/staking/src/phragmen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub struct ElectionConfig<Balance: HasCompact> {

// Wrapper around validation candidates some metadata.
#[derive(Clone, Encode, Decode, Default)]
#[cfg_attr(feature = "std", derive(Debug, Default))]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Candidate<AccountId, Balance: HasCompact> {
// The validator's account
pub who: AccountId,
Expand Down Expand Up @@ -96,7 +96,7 @@ pub fn elect<T: Trait + 'static, FR, FN, FV, FS>(
stash_of: FS,
minimum_validator_count: usize,
config: ElectionConfig<BalanceOf<T>>,
) -> Vec<Candidate<T::AccountId, BalanceOf<T>>> where
) -> Option<Vec<Candidate<T::AccountId, BalanceOf<T>>>> where
FR: Fn() -> usize,
FV: Fn() -> Box<dyn Iterator<
Item =(T::AccountId, ValidatorPrefs<BalanceOf<T>>)
Expand All @@ -119,9 +119,6 @@ pub fn elect<T: Trait + 'static, FR, FN, FV, FS>(
}
}).collect::<Vec<Candidate<T::AccountId, BalanceOf<T>>>>();

// Just to be used when we are below minimum validator count
let original_candidates = candidates.clone();

// 1.1- Add phantom votes.
let mut nominators: Vec<Nominator<T::AccountId, BalanceOf<T>>> = Vec::with_capacity(candidates.len());
candidates.iter_mut().enumerate().for_each(|(idx, c)| {
Expand Down Expand Up @@ -266,10 +263,10 @@ pub fn elect<T: Trait + 'static, FR, FN, FV, FS>(
}
} else {
// if we have less than minimum, use the previous validator set.
elected_candidates = original_candidates;
return None
}
}
elected_candidates
Some(elected_candidates)
}

pub fn equalise<T: Trait + 'static>(
Expand Down
52 changes: 36 additions & 16 deletions srml/staking/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,15 +562,15 @@ fn no_candidate_emergency_condition() {
assert_eq!(Staking::validator_count(), 15);

// initial validators
assert_eq!(Session::validators(), vec![40, 30, 20, 10]);
assert_eq!(Session::validators(), vec![10, 20, 30, 40]);

// trigger era
System::set_block_number(1);
Session::check_rotate_session(System::block_number());
assert_eq!(Staking::current_era(), 1);

// No one nominates => no one has a proper vote => no change
assert_eq!(Session::validators(), vec![40, 30, 20, 10]);
assert_eq!(Session::validators(), vec![10, 20, 30, 40]);
});
}

Expand Down Expand Up @@ -756,20 +756,38 @@ fn double_staking_should_fail() {
with_externalities(&mut ExtBuilder::default()
.sessions_per_era(2)
.build(),
|| {
let arbitrary_value = 5;
System::set_block_number(1);
// 2 = controller, 1 stashed => ok
assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default()));
// 2 = controller, 3 stashed (Note that 2 is reused.) => ok
assert_ok!(Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default()));
// 4 = not used so far, 1 stashed => not allowed.
assert_noop!(Staking::bond(Origin::signed(1), 4, arbitrary_value, RewardDestination::default()), "stash already bonded");
// 1 = stashed => attempting to nominate should fail.
assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller");
// 2 = controller => nominating should work.
assert_ok!(Staking::nominate(Origin::signed(2), vec![1]));
});
|| {
let arbitrary_value = 5;
System::set_block_number(1);
// 2 = controller, 1 stashed => ok
assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default()));
// 4 = not used so far, 1 stashed => not allowed.
assert_noop!(Staking::bond(Origin::signed(1), 4, arbitrary_value, RewardDestination::default()), "stash already bonded");
// 1 = stashed => attempting to nominate should fail.
assert_noop!(Staking::nominate(Origin::signed(1), vec![1]), "not a controller");
// 2 = controller => nominating should work.
assert_ok!(Staking::nominate(Origin::signed(2), vec![1]));
});
}

#[test]
fn double_controlling_should_fail() {
// should test (in the same order):
// * an account already bonded as controller CAN be reused as the controller of another account.
// * an account already bonded as stash cannot be the controller of another account.
// * an account already bonded as stash cannot nominate.
// * an account already bonded as controller can nominate.
with_externalities(&mut ExtBuilder::default()
.sessions_per_era(2)
.build(),
|| {
let arbitrary_value = 5;
System::set_block_number(1);
// 2 = controller, 1 stashed => ok
assert_ok!(Staking::bond(Origin::signed(1), 2, arbitrary_value, RewardDestination::default()));
// 2 = controller, 3 stashed (Note that 2 is reused.) => no-op
assert_noop!(Staking::bond(Origin::signed(3), 2, arbitrary_value, RewardDestination::default()), "controller already paired");
});
}

#[test]
Expand Down Expand Up @@ -1522,6 +1540,8 @@ fn phragmen_election_works_example_2() {
}
);

let winners = winners.unwrap();

// 10 and 30 must be the winners
assert_eq!(winners.iter().map(|w| w.who).collect::<Vec<BalanceOf<Test>>>(), vec![10, 30]);

Expand Down