Fix bug with inclusion_distance

This commit is contained in:
Paul Hauner 2019-01-31 08:49:50 +11:00
parent 7d94cfb0e4
commit 2fc6dbb02a
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
4 changed files with 77 additions and 52 deletions

View File

@ -4,6 +4,7 @@ use bls::Signature;
use log::debug; use log::debug;
use slot_clock::TestingSlotClockError; use slot_clock::TestingSlotClockError;
use types::{ use types::{
beacon_state::CommitteesError,
readers::{BeaconBlockReader, BeaconStateReader}, readers::{BeaconBlockReader, BeaconStateReader},
BeaconBlock, BeaconBlockBody, BeaconState, Eth1Data, Hash256, BeaconBlock, BeaconBlockBody, BeaconState, Eth1Data, Hash256,
}; };
@ -13,6 +14,7 @@ pub enum Error {
DBError(String), DBError(String),
StateTransitionError(TransitionError), StateTransitionError(TransitionError),
PresentSlotIsNone, PresentSlotIsNone,
CommitteesError(CommitteesError),
} }
impl<T, U> BeaconChain<T, U> impl<T, U> BeaconChain<T, U>
@ -50,12 +52,14 @@ where
debug!("Finding attesatations for block..."); debug!("Finding attesatations for block...");
let attestations = self let attestations = {
.attestation_aggregator let mut next_state = parent_state.clone();
.read() next_state.per_slot_processing(Hash256::zero(), &self.spec)?;
.unwrap() self.attestation_aggregator
// TODO: advance the parent_state slot. .read()
.get_attestations_for_state(&parent_state, &self.spec); .unwrap()
.get_attestations_for_state(&next_state, &self.spec)
};
debug!("Found {} attestation(s).", attestations.len()); debug!("Found {} attestation(s).", attestations.len());
@ -111,3 +115,9 @@ impl From<TestingSlotClockError> for Error {
unreachable!(); // Testing clock never throws an error. unreachable!(); // Testing clock never throws an error.
} }
} }
impl From<CommitteesError> for Error {
fn from(e: CommitteesError) -> Error {
Error::CommitteesError(e)
}
}

View File

