From 17210faf3a3c9dd6f1266e19941888ecbdf71e6a Mon Sep 17 00:00:00 2001 From: Paul Hauner Date: Wed, 6 Mar 2019 17:14:54 +1100 Subject: [PATCH] Start reorg of per_epoch_processing --- eth2/state_processing/src/lib.rs | 6 +- .../src/per_block_processing.rs | 3 +- .../src/{ => per_block_processing}/errors.rs | 0 .../validate_attestation.rs | 2 +- .../verify_attester_slashing.rs | 2 +- .../per_block_processing/verify_deposit.rs | 2 +- .../src/per_block_processing/verify_exit.rs | 2 +- .../verify_proposer_slashing.rs | 2 +- .../verify_slashable_attestation.rs | 2 +- .../per_block_processing/verify_transfer.rs | 2 +- ...processable.rs => per_epoch_processing.rs} | 121 +----------------- .../src/per_epoch_processing/errors.rs | 36 ++++++ .../tests.rs | 0 .../src/per_epoch_processing/winning_root.rs | 85 ++++++++++++ 14 files changed, 136 insertions(+), 129 deletions(-) rename eth2/state_processing/src/{ => per_block_processing}/errors.rs (100%) rename eth2/state_processing/src/{epoch_processable.rs => per_epoch_processing.rs} (88%) create mode 100644 eth2/state_processing/src/per_epoch_processing/errors.rs rename eth2/state_processing/src/{epoch_processable => per_epoch_processing}/tests.rs (100%) create mode 100644 eth2/state_processing/src/per_epoch_processing/winning_root.rs diff --git a/eth2/state_processing/src/lib.rs b/eth2/state_processing/src/lib.rs index ec883ddca..a5cc4f26e 100644 --- a/eth2/state_processing/src/lib.rs +++ b/eth2/state_processing/src/lib.rs @@ -1,12 +1,12 @@ #[macro_use] mod macros; + pub mod per_block_processing; -// mod epoch_processable; -pub mod errors; +pub mod per_epoch_processing; // mod slot_processable; -pub use errors::{BlockInvalid, BlockProcessingError}; pub use per_block_processing::{ + errors::{BlockInvalid, BlockProcessingError}, per_block_processing, per_block_processing_without_verifying_block_signature, }; // pub use epoch_processable::{EpochProcessable, Error as EpochProcessingError}; diff --git a/eth2/state_processing/src/per_block_processing.rs b/eth2/state_processing/src/per_block_processing.rs index 573513819..fc3a8204e 100644 --- a/eth2/state_processing/src/per_block_processing.rs +++ b/eth2/state_processing/src/per_block_processing.rs @@ -1,5 +1,5 @@ use self::verify_proposer_slashing::verify_proposer_slashing; -use crate::errors::{BlockInvalid as Invalid, BlockProcessingError as Error, IntoWithIndex}; +use errors::{BlockInvalid as Invalid, BlockProcessingError as Error, IntoWithIndex}; use hashing::hash; use log::debug; use ssz::{ssz_encode, SignedRoot, TreeHash}; @@ -11,6 +11,7 @@ pub use verify_deposit::verify_deposit; pub use verify_exit::verify_exit; pub use verify_transfer::verify_transfer; +pub mod errors; mod validate_attestation; mod verify_attester_slashing; mod verify_deposit; diff --git a/eth2/state_processing/src/errors.rs b/eth2/state_processing/src/per_block_processing/errors.rs similarity index 100% rename from eth2/state_processing/src/errors.rs rename to eth2/state_processing/src/per_block_processing/errors.rs diff --git a/eth2/state_processing/src/per_block_processing/validate_attestation.rs b/eth2/state_processing/src/per_block_processing/validate_attestation.rs index 8749bc5ea..54bd2d332 100644 --- a/eth2/state_processing/src/per_block_processing/validate_attestation.rs +++ b/eth2/state_processing/src/per_block_processing/validate_attestation.rs @@ -1,4 +1,4 @@ -use crate::errors::{AttestationInvalid as Invalid, AttestationValidationError as Error}; +use super::errors::{AttestationInvalid as Invalid, AttestationValidationError as Error}; use ssz::TreeHash; use types::beacon_state::helpers::*; use types::*; diff --git a/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs b/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs index aef09943a..71ac97469 100644 --- a/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs +++ b/eth2/state_processing/src/per_block_processing/verify_attester_slashing.rs @@ -1,5 +1,5 @@ +use super::errors::{AttesterSlashingInvalid as Invalid, AttesterSlashingValidationError as Error}; use super::verify_slashable_attestation::verify_slashable_attestation; -use crate::errors::{AttesterSlashingInvalid as Invalid, AttesterSlashingValidationError as Error}; use types::*; /// Indicates if an `AttesterSlashing` is valid to be included in a block in the current epoch of the given diff --git a/eth2/state_processing/src/per_block_processing/verify_deposit.rs b/eth2/state_processing/src/per_block_processing/verify_deposit.rs index 59a2a66c4..a1731f1a1 100644 --- a/eth2/state_processing/src/per_block_processing/verify_deposit.rs +++ b/eth2/state_processing/src/per_block_processing/verify_deposit.rs @@ -1,4 +1,4 @@ -use crate::errors::{DepositInvalid as Invalid, DepositValidationError as Error}; +use super::errors::{DepositInvalid as Invalid, DepositValidationError as Error}; use types::*; /// Indicates if a `Deposit` is valid to be included in a block in the current epoch of the given diff --git a/eth2/state_processing/src/per_block_processing/verify_exit.rs b/eth2/state_processing/src/per_block_processing/verify_exit.rs index 34c55c55e..408b77077 100644 --- a/eth2/state_processing/src/per_block_processing/verify_exit.rs +++ b/eth2/state_processing/src/per_block_processing/verify_exit.rs @@ -1,4 +1,4 @@ -use crate::errors::{ExitInvalid as Invalid, ExitValidationError as Error}; +use super::errors::{ExitInvalid as Invalid, ExitValidationError as Error}; use ssz::SignedRoot; use types::*; diff --git a/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs b/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs index c4e51b1a8..0350255ec 100644 --- a/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs +++ b/eth2/state_processing/src/per_block_processing/verify_proposer_slashing.rs @@ -1,4 +1,4 @@ -use crate::errors::{ProposerSlashingInvalid as Invalid, ProposerSlashingValidationError as Error}; +use super::errors::{ProposerSlashingInvalid as Invalid, ProposerSlashingValidationError as Error}; use ssz::SignedRoot; use types::*; diff --git a/eth2/state_processing/src/per_block_processing/verify_slashable_attestation.rs b/eth2/state_processing/src/per_block_processing/verify_slashable_attestation.rs index 0b948ad89..f0d371043 100644 --- a/eth2/state_processing/src/per_block_processing/verify_slashable_attestation.rs +++ b/eth2/state_processing/src/per_block_processing/verify_slashable_attestation.rs @@ -1,4 +1,4 @@ -use crate::errors::{ +use super::errors::{ SlashableAttestationInvalid as Invalid, SlashableAttestationValidationError as Error, }; use ssz::TreeHash; diff --git a/eth2/state_processing/src/per_block_processing/verify_transfer.rs b/eth2/state_processing/src/per_block_processing/verify_transfer.rs index 220f5e496..cd7bcb42c 100644 --- a/eth2/state_processing/src/per_block_processing/verify_transfer.rs +++ b/eth2/state_processing/src/per_block_processing/verify_transfer.rs @@ -1,4 +1,4 @@ -use crate::errors::{TransferInvalid as Invalid, TransferValidationError as Error}; +use super::errors::{TransferInvalid as Invalid, TransferValidationError as Error}; use types::*; /// Indicates if a `Transfer` is valid to be included in a block in the current epoch of the given diff --git a/eth2/state_processing/src/epoch_processable.rs b/eth2/state_processing/src/per_epoch_processing.rs similarity index 88% rename from eth2/state_processing/src/epoch_processable.rs rename to eth2/state_processing/src/per_epoch_processing.rs index 0d6ca8038..4c66d8ddc 100644 --- a/eth2/state_processing/src/epoch_processable.rs +++ b/eth2/state_processing/src/per_epoch_processing.rs @@ -1,3 +1,4 @@ +use errors::EpochProcessingError as Error; use integer_sqrt::IntegerSquareRoot; use log::{debug, trace}; use rayon::prelude::*; @@ -9,7 +10,9 @@ use types::{ Crosslink, Epoch, Hash256, InclusionError, PendingAttestation, RelativeEpoch, }; +mod errors; mod tests; +mod winning_root; macro_rules! safe_add_assign { ($a: expr, $b: expr) => { @@ -22,31 +25,6 @@ macro_rules! safe_sub_assign { }; } -#[derive(Debug, PartialEq)] -pub enum Error { - UnableToDetermineProducer, - NoBlockRoots, - BaseRewardQuotientIsZero, - NoRandaoSeed, - BeaconStateError(BeaconStateError), - InclusionError(InclusionError), - WinningRootError(WinningRootError), -} - -#[derive(Debug, PartialEq)] -pub enum WinningRootError { - NoWinningRoot, - BeaconStateError(BeaconStateError), -} - -#[derive(Clone)] -pub struct WinningRoot { - pub shard_block_root: Hash256, - pub attesting_validator_indices: Vec, - pub total_balance: u64, - pub total_attesting_balance: u64, -} - pub trait EpochProcessable { fn per_epoch_processing(&mut self, spec: &ChainSpec) -> Result<(), Error>; } @@ -628,96 +606,3 @@ impl EpochProcessable for BeaconState { fn hash_tree_root(input: Vec) -> Hash256 { Hash256::from(&input.hash_tree_root()[..]) } - -fn winning_root( - state: &BeaconState, - shard: u64, - current_epoch_attestations: &[&PendingAttestation], - previous_epoch_attestations: &[&PendingAttestation], - spec: &ChainSpec, -) -> Result { - let mut attestations = current_epoch_attestations.to_vec(); - attestations.append(&mut previous_epoch_attestations.to_vec()); - - let mut candidates: HashMap = 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()) -} - -impl From for Error { - fn from(e: InclusionError) -> Error { - Error::InclusionError(e) - } -} - -impl From for Error { - fn from(e: BeaconStateError) -> Error { - Error::BeaconStateError(e) - } -} - -impl From for WinningRootError { - fn from(e: BeaconStateError) -> WinningRootError { - WinningRootError::BeaconStateError(e) - } -} diff --git a/eth2/state_processing/src/per_epoch_processing/errors.rs b/eth2/state_processing/src/per_epoch_processing/errors.rs new file mode 100644 index 000000000..0f7063e3b --- /dev/null +++ b/eth2/state_processing/src/per_epoch_processing/errors.rs @@ -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 for EpochProcessingError { + fn from(e: InclusionError) -> EpochProcessingError { + EpochProcessingError::InclusionError(e) + } +} + +impl From for EpochProcessingError { + fn from(e: BeaconStateError) -> EpochProcessingError { + EpochProcessingError::BeaconStateError(e) + } +} + +impl From for WinningRootError { + fn from(e: BeaconStateError) -> WinningRootError { + WinningRootError::BeaconStateError(e) + } +} diff --git a/eth2/state_processing/src/epoch_processable/tests.rs b/eth2/state_processing/src/per_epoch_processing/tests.rs similarity index 100% rename from eth2/state_processing/src/epoch_processable/tests.rs rename to eth2/state_processing/src/per_epoch_processing/tests.rs diff --git a/eth2/state_processing/src/per_epoch_processing/winning_root.rs b/eth2/state_processing/src/per_epoch_processing/winning_root.rs new file mode 100644 index 000000000..5b1e5925f --- /dev/null +++ b/eth2/state_processing/src/per_epoch_processing/winning_root.rs @@ -0,0 +1,85 @@ +use super::WinningRootError; +use types::*; + +#[derive(Clone)] +pub struct WinningRoot { + pub shard_block_root: Hash256, + pub attesting_validator_indices: Vec, + 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 { + let mut attestations = current_epoch_attestations.to_vec(); + attestations.append(&mut previous_epoch_attestations.to_vec()); + + let mut candidates: HashMap = 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()) +}