Skip to content

Commit 6e3ca48

Browse files
Cache participating indices for Altair epoch processing (#2416)
## Issue Addressed NA ## Proposed Changes This PR addresses two things: 1. Allows the `ValidatorMonitor` to work with Altair states. 1. Optimizes `altair::process_epoch` (see [code](https://github.com/paulhauner/lighthouse/blob/participation-cache/consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs) for description) ## Breaking Changes The breaking changes in this PR revolve around one premise: *After the Altair fork, it's not longer possible (given only a `BeaconState`) to identify if a validator had *any* attestation included during some epoch. The best we can do is see if that validator made the "timely" source/target/head flags.* Whilst this seems annoying, it's not actually too bad. Finalization is based upon "timely target" attestations, so that's really the most important thing. Although there's *some* value in knowing if a validator had *any* attestation included, it's far more important to know about "timely target" participation, since this is what affects finality and justification. For simplicity and consistency, I've also removed the ability to determine if *any* attestation was included from metrics and API endpoints. Now, all Altair and non-Altair states will simply report on the head/target attestations. The following section details where we've removed fields and provides replacement values. ### Breaking Changes: Prometheus Metrics Some participation metrics have been removed and replaced. Some were removed since they are no longer relevant to Altair (e.g., total attesting balance) and others replaced with gwei values instead of pre-computed values. This provides more flexibility at display-time (e.g., Grafana). The following metrics were added as replacements: - `beacon_participation_prev_epoch_head_attesting_gwei_total` - `beacon_participation_prev_epoch_target_attesting_gwei_total` - `beacon_participation_prev_epoch_source_attesting_gwei_total` - `beacon_participation_prev_epoch_active_gwei_total` The following metrics were removed: - `beacon_participation_prev_epoch_attester` - instead use `beacon_participation_prev_epoch_source_attesting_gwei_total / beacon_participation_prev_epoch_active_gwei_total`. - `beacon_participation_prev_epoch_target_attester` - instead use `beacon_participation_prev_epoch_target_attesting_gwei_total / beacon_participation_prev_epoch_active_gwei_total`. - `beacon_participation_prev_epoch_head_attester` - instead use `beacon_participation_prev_epoch_head_attesting_gwei_total / beacon_participation_prev_epoch_active_gwei_total`. The `beacon_participation_prev_epoch_attester` endpoint has been removed. Users should instead use the pre-existing `beacon_participation_prev_epoch_target_attester`. ### Breaking Changes: HTTP API The `/lighthouse/validator_inclusion/{epoch}/{validator_id}` endpoint loses the following fields: - `current_epoch_attesting_gwei` (use `current_epoch_target_attesting_gwei` instead) - `previous_epoch_attesting_gwei` (use `previous_epoch_target_attesting_gwei` instead) The `/lighthouse/validator_inclusion/{epoch}/{validator_id}` endpoint lose the following fields: - `is_current_epoch_attester` (use `is_current_epoch_target_attester` instead) - `is_previous_epoch_attester` (use `is_previous_epoch_target_attester` instead) - `is_active_in_current_epoch` becomes `is_active_unslashed_in_current_epoch`. - `is_active_in_previous_epoch` becomes `is_active_unslashed_in_previous_epoch`. ## Additional Info NA ## TODO - [x] Deal with total balances - [x] Update validator_inclusion API - [ ] Ensure `beacon_participation_prev_epoch_target_attester` and `beacon_participation_prev_epoch_head_attester` work before Altair Co-authored-by: realbigsean <[email protected]>
1 parent f5bdca0 commit 6e3ca48

26 files changed

+1069
-370
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ cargo-fmt:
9595
check-benches:
9696
cargo check --workspace --benches
9797

98-
# Typechecks consensus code *without* allowing deprecated legacy arithmetic
98+
# Typechecks consensus code *without* allowing deprecated legacy arithmetic or metrics.
9999
check-consensus:
100100
cargo check --manifest-path=consensus/state_processing/Cargo.toml --no-default-features
101101

beacon_node/beacon_chain/src/block_verification.rs

Lines changed: 20 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,11 @@ use slot_clock::SlotClock;
5858
use ssz::Encode;
5959
use state_processing::{
6060
block_signature_verifier::{BlockSignatureVerifier, Error as BlockSignatureVerifierError},
61-
per_block_processing,
62-
per_epoch_processing::EpochProcessingSummary,
63-
per_slot_processing,
61+
per_block_processing, per_slot_processing,
6462
state_advance::partial_state_advance,
6563
BlockProcessingError, BlockSignatureStrategy, SlotProcessingError,
6664
};
6765
use std::borrow::Cow;
68-
use std::convert::TryFrom;
6966
use std::fs;
7067
use std::io::Write;
7168
use store::{Error as DBError, HotColdDB, HotStateSummary, KeyValueStore, StoreOp};
@@ -971,12 +968,19 @@ impl<'a, T: BeaconChainTypes> FullyVerifiedBlock<'a, T> {
971968
};
972969

973970
if let Some(summary) = per_slot_processing(&mut state, Some(state_root), &chain.spec)? {
974-
summaries.push(summary)
971+
// Expose Prometheus metrics.
972+
if let Err(e) = summary.observe_metrics() {
973+
error!(
974+
chain.log,
975+
"Failed to observe epoch summary metrics";
976+
"src" => "block_verification",
977+
"error" => ?e
978+
);
979+
}
980+
summaries.push(summary);
975981
}
976982
}
977983

