Fix bug in crosslink rewards during per-epoch

This commit is contained in:
Paul Hauner 2019-09-09 01:54:32 -04:00
parent 7b7a44e2f2
commit e1d6e187d1
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
4 changed files with 34 additions and 29 deletions

View File

@ -48,15 +48,10 @@ pub fn per_epoch_processing<T: EthSpec>(
process_justification_and_finalization(state, &validator_statuses.total_balances)?;
// Crosslinks.
let winning_root_for_shards = process_crosslinks(state, spec)?;
process_crosslinks(state, spec)?;
// Rewards and Penalties.
process_rewards_and_penalties(
state,
&mut validator_statuses,
&winning_root_for_shards,
spec,
)?;
process_rewards_and_penalties(state, &mut validator_statuses, spec)?;
// Registry Updates.
process_registry_updates(state, spec)?;
@ -160,9 +155,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
pub fn process_crosslinks<T: EthSpec>(
state: &mut BeaconState<T>,
spec: &ChainSpec,
) -> Result<WinningRootHashSet, Error> {
let mut winning_root_for_shards: WinningRootHashSet = HashMap::new();
) -> Result<(), Error> {
state.previous_crosslinks = state.current_crosslinks.clone();
for &relative_epoch in &[RelativeEpoch::Previous, RelativeEpoch::Current] {
@ -182,12 +175,11 @@ pub fn process_crosslinks<T: EthSpec>(
if 3 * winning_root.total_attesting_balance >= 2 * total_committee_balance {
state.current_crosslinks[shard as usize] = winning_root.crosslink.clone();
}
winning_root_for_shards.insert(shard, winning_root);
}
}
}
Ok(winning_root_for_shards)
Ok(())
}
/// Finish up an epoch update.

View File

@ -1,5 +1,5 @@
use super::validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses};
use super::{Error, WinningRootHashSet};
use super::Error;
use integer_sqrt::IntegerSquareRoot;
use types::*;
@ -36,7 +36,6 @@ impl std::ops::AddAssign for Delta {
pub fn process_rewards_and_penalties<T: EthSpec>(
state: &mut BeaconState<T>,
validator_statuses: &mut ValidatorStatuses,
winning_root_for_shards: &WinningRootHashSet,
spec: &ChainSpec,
) -> Result<(), Error> {
if state.current_epoch() == T::genesis_epoch() {
@ -53,15 +52,13 @@ pub fn process_rewards_and_penalties<T: EthSpec>(
let mut deltas = vec![Delta::default(); state.balances.len()];
get_attestation_deltas(&mut deltas, state, &validator_statuses, spec)?;
// Update statuses with the information from winning roots.
validator_statuses.process_winning_roots(state, spec)?;
get_crosslink_deltas(&mut deltas, state, &validator_statuses, spec)?;
get_proposer_deltas(
&mut deltas,
state,
validator_statuses,
winning_root_for_shards,
spec,
)?;
get_proposer_deltas(&mut deltas, state, validator_statuses, spec)?;
// Apply the deltas, over-flowing but not under-flowing (saturating at 0 instead).
for (i, delta) in deltas.iter().enumerate() {
@ -79,12 +76,8 @@ fn get_proposer_deltas<T: EthSpec>(
deltas: &mut Vec<Delta>,
state: &BeaconState<T>,
validator_statuses: &mut ValidatorStatuses,
winning_root_for_shards: &WinningRootHashSet,
spec: &ChainSpec,
) -> Result<(), Error> {
// Update statuses with the information from winning roots.
validator_statuses.process_winning_roots(state, winning_root_for_shards, spec)?;
for (index, validator) in validator_statuses.statuses.iter().enumerate() {
if validator.is_previous_epoch_attester {
let inclusion = validator

View File

@ -1,4 +1,4 @@
use super::WinningRootHashSet;
use super::{winning_root::winning_root, WinningRootHashSet};
use crate::common::get_attesting_indices;
use types::*;
@ -292,9 +292,29 @@ impl ValidatorStatuses {
pub fn process_winning_roots<T: EthSpec>(
&mut self,
state: &BeaconState<T>,
winning_roots: &WinningRootHashSet,
spec: &ChainSpec,
) -> Result<(), BeaconStateError> {
// We must re-calculate the winning roots here because it is possible that they have
// changed since the first time they were calculated.
//
// This is because we altered the state during the first time we calculated the winning
// roots.
let winning_root_for_shards = {
let mut winning_root_for_shards = WinningRootHashSet::new();
let relative_epoch = RelativeEpoch::Previous;
let epoch = relative_epoch.into_epoch(state.current_epoch());
for offset in 0..state.get_committee_count(relative_epoch)? {
let shard = (state.get_epoch_start_shard(relative_epoch)? + offset)
% T::ShardCount::to_u64();
if let Some(winning_root) = winning_root(state, shard, epoch, spec)? {
winning_root_for_shards.insert(shard, winning_root);
}
}
winning_root_for_shards
};
// Loop through each slot in the previous epoch.
for slot in state.previous_epoch().slot_iter(T::slots_per_epoch()) {
let crosslink_committees_at_slot = state.get_crosslink_committees_at_slot(slot)?;
@ -302,7 +322,7 @@ impl ValidatorStatuses {
// Loop through each committee in the slot.
for c in crosslink_committees_at_slot {
// If there was some winning crosslink root for the committee's shard.
if let Some(winning_root) = winning_roots.get(&c.shard) {
if let Some(winning_root) = winning_root_for_shards.get(&c.shard) {
let total_committee_balance = state.get_total_balance(&c.committee, spec)?;
for &validator_index in &winning_root.attesting_validator_indices {
// Take note of the balance information for the winning root, it will be

View File

@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet};
use tree_hash::TreeHash;
use types::*;
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct WinningRoot {
pub crosslink: Crosslink,
pub attesting_validator_indices: Vec<usize>,