spec: justification and finalization v0.6.1

This commit is contained in:
Michael Sproul 2019-05-06 15:19:27 +10:00
parent ed00ad9d00
commit 839ef0119b
No known key found for this signature in database
GPG Key ID: 77B1309D2E54E914
2 changed files with 45 additions and 43 deletions

View File

@ -45,7 +45,7 @@ pub fn per_epoch_processing(state: &mut BeaconState, spec: &ChainSpec) -> Result
validator_statuses.process_attestations(&state, spec)?;
// Justification.
update_justification_and_finalization(state, &validator_statuses.total_balances, spec)?;
process_justification_and_finalization(state, &validator_statuses.total_balances, spec)?;
// Crosslinks.
let winning_root_for_shards = process_crosslinks(state, spec)?;
@ -104,69 +104,71 @@ pub fn maybe_reset_eth1_period(state: &mut BeaconState, spec: &ChainSpec) {
/// Update the following fields on the `BeaconState`:
///
/// - `justification_bitfield`.
/// - `finalized_epoch`
/// - `justified_epoch`
/// - `previous_justified_epoch`
/// - `previous_justified_root`
/// - `current_justified_epoch`
/// - `current_justified_root`
/// - `finalized_epoch`
/// - `finalized_root`
///
/// Spec v0.5.1
pub fn update_justification_and_finalization(
/// Spec v0.6.1
pub fn process_justification_and_finalization(
state: &mut BeaconState,
total_balances: &TotalBalances,
spec: &ChainSpec,
) -> Result<(), Error> {
if state.current_epoch(spec) == spec.genesis_epoch {
return Ok(());
}
let previous_epoch = state.previous_epoch(spec);
let current_epoch = state.current_epoch(spec);
let mut new_justified_epoch = state.current_justified_epoch;
let mut new_finalized_epoch = state.finalized_epoch;
let old_previous_justified_epoch = state.previous_justified_epoch;
let old_current_justified_epoch = state.current_justified_epoch;
// Rotate the justification bitfield up one epoch to make room for the current epoch.
// Process justifications
state.previous_justified_epoch = state.current_justified_epoch;
state.previous_justified_root = state.current_justified_root;
state.justification_bitfield <<= 1;
// If the previous epoch gets justified, full the second last bit.
if (total_balances.previous_epoch_boundary_attesters * 3) >= (total_balances.previous_epoch * 2)
{
new_justified_epoch = previous_epoch;
let previous_epoch_matching_target_balance = total_balances.previous_epoch_target_attesters;
if total_balances.previous_epoch_target_attesters * 3 >= total_balances.previous_epoch * 2 {
state.current_justified_epoch = previous_epoch;
state.current_justified_root =
*state.get_block_root_at_epoch(state.current_justified_epoch, spec)?;
state.justification_bitfield |= 2;
}
// If the current epoch gets justified, fill the last bit.
if (total_balances.current_epoch_boundary_attesters * 3) >= (total_balances.current_epoch * 2) {
new_justified_epoch = current_epoch;
if total_balances.current_epoch_target_attesters * 3 >= total_balances.current_epoch * 2 {
state.current_justified_epoch = current_epoch;
state.current_justified_root =
*state.get_block_root_at_epoch(state.current_justified_epoch, spec)?;
state.justification_bitfield |= 1;
}
let bitfield = state.justification_bitfield;
// The 2nd/3rd/4th most recent epochs are all justified, the 2nd using the 4th as source.
if ((bitfield >> 1) % 8 == 0b111) & (state.previous_justified_epoch == current_epoch - 3) {
new_finalized_epoch = state.previous_justified_epoch;
if (bitfield >> 1) % 8 == 0b111 && old_previous_justified_epoch == current_epoch - 3 {
state.finalized_epoch = old_previous_justified_epoch;
state.finalized_root = *state.get_block_root_at_epoch(state.finalized_epoch, spec)?;
}
// The 2nd/3rd most recent epochs are both justified, the 2nd using the 3rd as source.
if ((bitfield >> 1) % 4 == 0b11) & (state.previous_justified_epoch == current_epoch - 2) {
new_finalized_epoch = state.previous_justified_epoch;
if (bitfield >> 1) % 4 == 0b11 && state.previous_justified_epoch == current_epoch - 2 {
state.finalized_epoch = old_previous_justified_epoch;
state.finalized_root = *state.get_block_root_at_epoch(state.finalized_epoch, spec)?;
}
// The 1st/2nd/3rd most recent epochs are all justified, the 1st using the 2nd as source.
if (bitfield % 8 == 0b111) & (state.current_justified_epoch == current_epoch - 2) {
new_finalized_epoch = state.current_justified_epoch;
if bitfield % 8 == 0b111 && state.current_justified_epoch == current_epoch - 2 {
state.finalized_epoch = old_current_justified_epoch;
state.finalized_root = *state.get_block_root_at_epoch(state.finalized_epoch, spec)?;
}
// The 1st/2nd most recent epochs are both justified, the 1st using the 2nd as source.
if (bitfield % 4 == 0b11) & (state.current_justified_epoch == current_epoch - 1) {
new_finalized_epoch = state.current_justified_epoch;
}
state.previous_justified_epoch = state.current_justified_epoch;
state.previous_justified_root = state.current_justified_root;
if new_justified_epoch != state.current_justified_epoch {
state.current_justified_epoch = new_justified_epoch;
state.current_justified_root =
*state.get_block_root(new_justified_epoch.start_slot(spec.slots_per_epoch), spec)?;
}
if new_finalized_epoch != state.finalized_epoch {
state.finalized_epoch = new_finalized_epoch;
state.finalized_root =
*state.get_block_root(new_finalized_epoch.start_slot(spec.slots_per_epoch), spec)?;
if bitfield % 4 == 0b11 && state.current_justified_epoch == current_epoch - 1 {
state.finalized_epoch = old_current_justified_epoch;
state.finalized_root = *state.get_block_root_at_epoch(state.finalized_epoch, spec)?;
}
Ok(())

View File

@ -75,7 +75,7 @@ pub struct ValidatorStatus {
pub is_current_epoch_attester: bool,
/// True if the validator's beacon block root attestation for the first slot of the _current_
/// epoch matches the block root known to the state.
pub is_current_epoch_boundary_attester: bool,
pub is_current_epoch_target_attester: bool,
/// True if the validator had an attestation included in the _previous_ epoch.
pub is_previous_epoch_attester: bool,
/// True if the validator's beacon block root attestation for the first slot of the _previous_
@ -108,7 +108,7 @@ impl ValidatorStatus {
set_self_if_other_is_true!(self, other, is_active_in_current_epoch);
set_self_if_other_is_true!(self, other, is_active_in_previous_epoch);
set_self_if_other_is_true!(self, other, is_current_epoch_attester);
set_self_if_other_is_true!(self, other, is_current_epoch_boundary_attester);
set_self_if_other_is_true!(self, other, is_current_epoch_target_attester);
set_self_if_other_is_true!(self, other, is_previous_epoch_attester);
set_self_if_other_is_true!(self, other, is_previous_epoch_target_attester);
set_self_if_other_is_true!(self, other, is_previous_epoch_head_attester);
@ -135,7 +135,7 @@ pub struct TotalBalances {
pub current_epoch_attesters: u64,
/// The total effective balance of all validators who attested during the _current_ epoch and
/// agreed with the state about the beacon block at the first slot of the _current_ epoch.
pub current_epoch_boundary_attesters: u64,
pub current_epoch_target_attesters: u64,
/// The total effective balance of all validators who attested during the _previous_ epoch.
pub previous_epoch_attesters: u64,
/// The total effective balance of all validators who attested during the _previous_ epoch and
@ -221,7 +221,7 @@ impl ValidatorStatuses {
status.is_current_epoch_attester = true;
if target_matches_epoch_start_block(a, state, state.current_epoch(spec), spec)? {
status.is_current_epoch_boundary_attester = true;
status.is_current_epoch_target_attester = true;
}
} else if is_from_epoch(a, state.previous_epoch(spec), spec) {
status.is_previous_epoch_attester = true;
@ -262,8 +262,8 @@ impl ValidatorStatuses {
if v.is_current_epoch_attester {
self.total_balances.current_epoch_attesters += validator_balance;
}
if v.is_current_epoch_boundary_attester {
self.total_balances.current_epoch_boundary_attesters += validator_balance;
if v.is_current_epoch_target_attester {
self.total_balances.current_epoch_target_attesters += validator_balance;
}
if v.is_previous_epoch_attester {
self.total_balances.previous_epoch_attesters += validator_balance;