978-
expose_participation_metrics(&summaries);
979-
980984
// If the block is sufficiently recent, notify the validator monitor.
981985
if let Some(slot) = chain.slot_clock.now() {
982986
let epoch = slot.epoch(T::EthSpec::slots_per_epoch());
@@ -990,7 +994,15 @@ impl<'a, T: BeaconChainTypes> FullyVerifiedBlock<'a, T> {
990994
// performing `per_slot_processing`.
991995
for (i, summary) in summaries.iter().enumerate() {
992996
let epoch = state.current_epoch() - Epoch::from(summaries.len() - i);
993-
validator_monitor.process_validator_statuses(epoch, &summary.statuses);
997+
if let Err(e) =
998+
validator_monitor.process_validator_statuses(epoch, &summary, &chain.spec)
999+
{
1000+
error!(
1001+
chain.log,
1002+
"Failed to process validator statuses";
1003+
"error" => ?e
1004+
);
1005+
}
9941006
}
9951007
}
9961008
}
@@ -1432,45 +1444,6 @@ fn verify_header_signature<T: BeaconChainTypes>(
14321444
}
14331445
}
14341446

1435-
fn expose_participation_metrics(summaries: &[EpochProcessingSummary]) {
1436-
if !cfg!(feature = "participation_metrics") {
1437-
return;
1438-
}
1439-
1440-
for summary in summaries {
1441-
let b = &summary.total_balances;
1442-
1443-
metrics::maybe_set_float_gauge(
1444-
&metrics::PARTICIPATION_PREV_EPOCH_ATTESTER,
1445-
participation_ratio(b.previous_epoch_attesters(), b.previous_epoch()),
1446-
);
1447-
1448-
metrics::maybe_set_float_gauge(
1449-
&metrics::PARTICIPATION_PREV_EPOCH_TARGET_ATTESTER,
1450-
participation_ratio(b.previous_epoch_target_attesters(), b.previous_epoch()),
1451-
);
1452-
1453-
metrics::maybe_set_float_gauge(
1454-
&metrics::PARTICIPATION_PREV_EPOCH_HEAD_ATTESTER,
1455-
participation_ratio(b.previous_epoch_head_attesters(), b.previous_epoch()),
1456-
);
1457-
}
1458-
}
1459-
1460-
fn participation_ratio(section: u64, total: u64) -> Option<f64> {
1461-
// Reduce the precision to help ensure we fit inside a u32.
1462-
const PRECISION: u64 = 100_000_000;
1463-
1464-
let section: f64 = u32::try_from(section / PRECISION).ok()?.into();
1465-
let total: f64 = u32::try_from(total / PRECISION).ok()?.into();
1466-
1467-
if total > 0_f64 {
1468-
Some(section / total)
1469-
} else {
1470-
None
1471-
}
1472-
}
1473-
14741447
fn write_state<T: EthSpec>(prefix: &str, state: &BeaconState<T>, log: &Logger) {
14751448
if WRITE_BLOCK_PROCESSING_SSZ {
14761449
let root = state.tree_hash_root();

beacon_node/beacon_chain/src/metrics.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -330,21 +330,6 @@ lazy_static! {
330330
pub static ref OP_POOL_NUM_SYNC_CONTRIBUTIONS: Result<IntGauge> =
331331
try_create_int_gauge("beacon_op_pool_sync_contributions_total", "Count of sync contributions in the op pool");
332332

333-
/*
334-
* Participation Metrics
335-
*/
336-
pub static ref PARTICIPATION_PREV_EPOCH_ATTESTER: Result<Gauge> = try_create_float_gauge(
337-
"beacon_participation_prev_epoch_attester",
338-
"Ratio of attesting balances to total balances"
339-
);
340-
pub static ref PARTICIPATION_PREV_EPOCH_TARGET_ATTESTER: Result<Gauge> = try_create_float_gauge(
341-
"beacon_participation_prev_epoch_target_attester",
342-
"Ratio of target-attesting balances to total balances"
343-
);
344-
pub static ref PARTICIPATION_PREV_EPOCH_HEAD_ATTESTER: Result<Gauge> = try_create_float_gauge(
345-
"beacon_participation_prev_epoch_head_attester",
346-
"Ratio of head-attesting balances to total balances"
347-
);
348333

349334
/*
350335
* Attestation Observation Metrics

beacon_node/beacon_chain/src/state_advance_timer.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,32 @@ fn advance_head<T: BeaconChainTypes>(
233233
if let Some(summary) = per_slot_processing(&mut state, state_root, &beacon_chain.spec)
234234
.map_err(BeaconChainError::from)?
235235
{
236+
// Expose Prometheus metrics.
237+
if let Err(e) = summary.observe_metrics() {
238+
error!(
239+
log,
240+
"Failed to observe epoch summary metrics";
241+
"src" => "state_advance_timer",
242+
"error" => ?e
243+
);
244+
}
245+
236246
// Only notify the validator monitor for recent blocks.
237247
if state.current_epoch() + VALIDATOR_MONITOR_HISTORIC_EPOCHS as u64
238248
>= current_slot.epoch(T::EthSpec::slots_per_epoch())
239249
{
240250
// Potentially create logs/metrics for locally monitored validators.
241-
beacon_chain
251+
if let Err(e) = beacon_chain
242252
.validator_monitor
243253
.read()
244-
.process_validator_statuses(state.current_epoch(), &summary.statuses);
254+
.process_validator_statuses(state.current_epoch(), &summary, &beacon_chain.spec)
255+
{
256+
error!(
257+
log,
258+
"Unable to process validator statuses";
259+
"error" => ?e
260+
);
261+
}
245262
}
246263
}
247264

0 commit comments

Comments
 (0)