Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Prev Previous commit
Next Next commit
1.Adjust the logic of the function 'do_elect()'.
2.Add one test that does ElectionCompute::Signed and one that does ElectionCompute::Unsigned to check 'Event::SolutionStored' and 'Event::ElectionFinalized'
  • Loading branch information
hzy1919 committed Aug 29, 2022
commit 31d2808d08aac04a5e185cfe38e1afeeeed89d50
159 changes: 127 additions & 32 deletions frame/election-provider-multi-phase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1533,35 +1533,48 @@ impl<T: Config> Pallet<T> {
// - signed phase was complete or not started, in which case finalization is idempotent and
// inexpensive (1 read of an empty vector).
let _ = Self::finalize_signed_phase();
<QueuedSolution<T>>::take()
.map_or_else(
|| {
T::Fallback::elect().map_err(|fe| ElectionError::Fallback(fe)).map(|supports| {
(supports.clone(), supports.evaluate(), ElectionCompute::Fallback)
})
},
|ReadySolution { supports, score, compute }| Ok((supports, score, compute)),
)
.map(|(supports, score, compute)| {
match <QueuedSolution<T>>::take() {
Some(ready_solution) => {
Self::deposit_event(Event::ElectionFinalized {
election_compute: Some(compute),
score: Some(score),
election_compute: Some(ready_solution.compute),
score: Some(ready_solution.score),
});
if Self::round() != 1 {
log!(info, "Finalized election round with compute {:?}.", compute);
log!(
info,
"Finalized election round with compute {:?}.",
ready_solution.compute
);
}
supports
})
.map_err(|err| {
Self::deposit_event(Event::ElectionFinalized {
election_compute: None,
score: None,
});
if Self::round() != 1 {
log!(warn, "Failed to finalize election round. reason {:?}", err);
}
err
})
Ok(ready_solution.supports)
},
None => match T::Fallback::elect() {
Ok(supports) => {
Self::deposit_event(Event::ElectionFinalized {
election_compute: Some(ElectionCompute::Fallback),
score: None,
});
if Self::round() != 1 {
log!(
info,
"Finalized election round with compute {:?}.",
ElectionCompute::Fallback
);
}
Ok(supports)
},
Err(err) => {
Self::deposit_event(Event::ElectionFinalized {
election_compute: None,
score: None,
});
if Self::round() != 1 {
log!(warn, "Failed to finalize election round. reason {:?}", err);
}
Err(ElectionError::Fallback(err))
},
},
}
}

/// record the weight of the given `supports`.
Expand Down Expand Up @@ -1810,8 +1823,9 @@ mod tests {
use super::*;
use crate::{
mock::{
multi_phase_events, roll_to, AccountId, ExtBuilder, MockWeightInfo, MockedWeightInfo,
MultiPhase, Origin, Runtime, SignedMaxSubmissions, System, TargetIndex, Targets,
multi_phase_events, raw_solution, roll_to, AccountId, ExtBuilder, MockWeightInfo,
MockedWeightInfo, MultiPhase, Origin, Runtime, SignedMaxSubmissions, System,
TargetIndex, Targets,
},
Phase,
};
Expand Down Expand Up @@ -1979,11 +1993,7 @@ mod tests {
Event::SignedPhaseStarted { round: 1 },
Event::ElectionFinalized {
election_compute: Some(ElectionCompute::Fallback),
score: Some(ElectionScore {
minimal_stake: 40,
sum_stake: 100,
sum_stake_squared: 5200
})
score: None
}
],
);
Expand Down Expand Up @@ -2033,6 +2043,91 @@ mod tests {
})
}

#[test]
fn check_events_with_election_compute_signed() {
ExtBuilder::default().build_and_execute(|| {
roll_to(14);
assert_eq!(MultiPhase::current_phase(), Phase::Off);

roll_to(15);
assert!(MultiPhase::current_phase().is_signed());

let solution = raw_solution();
assert_ok!(MultiPhase::submit(crate::mock::Origin::signed(99), Box::new(solution)));

roll_to(30);
assert_ok!(MultiPhase::elect());

assert_eq!(
multi_phase_events(),
vec![
Event::SignedPhaseStarted { round: 1 },
Event::SolutionStored {
election_compute: ElectionCompute::Signed,
prev_ejected: false
},
Event::Rewarded { account: 99, value: 7 },
Event::UnsignedPhaseStarted { round: 1 },
Event::ElectionFinalized {
election_compute: Some(ElectionCompute::Signed),
score: Some(ElectionScore {
minimal_stake: 40,
sum_stake: 100,
sum_stake_squared: 5200
})
}
],
);
})
}

#[test]
fn check_events_with_election_compute_unsigned() {
ExtBuilder::default().build_and_execute(|| {
roll_to(25);
assert!(MultiPhase::current_phase().is_unsigned());

// ensure we have snapshots in place.
assert!(MultiPhase::snapshot().is_some());
assert_eq!(MultiPhase::desired_targets().unwrap(), 2);

// mine seq_phragmen solution with 2 iters.
let (solution, witness) = MultiPhase::mine_solution().unwrap();

// ensure this solution is valid.
assert!(MultiPhase::queued_solution().is_none());
assert_ok!(MultiPhase::submit_unsigned(
crate::mock::Origin::none(),
Box::new(solution),
witness
));
assert!(MultiPhase::queued_solution().is_some());

roll_to(30);
assert_ok!(MultiPhase::elect());

assert_eq!(
multi_phase_events(),
vec![
Event::SignedPhaseStarted { round: 1 },
Event::UnsignedPhaseStarted { round: 1 },
Event::SolutionStored {
election_compute: ElectionCompute::Unsigned,
prev_ejected: false
},
Event::ElectionFinalized {
election_compute: Some(ElectionCompute::Unsigned),
score: Some(ElectionScore {
minimal_stake: 40,
sum_stake: 100,
sum_stake_squared: 5200
})
}
],
);
})
}

#[test]
fn fallback_strategy_works() {
ExtBuilder::default().onchain_fallback(true).build_and_execute(|| {
Expand Down