mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-19 21:04:41 +00:00
Single-pass epoch processing and optimised block processing (#5279)
* Single-pass epoch processing (#4483, #4573) Co-authored-by: Michael Sproul <michael@sigmaprime.io> * Delete unused epoch processing code (#5170) * Delete unused epoch processing code * Compare total deltas * Remove unnecessary apply_pending * cargo fmt * Remove newline * Use epoch cache in block packing (#5223) * Remove progressive balances mode (#5224) * inline inactivity_penalty_quotient_for_state * drop previous_epoch_total_active_balance * fc lint * spec compliant process_sync_aggregate (#15) * spec compliant process_sync_aggregate * Update consensus/state_processing/src/per_block_processing/altair/sync_committee.rs Co-authored-by: Michael Sproul <micsproul@gmail.com> --------- Co-authored-by: Michael Sproul <micsproul@gmail.com> * Delete the participation cache (#16) * update help * Fix op_pool tests * Fix fork choice tests * Merge remote-tracking branch 'sigp/unstable' into epoch-single-pass * Simplify exit cache (#5280) * Fix clippy on exit cache * Clean up single-pass a bit (#5282) * Address Mark's review of single-pass (#5386) * Merge remote-tracking branch 'origin/unstable' into epoch-single-pass * Address Sean's review comments (#5414) * Address most of Sean's review comments * Simplify total balance cache building * Clean up unused junk * Merge remote-tracking branch 'origin/unstable' into epoch-single-pass * More self-review * Merge remote-tracking branch 'origin/unstable' into epoch-single-pass * Merge branch 'unstable' into epoch-single-pass * Fix imports for beta compiler * Fix tests, probably
This commit is contained in:
@@ -1,28 +1,14 @@
|
||||
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
|
||||
use eth2::lighthouse::attestation_rewards::{IdealAttestationRewards, TotalAttestationRewards};
|
||||
use eth2::lighthouse::StandardAttestationRewards;
|
||||
use participation_cache::ParticipationCache;
|
||||
use eth2::types::ValidatorId;
|
||||
use safe_arith::SafeArith;
|
||||
use serde_utils::quoted_u64::Quoted;
|
||||
use slog::debug;
|
||||
use state_processing::common::base::{self, SqrtTotalActiveBalance};
|
||||
use state_processing::per_epoch_processing::altair::{
|
||||
process_inactivity_updates, process_justification_and_finalization,
|
||||
process_inactivity_updates_slow, process_justification_and_finalization,
|
||||
};
|
||||
use state_processing::{
|
||||
common::altair::BaseRewardPerIncrement,
|
||||
per_epoch_processing::altair::{participation_cache, rewards_and_penalties::get_flag_weight},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use store::consts::altair::{
|
||||
PARTICIPATION_FLAG_WEIGHTS, TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX,
|
||||
TIMELY_TARGET_FLAG_INDEX,
|
||||
};
|
||||
use types::consts::altair::WEIGHT_DENOMINATOR;
|
||||
|
||||
use types::{BeaconState, Epoch, EthSpec};
|
||||
|
||||
use eth2::types::ValidatorId;
|
||||
use state_processing::common::base::get_base_reward_from_effective_balance;
|
||||
use state_processing::per_epoch_processing::base::rewards_and_penalties::{
|
||||
get_attestation_component_delta, get_attestation_deltas_all, get_attestation_deltas_subset,
|
||||
get_inactivity_penalty_delta, get_inclusion_delay_delta,
|
||||
@@ -32,6 +18,19 @@ use state_processing::per_epoch_processing::base::{
|
||||
process_justification_and_finalization as process_justification_and_finalization_base,
|
||||
TotalBalances, ValidatorStatus, ValidatorStatuses,
|
||||
};
|
||||
use state_processing::{
|
||||
common::altair::BaseRewardPerIncrement,
|
||||
common::update_progressive_balances_cache::initialize_progressive_balances_cache,
|
||||
epoch_cache::initialize_epoch_cache,
|
||||
per_epoch_processing::altair::rewards_and_penalties::get_flag_weight,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use store::consts::altair::{
|
||||
PARTICIPATION_FLAG_WEIGHTS, TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX,
|
||||
TIMELY_TARGET_FLAG_INDEX,
|
||||
};
|
||||
use types::consts::altair::WEIGHT_DENOMINATOR;
|
||||
use types::{BeaconState, Epoch, EthSpec, RelativeEpoch};
|
||||
|
||||
impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub fn compute_attestation_rewards(
|
||||
@@ -134,11 +133,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
) -> Result<StandardAttestationRewards, BeaconChainError> {
|
||||
let spec = &self.spec;
|
||||
|
||||
// Build required caches.
|
||||
initialize_epoch_cache(&mut state, spec)?;
|
||||
initialize_progressive_balances_cache(&mut state, spec)?;
|
||||
state.build_exit_cache(spec)?;
|
||||
state.build_committee_cache(RelativeEpoch::Previous, spec)?;
|
||||
state.build_committee_cache(RelativeEpoch::Current, spec)?;
|
||||
|
||||
// Calculate ideal_rewards
|
||||
let participation_cache = ParticipationCache::new(&state, spec)?;
|
||||
process_justification_and_finalization(&state, &participation_cache)?
|
||||
.apply_changes_to_state(&mut state);
|
||||
process_inactivity_updates(&mut state, &participation_cache, spec)?;
|
||||
process_justification_and_finalization(&state)?.apply_changes_to_state(&mut state);
|
||||
process_inactivity_updates_slow(&mut state, spec)?;
|
||||
|
||||
let previous_epoch = state.previous_epoch();
|
||||
|
||||
@@ -148,18 +152,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
let weight = get_flag_weight(flag_index)
|
||||
.map_err(|_| BeaconChainError::AttestationRewardsError)?;
|
||||
|
||||
let unslashed_participating_indices = participation_cache
|
||||
.get_unslashed_participating_indices(flag_index, previous_epoch)?;
|
||||
|
||||
let unslashed_participating_balance =
|
||||
unslashed_participating_indices
|
||||
.total_balance()
|
||||
.map_err(|_| BeaconChainError::AttestationRewardsError)?;
|
||||
let unslashed_participating_balance = state
|
||||
.progressive_balances_cache()
|
||||
.previous_epoch_flag_attesting_balance(flag_index)?;
|
||||
|
||||
let unslashed_participating_increments =
|
||||
unslashed_participating_balance.safe_div(spec.effective_balance_increment)?;
|
||||
|
||||
let total_active_balance = participation_cache.current_epoch_total_active_balance();
|
||||
let total_active_balance = state.get_total_active_balance()?;
|
||||
|
||||
let active_increments =
|
||||
total_active_balance.safe_div(spec.effective_balance_increment)?;
|
||||
@@ -195,30 +195,49 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
let mut total_rewards: Vec<TotalAttestationRewards> = Vec::new();
|
||||
|
||||
let validators = if validators.is_empty() {
|
||||
participation_cache.eligible_validator_indices().to_vec()
|
||||
Self::all_eligible_validator_indices(&state, previous_epoch)?
|
||||
} else {
|
||||
Self::validators_ids_to_indices(&mut state, validators)?
|
||||
};
|
||||
|
||||
for validator_index in &validators {
|
||||
let eligible = state.is_eligible_validator(previous_epoch, *validator_index)?;
|
||||
for &validator_index in &validators {
|
||||
// Return 0s for unknown/inactive validator indices.
|
||||
let Ok(validator) = state.get_validator(validator_index) else {
|
||||
debug!(
|
||||
self.log,
|
||||
"No rewards for inactive/unknown validator";
|
||||
"index" => validator_index,
|
||||
"epoch" => previous_epoch
|
||||
);
|
||||
total_rewards.push(TotalAttestationRewards {
|
||||
validator_index: validator_index as u64,
|
||||
head: 0,
|
||||
target: 0,
|
||||
source: 0,
|
||||
inclusion_delay: None,
|
||||
inactivity: 0,
|
||||
});
|
||||
continue;
|
||||
};
|
||||
let previous_epoch_participation_flags = state
|
||||
.previous_epoch_participation()?
|
||||
.get(validator_index)
|
||||
.ok_or(BeaconChainError::AttestationRewardsError)?;
|
||||
let eligible = state.is_eligible_validator(previous_epoch, validator)?;
|
||||
let mut head_reward = 0i64;
|
||||
let mut target_reward = 0i64;
|
||||
let mut source_reward = 0i64;
|
||||
let mut inactivity_penalty = 0i64;
|
||||
|
||||
if eligible {
|
||||
let effective_balance = state.get_effective_balance(*validator_index)?;
|
||||
let effective_balance = validator.effective_balance;
|
||||
|
||||
for flag_index in 0..PARTICIPATION_FLAG_WEIGHTS.len() {
|
||||
let (ideal_reward, penalty) = ideal_rewards_hashmap
|
||||
.get(&(flag_index, effective_balance))
|
||||
.ok_or(BeaconChainError::AttestationRewardsError)?;
|
||||
let voted_correctly = participation_cache
|
||||
.get_unslashed_participating_indices(flag_index, previous_epoch)
|
||||
.map_err(|_| BeaconChainError::AttestationRewardsError)?
|
||||
.contains(*validator_index)
|
||||
.map_err(|_| BeaconChainError::AttestationRewardsError)?;
|
||||
let voted_correctly = !validator.slashed
|
||||
&& previous_epoch_participation_flags.has_flag(flag_index)?;
|
||||
if voted_correctly {
|
||||
if flag_index == TIMELY_HEAD_FLAG_INDEX {
|
||||
head_reward += *ideal_reward as i64;
|
||||
@@ -233,10 +252,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
target_reward = *penalty;
|
||||
|
||||
let penalty_numerator = effective_balance
|
||||
.safe_mul(state.get_inactivity_score(*validator_index)?)?;
|
||||
let penalty_denominator = spec
|
||||
.inactivity_score_bias
|
||||
.safe_mul(spec.inactivity_penalty_quotient_for_state(&state))?;
|
||||
.safe_mul(state.get_inactivity_score(validator_index)?)?;
|
||||
let penalty_denominator = spec.inactivity_score_bias.safe_mul(
|
||||
spec.inactivity_penalty_quotient_for_fork(state.fork_name_unchecked()),
|
||||
)?;
|
||||
inactivity_penalty =
|
||||
-(penalty_numerator.safe_div(penalty_denominator)? as i64);
|
||||
} else if flag_index == TIMELY_SOURCE_FLAG_INDEX {
|
||||
@@ -245,7 +264,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
}
|
||||
}
|
||||
total_rewards.push(TotalAttestationRewards {
|
||||
validator_index: *validator_index as u64,
|
||||
validator_index: validator_index as u64,
|
||||
head: head_reward,
|
||||
target: target_reward,
|
||||
source: source_reward,
|
||||
@@ -302,6 +321,24 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
Ok(max_steps)
|
||||
}
|
||||
|
||||
fn all_eligible_validator_indices(
|
||||
state: &BeaconState<T::EthSpec>,
|
||||
previous_epoch: Epoch,
|
||||
) -> Result<Vec<usize>, BeaconChainError> {
|
||||
state
|
||||
.validators()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, validator)| {
|
||||
state
|
||||
.is_eligible_validator(previous_epoch, validator)
|
||||
.map(|eligible| eligible.then_some(i))
|
||||
.map_err(BeaconChainError::BeaconStateError)
|
||||
.transpose()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn validators_ids_to_indices(
|
||||
state: &mut BeaconState<T::EthSpec>,
|
||||
validators: Vec<ValidatorId>,
|
||||
@@ -340,15 +377,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
};
|
||||
|
||||
let mut ideal_attestation_rewards_list = Vec::new();
|
||||
|
||||
let sqrt_total_active_balance = SqrtTotalActiveBalance::new(total_balances.current_epoch());
|
||||
for effective_balance_step in 1..=self.max_effective_balance_increment_steps()? {
|
||||
let effective_balance =
|
||||
effective_balance_step.safe_mul(spec.effective_balance_increment)?;
|
||||
let base_reward = get_base_reward_from_effective_balance::<T::EthSpec>(
|
||||
effective_balance,
|
||||
total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
let base_reward =
|
||||
base::get_base_reward(effective_balance, sqrt_total_active_balance, spec)?;
|
||||
|
||||
// compute ideal head rewards
|
||||
let head = get_attestation_component_delta(
|
||||
|
||||
Reference in New Issue
Block a user