Start reorg of per_epoch_processing

This commit is contained in:
Paul Hauner
2019-03-06 17:14:54 +11:00
parent 521d48d37c
commit 17210faf3a
14 changed files with 136 additions and 129 deletions

View File

@@ -0,0 +1,36 @@
use types::*;
#[derive(Debug, PartialEq)]
pub enum WinningRootError {
NoWinningRoot,
BeaconStateError(BeaconStateError),
}
#[derive(Debug, PartialEq)]
pub enum EpochProcessingError {
UnableToDetermineProducer,
NoBlockRoots,
BaseRewardQuotientIsZero,
NoRandaoSeed,
BeaconStateError(BeaconStateError),
InclusionError(InclusionError),
WinningRootError(WinningRootError),
}
impl From<InclusionError> for EpochProcessingError {
fn from(e: InclusionError) -> EpochProcessingError {
EpochProcessingError::InclusionError(e)
}
}
impl From<BeaconStateError> for EpochProcessingError {
fn from(e: BeaconStateError) -> EpochProcessingError {
EpochProcessingError::BeaconStateError(e)
}
}
impl From<BeaconStateError> for WinningRootError {
fn from(e: BeaconStateError) -> WinningRootError {
WinningRootError::BeaconStateError(e)
}
}

View File

@@ -0,0 +1,21 @@
#![cfg(test)]
use crate::EpochProcessable;
use env_logger::{Builder, Env};
use types::beacon_state::BeaconStateBuilder;
use types::*;
#[test]
fn runs_without_error() {
Builder::from_env(Env::default().default_filter_or("error")).init();
let mut builder = BeaconStateBuilder::new(8);
builder.spec = ChainSpec::few_validators();
builder.build().unwrap();
builder.teleport_to_end_of_epoch(builder.spec.genesis_epoch + 4);
let mut state = builder.cloned_state();
let spec = &builder.spec;
state.per_epoch_processing(spec).unwrap();
}

View File

@@ -0,0 +1,85 @@
use super::WinningRootError;
use types::*;
#[derive(Clone)]
pub struct WinningRoot {
pub shard_block_root: Hash256,
pub attesting_validator_indices: Vec<usize>,
pub total_balance: u64,
pub total_attesting_balance: u64,
}
fn winning_root(
state: &BeaconState,
shard: u64,
current_epoch_attestations: &[&PendingAttestation],
previous_epoch_attestations: &[&PendingAttestation],
spec: &ChainSpec,
) -> Result<WinningRoot, WinningRootError> {
let mut attestations = current_epoch_attestations.to_vec();
attestations.append(&mut previous_epoch_attestations.to_vec());
let mut candidates: HashMap<Hash256, WinningRoot> = HashMap::new();
let mut highest_seen_balance = 0;
for a in &attestations {
if a.data.shard != shard {
continue;
}
let shard_block_root = &a.data.shard_block_root;
if candidates.contains_key(shard_block_root) {
continue;
}
let attesting_validator_indices = attestations
.iter()
.try_fold::<_, _, Result<_, BeaconStateError>>(vec![], |mut acc, a| {
if (a.data.shard == shard) && (a.data.shard_block_root == *shard_block_root) {
acc.append(&mut state.get_attestation_participants(
&a.data,
&a.aggregation_bitfield,
spec,
)?);
}
Ok(acc)
})?;
let total_balance: u64 = attesting_validator_indices
.iter()
.fold(0, |acc, i| acc + state.get_effective_balance(*i, spec));
let total_attesting_balance: u64 = attesting_validator_indices
.iter()
.fold(0, |acc, i| acc + state.get_effective_balance(*i, spec));
if total_attesting_balance > highest_seen_balance {
highest_seen_balance = total_attesting_balance;
}
let candidate_root = WinningRoot {
shard_block_root: *shard_block_root,
attesting_validator_indices,
total_attesting_balance,
total_balance,
};
candidates.insert(*shard_block_root, candidate_root);
}
Ok(candidates
.iter()
.filter_map(|(_hash, candidate)| {
if candidate.total_attesting_balance == highest_seen_balance {
Some(candidate)
} else {
None
}
})
.min_by_key(|candidate| candidate.shard_block_root)
.ok_or_else(|| WinningRootError::NoWinningRoot)?
// TODO: avoid clone.
.clone())
}