@ -1,15 +1,28 @@
use crate::{validator_registry::get_active_validator_indices, BeaconState, ChainSpec}; use crate::{validator_registry::get_active_validator_indices, BeaconState, ChainSpec};
use log::debug;
use std::ops::Range; use std::ops::Range;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Error { pub enum Error {
InvalidSlot(u64, Range<u64>), InvalidEpoch(u64, Range<u64>),
InsufficientNumberOfValidators, InsufficientNumberOfValidators,
} }
macro_rules! ensure {
($condition: expr, $result: expr) => {
if !$condition {
return Err($result);
}
};
}
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
impl BeaconState { impl BeaconState {
pub fn current_epoch(&self, spec: &ChainSpec) -> u64 {
self.slot / spec.epoch_length
}
/// Returns the number of committees per slot. /// Returns the number of committees per slot.
/// ///
/// Note: this is _not_ the committee size. /// Note: this is _not_ the committee size.
@ -69,7 +82,7 @@ impl BeaconState {
let previous_epoch_range = self.get_current_epoch_boundaries(spec.epoch_length); let previous_epoch_range = self.get_current_epoch_boundaries(spec.epoch_length);
let current_epoch_range = self.get_current_epoch_boundaries(spec.epoch_length); let current_epoch_range = self.get_current_epoch_boundaries(spec.epoch_length);
if !range_contains(&current_epoch_range, slot) { if !range_contains(&current_epoch_range, slot) {
return Err(Error::InvalidSlot(slot, current_epoch_range)); return Err(Error::InvalidEpoch(slot, current_epoch_range));
} }
*/ */
let epoch = slot / spec.epoch_length; let epoch = slot / spec.epoch_length;
@ -81,9 +94,17 @@ impl BeaconState {
}; };
let next_epoch = current_epoch + 1; let next_epoch = current_epoch + 1;
if !((previous_epoch <= epoch) & (epoch < next_epoch)) { /*
return Err(Error::InvalidSlot(slot, previous_epoch..current_epoch)); debug!(
} "state.slot: {}, slot: {}, current_epoch: {}, previous_epoch: {}, next_epoch: {}",
self.slot, slot, current_epoch, previous_epoch, next_epoch
);
*/
ensure!(
(previous_epoch <= epoch) & (epoch < next_epoch),
Error::InvalidEpoch(slot, previous_epoch..current_epoch)
);
let offset = slot % spec.epoch_length; let offset = slot % spec.epoch_length;

View File

@ -54,10 +54,18 @@ impl BeaconState {
total_balance total_balance
); );
debug!(
"latest_attestations = {:?}",
self.latest_attestations
.iter()
.map(|a| a.data.slot)
.collect::<Vec<u64>>()
);
let current_epoch_attestations: Vec<&PendingAttestation> = self let current_epoch_attestations: Vec<&PendingAttestation> = self
.latest_attestations .latest_attestations
.iter() .iter()
.filter(|a| (self.slot - spec.epoch_length <= a.data.slot) && (a.data.slot < self.slot)) .filter(|a| a.data.slot / spec.epoch_length == self.current_epoch(spec))
.collect(); .collect();
/* /*
@ -103,8 +111,7 @@ impl BeaconState {
.iter() .iter()
.filter(|a| { .filter(|a| {
//TODO: ensure these saturating subs are correct. //TODO: ensure these saturating subs are correct.
(self.slot.saturating_sub(2 * spec.epoch_length) <= a.data.slot) a.data.slot / spec.epoch_length == self.current_epoch(spec).saturating_sub(1)
&& (a.data.slot < self.slot.saturating_sub(spec.epoch_length))
}) })
.collect(); .collect();
@ -183,6 +190,11 @@ impl BeaconState {
let previous_epoch_head_attesting_balance = let previous_epoch_head_attesting_balance =
self.get_effective_balances(&previous_epoch_head_attester_indices[..], spec); self.get_effective_balances(&previous_epoch_head_attester_indices[..], spec);
debug!(
"previous_epoch_head_attester_balance of {} wei.",
previous_epoch_head_attesting_balance
);
/* /*
* Eth1 Data * Eth1 Data
*/ */
@ -295,7 +307,8 @@ impl BeaconState {
/* /*
* Justification and finalization * Justification and finalization
*/ */
let epochs_since_finality = (self.slot - self.finalized_slot) / spec.epoch_length; let epochs_since_finality =
self.slot.saturating_sub(self.finalized_slot) / spec.epoch_length;
// TODO: fix this extra map // TODO: fix this extra map
let previous_epoch_justified_attester_indices_hashset: HashSet<usize> = let previous_epoch_justified_attester_indices_hashset: HashSet<usize> =
@ -307,6 +320,8 @@ impl BeaconState {
let previous_epoch_attester_indices_hashset: HashSet<usize> = let previous_epoch_attester_indices_hashset: HashSet<usize> =
HashSet::from_iter(previous_epoch_attester_indices.iter().map(|i| *i)); HashSet::from_iter(previous_epoch_attester_indices.iter().map(|i| *i));
debug!("{} epochs since finality.", epochs_since_finality);
if epochs_since_finality <= 4 { if epochs_since_finality <= 4 {
for index in 0..self.validator_balances.len() { for index in 0..self.validator_balances.len() {
let base_reward = self.base_reward(index, base_reward_quotient, spec); let base_reward = self.base_reward(index, base_reward_quotient, spec);
@ -341,7 +356,7 @@ impl BeaconState {
for index in previous_epoch_attester_indices { for index in previous_epoch_attester_indices {
let base_reward = self.base_reward(index, base_reward_quotient, spec); let base_reward = self.base_reward(index, base_reward_quotient, spec);
let inclusion_distance = self.inclusion_distance(index, spec)?; let inclusion_distance = self.inclusion_distance(&previous_epoch_attestations, index, spec)?;
safe_add_assign!( safe_add_assign!(
self.validator_balances[index], self.validator_balances[index],
@ -372,7 +387,7 @@ impl BeaconState {
for index in previous_epoch_attester_indices { for index in previous_epoch_attester_indices {
let base_reward = self.base_reward(index, base_reward_quotient, spec); let base_reward = self.base_reward(index, base_reward_quotient, spec);
let inclusion_distance = self.inclusion_distance(index, spec)?; let inclusion_distance = self.inclusion_distance(&previous_epoch_attestations, index, spec)?;
safe_sub_assign!( safe_sub_assign!(
self.validator_balances[index], self.validator_balances[index],
@ -388,7 +403,7 @@ impl BeaconState {
* Attestation inclusion * Attestation inclusion
*/ */
for index in previous_epoch_attester_indices_hashset { for index in previous_epoch_attester_indices_hashset {
let inclusion_slot = self.inclusion_slot(index, spec)?; let inclusion_slot = self.inclusion_slot(&previous_epoch_attestations[..], index, spec)?;
let proposer_index = self let proposer_index = self
.get_beacon_proposer_index(inclusion_slot, spec) .get_beacon_proposer_index(inclusion_slot, spec)
.map_err(|_| Error::UnableToDetermineProducer)?; .map_err(|_| Error::UnableToDetermineProducer)?;
@ -499,7 +514,7 @@ impl BeaconState {
self.latest_attestations = self self.latest_attestations = self
.latest_attestations .latest_attestations
.iter() .iter()
.filter(|a| a.data.slot < self.slot - spec.epoch_length) .filter(|a| a.data.slot / spec.epoch_length >= self.current_epoch(spec))
.cloned() .cloned()
.collect(); .collect();
@ -656,10 +671,11 @@ impl BeaconState {
fn inclusion_distance( fn inclusion_distance(
&self, &self,
attestations: &[&PendingAttestation],
validator_index: usize, validator_index: usize,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<u64, InclusionError> { ) -> Result<u64, InclusionError> {
let attestation = self.earliest_included_attestation(validator_index, spec)?; let attestation = self.earliest_included_attestation(attestations, validator_index, spec)?;
Ok(attestation Ok(attestation
.slot_included .slot_included
.saturating_sub(attestation.data.slot)) .saturating_sub(attestation.data.slot))
@ -667,21 +683,23 @@ impl BeaconState {
fn inclusion_slot( fn inclusion_slot(
&self, &self,
attestations: &[&PendingAttestation],
validator_index: usize, validator_index: usize,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<u64, InclusionError> { ) -> Result<u64, InclusionError> {
let attestation = self.earliest_included_attestation(validator_index, spec)?; let attestation = self.earliest_included_attestation(attestations, validator_index, spec)?;
Ok(attestation.slot_included) Ok(attestation.slot_included)
} }
fn earliest_included_attestation( fn earliest_included_attestation(
&self, &self,
attestations: &[&PendingAttestation],
validator_index: usize, validator_index: usize,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<&PendingAttestation, InclusionError> { ) -> Result<PendingAttestation, InclusionError> {
let mut included_attestations = vec![]; let mut included_attestations = vec![];
for a in &self.latest_attestations { for (i, a) in attestations.iter().enumerate() {
let participants = let participants =
self.get_attestation_participants(&a.data, &a.aggregation_bitfield, spec)?; self.get_attestation_participants(&a.data, &a.aggregation_bitfield, spec)?;
if participants if participants
@ -689,29 +707,15 @@ impl BeaconState {
.find(|i| **i == validator_index) .find(|i| **i == validator_index)
.is_some() .is_some()
{ {
included_attestations.push(a); included_attestations.push(i);
} }
} }
Ok(included_attestations let earliest_attestation_index = included_attestations
.iter() .iter()
.min_by_key(|a| a.slot_included) .min_by_key(|i| attestations[**i].slot_included)
.and_then(|x| Some(*x)) .ok_or_else(|| InclusionError::NoIncludedAttestations)?;
.ok_or_else(|| InclusionError::NoIncludedAttestations)?) Ok(attestations[*earliest_attestation_index].clone())
/*
self.latest_attestations
.iter()
.try_for_each(|a| {
self.get_attestation_participants(&a.data, &a.aggregation_bitfield, spec)
})?
.filter(|participants| {
participants
.iter()
.find(|i| **i == validator_index)
.is_some()
})
.min_by_key(|a| a.slot_included)
*/
} }
fn base_reward( fn base_reward(

View File

@ -36,19 +36,9 @@ impl BeaconState {
if committee.iter().find(|i| **i == validator_index).is_some() { if committee.iter().find(|i| **i == validator_index).is_some() {
result = Some(Ok((slot, shard))); result = Some(Ok((slot, shard)));
} }
} }
} }
result.unwrap() result.unwrap()
/*
// TODO: this is a stub; implement it properly.
let validator_index = validator_index as u64;
let slot = validator_index % spec.epoch_length;
let shard = validator_index % spec.shard_count;
(slot, shard)
*/
} }
} }