Skip to content

Commit 2c18537

Browse files
committed
Tidy, add comments
1 parent 9cd00db commit 2c18537

File tree

1 file changed

+80
-11
lines changed

1 file changed

+80
-11
lines changed

consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
//! Provides the `ParticipationCache`, a custom Lighthouse cache which attempts to reduce CPU and
2+
//! memory usage by:
3+
//!
4+
//! - Caching a map of `validator_index -> participation_flags` for all active validators in the
5+
//! previous and current epochs.
6+
//! - Caching the total balances of:
7+
//! - All active validators.
8+
//! - All active validators matching each of the three "timely" flags.
9+
//! - Caching the "eligible" validators.
10+
//!
11+
//! Additionally, this cache is returned from the `altair::process_epoch` function and can be used
12+
//! to get useful summaries about the validator participation in an epoch.
13+
114
use safe_arith::{ArithError, SafeArith};
215
use std::collections::HashMap;
316
use types::{
@@ -8,34 +21,56 @@ use types::{
821
BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, ParticipationFlags, RelativeEpoch,
922
};
1023

24+
/// A balance which will never be below the specified `minimum`.
25+
///
26+
/// This is an attempt to ensure the `EFFECTIVE_BALANCE_INCREMENT` minimum is always respected.
1127
#[derive(PartialEq, Debug, Clone, Copy)]
1228
struct Balance {
1329
raw: u64,
1430
minimum: u64,
1531
}
1632

1733
impl Balance {
34+
/// Initialize the balance to `0`, or the given `minimum`.
1835
pub fn zero(minimum: u64) -> Self {
1936
Self { raw: 0, minimum }
2037
}
2138

39+
/// Returns the balance with respect to the initialization `minimum`.
2240
pub fn get(&self) -> u64 {
2341
std::cmp::max(self.raw, self.minimum)
2442
}
2543

44+
/// Add-assign to the balance.
2645
pub fn safe_add_assign(&mut self, other: u64) -> Result<(), ArithError> {
2746
self.raw.safe_add_assign(other)
2847
}
2948
}
3049

50+
/// Caches the participation values for one epoch (either the previous or current).
3151
#[derive(PartialEq, Debug)]
32-
struct EpochParticipation {
52+
struct SingleEpochParticipationCache {
53+
/// Maps an active validator index to their participation flags.
54+
///
55+
/// To reiterate, only active validator indices are stored in this map.
56+
///
57+
/// ## Note
58+
///
59+
/// It would be ideal to maintain a reference to the `BeaconState` here rather than copying the
60+
/// `ParticipationFlags`, however that would cause us to run into mutable reference limitations
61+
/// upstream.
3362
unslashed_participating_indices: HashMap<usize, ParticipationFlags>,
63+
/// Stores the sum of the balances for all validators in `self.unslashed_participating_indices`
64+
/// for all flags in `NUM_FLAG_INDICES`.
65+
///
66+
/// A flag balance is only incremented if a validator is that flag set.
3467
total_flag_balances: [Balance; NUM_FLAG_INDICES],
68+
/// Stores the sum of all balances of all validators in `self.unslashed_participating_indices`
69+
/// (regardless of which flags are set).
3570
total_active_balance: Balance,
3671
}
3772

38-
impl EpochParticipation {
73+
impl SingleEpochParticipationCache {
3974
pub fn new(hashmap_len: usize, spec: &ChainSpec) -> Self {
4075
let zero_balance = Balance::zero(spec.effective_balance_increment);
4176

@@ -46,20 +81,32 @@ impl EpochParticipation {
4681
}
4782
}
4883

84+
/// Process an **active** validator.
85+
///
86+
/// ## Errors
87+
///
88+
/// - The provided `state` **must** be Altair, otherwise an error will be returned.
89+
///
90+
/// ## Warning
91+
///
92+
/// - It is a logic error to provide an inactive validator to this function.
4993
pub fn process_active_validator<T: EthSpec>(
5094
&mut self,
5195
val_index: usize,
5296
state: &BeaconState<T>,
5397
epoch_participation: &[ParticipationFlags],
5498
) -> Result<(), BeaconStateError> {
5599
let val_balance = state.get_effective_balance(val_index)?;
100+
101+
// All active validator increase the total active balance.
56102
self.total_active_balance.safe_add_assign(val_balance)?;
57103

58104
if state.get_validator(val_index)?.slashed {
59105
return Ok(());
60106
}
61107

62-
// Iterate through all the flags and increment total balances.
108+
// Iterate through all the flags and increment the total flag balances for whichever flags
109+
// are set for `val_index`.
63110
self.total_flag_balances
64111
.iter_mut()
65112
.enumerate()
@@ -87,16 +134,25 @@ impl EpochParticipation {
87134
}
88135
}
89136

137+
/// Maintains a cache to be used during `altair::process_epoch`.
90138
#[derive(PartialEq, Debug)]
91139
pub struct ParticipationCache {
92140
current_epoch: Epoch,
93-
current_epoch_participation: EpochParticipation,
141+
/// Caches information about active validators pertaining to `self.current_epoch`.
142+
current_epoch_participation: SingleEpochParticipationCache,
94143
previous_epoch: Epoch,
95-
previous_epoch_participation: EpochParticipation,
144+
/// Caches information about active validators pertaining to `self.previous_epoch`.
145+
previous_epoch_participation: SingleEpochParticipationCache,
146+
/// Caches the result of the `get_eligible_validator_indices` function.
96147
eligible_indices: Vec<usize>,
97148
}
98149

99150
impl ParticipationCache {
151+
/// Instantiate `Self`, returning a cache that is fully initialized and ready-to-go.
152+
///
153+
/// ## Errors
154+
///
155+
/// - The provided `state` **must** be an Altair state, otherwise an error will be returned.
100156
pub fn new<T: EthSpec>(
101157
state: &BeaconState<T>,
102158
spec: &ChainSpec,
@@ -112,10 +168,10 @@ impl ParticipationCache {
112168
.len();
113169

114170
let mut current_epoch_participation =
115-
EpochParticipation::new(num_current_epoch_active_vals, spec);
171+
SingleEpochParticipationCache::new(num_current_epoch_active_vals, spec);
116172
let mut previous_epoch_participation =
117-
EpochParticipation::new(num_previous_epoch_active_vals, spec);
118-
let mut eligible_indices = Vec::with_capacity(state.validators().len());
173+
SingleEpochParticipationCache::new(num_previous_epoch_active_vals, spec);
174+
let mut eligible_indices = Vec::with_capacity(num_previous_epoch_active_vals);
119175

120176
for (val_index, val) in state.validators().iter().enumerate() {
121177
if val.is_active_at(current_epoch) {
@@ -139,8 +195,6 @@ impl ParticipationCache {
139195
}
140196
}
141197

142-
eligible_indices.shrink_to_fit();
143-
144198
Ok(Self {
145199
current_epoch,
146200
current_epoch_participation,
@@ -150,6 +204,7 @@ impl ParticipationCache {
150204
})
151205
}
152206

207+
/// Equivalent to the specification `get_eligible_validator_indices` function.
153208
pub fn eligible_validator_indices(&self) -> &[usize] {
154209
&self.eligible_indices
155210
}
@@ -182,6 +237,7 @@ impl ParticipationCache {
182237
self.current_epoch_participation.total_active_balance.get()
183238
}
184239

240+
/// Equivalent to the `get_unslashed_participating_indices` function in the specification.
185241
pub fn get_unslashed_participating_indices(
186242
&self,
187243
flag_index: usize,
@@ -254,12 +310,20 @@ impl ParticipationCache {
254310
}
255311
}
256312

313+
/// Imitates the return value of the `get_unslashed_participating_indices` in the
314+
/// specification.
315+
///
316+
/// This struct exists to help make the Lighthouse code read more like the specification.
257317
pub struct UnslashedParticipatingIndices<'a> {
258-
participation: &'a EpochParticipation,
318+
participation: &'a SingleEpochParticipationCache,
259319
flag_index: usize,
260320
}
261321

262322
impl<'a> UnslashedParticipatingIndices<'a> {
323+
/// Returns `Ok(true)` if the given `val_index` is:
324+
///
325+
/// - An active validator.
326+
/// - Has `self.flag_index` set.
263327
pub fn contains(&self, val_index: usize) -> Result<bool, ArithError> {
264328
self.participation
265329
.unslashed_participating_indices
@@ -268,6 +332,11 @@ impl<'a> UnslashedParticipatingIndices<'a> {
268332
.unwrap_or(Ok(false))
269333
}
270334

335+
/// Returns the sum of all balances of validators which have `self.flag_index` set.
336+
///
337+
/// ## Notes
338+
///
339+
/// Respects the `EFFECTIVE_BALANCE_INCREMENT` minimum.
271340
pub fn total_balance(&self) -> Result<u64, BeaconStateError> {
272341
self.participation
273342
.total_flag_balances

0 commit comments

Comments
 (0)