Skip to content

Commit d4f87ef

Browse files
committed
Fix three consensus bugs!
1 parent ca1abfe commit d4f87ef

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

consensus/state_processing/src/epoch_cache.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,23 @@ pub fn initialize_epoch_cache<E: EthSpec>(
7979
state: &mut BeaconState<E>,
8080
spec: &ChainSpec,
8181
) -> Result<(), EpochCacheError> {
82-
let epoch = state.current_epoch();
82+
let current_epoch = state.current_epoch();
83+
let next_epoch = state.next_epoch().map_err(EpochCacheError::BeaconState)?;
8384
let epoch_cache: &EpochCache = state.epoch_cache();
8485
let decision_block_root = state
8586
.proposer_shuffling_decision_root(Hash256::zero())
8687
.map_err(EpochCacheError::BeaconState)?;
8788

8889
if epoch_cache
89-
.check_validity::<E>(epoch, decision_block_root)
90+
.check_validity::<E>(current_epoch, decision_block_root)
9091
.is_ok()
9192
{
9293
// `EpochCache` has already been initialized and is valid, no need to initialize.
9394
return Ok(());
9495
}
9596

96-
state.build_total_active_balance_cache_at(epoch, spec)?;
97-
let total_active_balance = state.get_total_active_balance_at_epoch(epoch)?;
97+
state.build_total_active_balance_cache_at(current_epoch, spec)?;
98+
let total_active_balance = state.get_total_active_balance_at_epoch(current_epoch)?;
9899

99100
// Collect effective balances and compute activation queue.
100101
let mut effective_balances = Vec::with_capacity(state.validators().len());
@@ -104,13 +105,14 @@ pub fn initialize_epoch_cache<E: EthSpec>(
104105
effective_balances.push(validator.effective_balance());
105106

106107
// Add to speculative activation queue.
107-
activation_queue.add_if_could_be_eligible_for_activation(index, validator, epoch, spec);
108+
activation_queue
109+
.add_if_could_be_eligible_for_activation(index, validator, next_epoch, spec);
108110
}
109111

110112
// Compute base rewards.
111113
let pre_epoch_cache = PreEpochCache {
112114
epoch_key: EpochCacheKey {
113-
epoch,
115+
epoch: current_epoch,
114116
decision_block_root,
115117
},
116118
effective_balances,

consensus/state_processing/src/per_epoch_processing/single_pass.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ pub fn process_epoch_single_pass<E: EthSpec>(
120120
let is_in_inactivity_leak = state.is_in_inactivity_leak(previous_epoch, spec)?;
121121
let total_active_balance = state.get_total_active_balance()?;
122122
let churn_limit = state.get_churn_limit(spec)?;
123+
let activation_churn_limit = state.get_activation_churn_limit(spec)?;
123124
let finalized_checkpoint = state.finalized_checkpoint();
124125
let fork_name = state.fork_name_unchecked();
125126

@@ -164,7 +165,10 @@ pub fn process_epoch_single_pass<E: EthSpec>(
164165
let rewards_ctxt = &RewardsAndPenaltiesContext::new(progressive_balances, state_ctxt, spec)?;
165166
let activation_queue = &epoch_cache
166167
.activation_queue()?
167-
.get_validators_eligible_for_activation(finalized_checkpoint.epoch, churn_limit as usize);
168+
.get_validators_eligible_for_activation(
169+
finalized_checkpoint.epoch,
170+
activation_churn_limit as usize,
171+
);
168172
let effective_balances_ctxt = &EffectiveBalancesContext::new(spec)?;
169173

170174
// Iterate over the validators and related fields in one pass.
@@ -619,6 +623,7 @@ fn process_single_effective_balance_update(
619623
// Update progressive balances cache for the *current* epoch, which will soon become the
620624
// previous epoch once the epoch transition completes.
621625
progressive_balances.on_effective_balance_change(
626+
validator.slashed(),
622627
validator_info.current_epoch_participation,
623628
old_effective_balance,
624629
new_effective_balance,

consensus/types/src/beacon_state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ where
351351
#[test_random(default)]
352352
pub validators: VList<GenericValidator, T::ValidatorRegistryLimit>,
353353
#[serde(with = "ssz_types::serde_utils::quoted_u64_var_list")]
354+
#[compare_fields(as_iter)]
354355
#[test_random(default)]
355356
pub balances: VList<u64, T::ValidatorRegistryLimit>,
356357

consensus/types/src/beacon_state/progressive_balances_cache.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,16 @@ impl EpochTotalBalances {
9393

9494
pub fn on_effective_balance_change(
9595
&mut self,
96+
is_slashed: bool,
9697
current_epoch_participation_flags: ParticipationFlags,
9798
old_effective_balance: u64,
9899
new_effective_balance: u64,
99100
) -> Result<(), BeaconStateError> {
101+
// If the validator is slashed then we should not update the effective balance, because this
102+
// validator's effective balance has already been removed from the totals.
103+
if is_slashed {
104+
return Ok(());
105+
}
100106
for flag_index in 0..NUM_FLAG_INDICES {
101107
if current_epoch_participation_flags.has_flag(flag_index)? {
102108
let total = self
@@ -188,12 +194,14 @@ impl ProgressiveBalancesCache {
188194
/// its share of the target attesting balance in the cache.
189195
pub fn on_effective_balance_change(
190196
&mut self,
197+
is_slashed: bool,
191198
current_epoch_participation: ParticipationFlags,
192199
old_effective_balance: u64,
193200
new_effective_balance: u64,
194201
) -> Result<(), BeaconStateError> {
195202
let cache = self.get_inner_mut()?;
196203
cache.current_epoch_cache.on_effective_balance_change(
204+
is_slashed,
197205
current_epoch_participation,
198206
old_effective_balance,
199207
new_effective_balance,

0 commit comments

Comments
 (0)