Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Changes from 1 commit
Commits
Show all changes
30 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
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
Remove redundant inner loops from election round.
  • Loading branch information
kianenigma committed Mar 18, 2019
commit c4bdb819d0552d6a102e2baec97cd6d9ffa41152
49 changes: 28 additions & 21 deletions srml/staking/src/phragmen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ pub struct Candidate<AccountId, Balance: HasCompact> {
pub who: AccountId,
// Exposure struct, holding info about the value that the validator has in stake.
pub exposure: Exposure<AccountId, Balance>,
// Accumulator of the stake of this candidate based on received votes.
approval_stake: Balance,
// Intermediary value used to sort candidates.
// See Phragmén reference implementation.
pub score: Perquintill,
// Accumulator of the stake of this candidate based on received votes.
approval_stake: Balance,
// Flag for being elected.
elected: bool,

}

// Wrapper around the nomination info of a single nominator for a group of validators.
Expand All @@ -61,8 +63,8 @@ pub struct Edge<AccountId, Balance: HasCompact> {
load: Perquintill,
// Final backing stake of this vote.
backing_stake: Balance,
// Reference to the target candidate object
// candidate: &'a Candidate<AccountId, Balance>,
// Index of the candidate stored in the 'candidates' vecotr
candidate_idx: usize,
}

/// Perform election based on Phragmén algorithm.
Expand Down Expand Up @@ -104,11 +106,11 @@ pub fn elect<T: Trait + 'static, FR, FN, FV, FS>(

// 1.1- Add phantom votes.
let mut nominations: Vec<Nominations<T::AccountId, BalanceOf<T>>> = Vec::with_capacity(candidates.len());
candidates.iter_mut().for_each(|c| {
candidates.iter_mut().enumerate().for_each(|(idx, c)| {
c.approval_stake += c.exposure.total;
nominations.push(Nominations {
who: c.who.clone(),
edges: vec![ Edge { who: c.who.clone(), ..Default::default() }],
edges: vec![ Edge { who: c.who.clone(), candidate_idx: idx, ..Default::default() }],
budget: c.exposure.total,
load: Perquintill::zero(),
})
Expand All @@ -120,9 +122,9 @@ pub fn elect<T: Trait + 'static, FR, FN, FV, FS>(
let nominator_stake = stash_of(&who);
let mut edges: Vec<Edge<T::AccountId, BalanceOf<T>>> = Vec::with_capacity(nominees.len());
for n in &nominees {
if let Some(c) = candidates.iter_mut().find(|i| i.who == *n) {
c.approval_stake += nominator_stake;
edges.push(Edge { who: n.clone(), ..Default::default() });
if let Some(idx) = candidates.iter_mut().position(|i| i.who == *n) {
candidates[idx].approval_stake += nominator_stake;
edges.push(Edge { who: n.clone(), candidate_idx: idx, ..Default::default() });
}
}

Expand Down Expand Up @@ -150,27 +152,32 @@ pub fn elect<T: Trait + 'static, FR, FN, FV, FS>(
// Loop 1: initialize score
for nomination in &nominations {
for edge in &nomination.edges {
if let Some(c) = candidates.iter_mut().find(|i| i.who == edge.who) {
let c = &mut candidates[edge.candidate_idx];
if !c.elected {
c.score = Perquintill::from_xth(c.approval_stake.as_());
}
}
}
// Loop 2: increment score.
for nomination in &nominations {
for edge in &nomination.edges {
if let Some(c) = candidates.iter_mut().find(|i| i.who == edge.who) {
let temp = nomination.budget.as_() * *nomination.load / c.approval_stake.as_();
let c = &mut candidates[edge.candidate_idx];
let temp = nomination.budget.as_() * *nomination.load / c.approval_stake.as_();
if !c.elected {
c.score = Perquintill::from_quintillionths(*c.score + temp);
}
}
}

// Find the best
let (winner_index, _) = candidates.iter().enumerate().min_by_key(|&(_i, c)| *c.score)
let winner = candidates
.iter_mut()
.filter(|c| !c.elected)
.min_by_key(|c| *c.score)
.expect("candidates length is checked to be >0; qed");

// loop 3: update nominator and vote load
let winner = candidates.remove(winner_index);
winner.elected = true;
for n in &mut nominations {
for v in &mut n.edges {
if v.who == winner.who {
Expand All @@ -180,20 +187,20 @@ pub fn elect<T: Trait + 'static, FR, FN, FV, FS>(
}
}

elected_candidates.push(winner);
elected_candidates.push(winner.clone());
} // end of all rounds

// 4.1- Update backing stake of candidates and nominators
for n in &mut nominations {
let nominator = n.who.clone();
for v in &mut n.edges {
for e in &mut n.edges {
// if the target of this vote is among the winners, otherwise let go.
if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == v.who && c.who != nominator) {
v.backing_stake = <BalanceOf<T> as As<u64>>::sa(n.budget.as_() * *v.load / *n.load);
c.exposure.total += v.backing_stake;
if let Some(c) = elected_candidates.iter_mut().find(|c| c.who == e.who && c.who != nominator) {
e.backing_stake = <BalanceOf<T> as As<u64>>::sa(n.budget.as_() * *e.load / *n.load);
c.exposure.total += e.backing_stake;
// Update IndividualExposure of those who nominated and their vote won
c.exposure.others.push(
IndividualExposure { who: n.who.clone(), value: v.backing_stake }
IndividualExposure { who: n.who.clone(), value: e.backing_stake }
);
}
}
Expand Down