Add lean_block_proposal_* metrics for block-proposal attestation selection#414
Conversation
…ction
Port the five block-proposal observability metrics from leanSpec PR #753 into
the ethlambda block builder:
- lean_block_proposal_attestation_build_phase_seconds{phase} — phase-level
timing for select_payloads, compact, and stf_simulate
- lean_block_proposal_attestation_builds_total — completed selection runs
- lean_block_proposal_child_payloads_consumed_total — greedily-picked proofs
before compaction
- lean_block_proposal_attestation_data_selected — distinct AttestationData in
the block body
- lean_block_proposal_aggregates_selected — proofs after compaction
Instrument build_block to time the three phases and emit the counters and
histograms after a successful build. ethlambda projects justification and
finalization incrementally during selection and runs the STF once at the end,
rather than re-running it inside a fixed-point loop as leanSpec does, so
stf_simulate is a single observation per build; this divergence is documented
on the phase-label constant.
Add a unit test guarding against drift between the phase-label constant and the
strings passed at the build_block call sites, and document all five metrics in
docs/metrics.md.
🤖 Kimi Code ReviewThe PR adds comprehensive metrics instrumentation for block-proposal attestation selection. The implementation follows existing patterns in the codebase and is generally well-structured. Issues and suggestions:
Positive aspects:
Consensus safety note: Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code ReviewFindings
I did not see a consensus-path logic change here: fork choice, attestation validation, justification/finalization, STF, XMSS verification, and SSZ behavior are unaffected beyond telemetry. I could not run Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
🤖 Claude Code ReviewCode Review: PR #414 —
|
Greptile SummaryThis PR ports five
Confidence Score: 4/5Safe to merge — only metric observations were added around existing logic; block selection and the STF path are untouched. The instrumentation is purely additive and the production code path is correct. The only concern is the new unit test, whose exact-value counter assertions can produce non-deterministic failures because the existing build_block_* tests now also trigger these same global metric counters and run in parallel by default. crates/blockchain/src/metrics.rs — specifically the block_proposal_attestation_build_metrics_are_usable test assertions.
|
| Filename | Overview |
|---|---|
| crates/blockchain/src/block_builder.rs | Instruments build_block with three phase timers and four metric observations; no behavior change to block selection or STF logic. |
| crates/blockchain/src/metrics.rs | Registers five new metrics and exposes public API functions correctly; the new unit test has fragile exact-value assertions against global counters shared with parallel build_block_* tests. |
| docs/metrics.md | Adds five rows to the Block Production Metrics table; buckets and labels match the registered metric definitions. |
Sequence Diagram
sequenceDiagram
participant BB as build_block
participant SA as select_attestations
participant CA as compact_attestations
participant STF as process_slots/process_block
participant M as metrics
BB->>SA: select_attestations(head_state, ...)
SA-->>BB: selected (Vec of Attestation+Proof pairs)
BB->>M: observe_block_proposal_phase("select_payloads", elapsed)
BB->>CA: compact_attestations(selected, head_state)
CA-->>BB: compacted (one entry per AttestationData)
BB->>M: observe_block_proposal_phase("compact", elapsed)
BB->>STF: process_slots + process_block
STF-->>BB: post_state
BB->>M: observe_block_proposal_phase("stf_simulate", elapsed)
BB->>M: inc_block_proposal_attestation_builds()
BB->>M: inc_block_proposal_child_payloads_consumed(selected.len())
BB->>M: observe_block_proposal_attestation_data_selected(attestations.len())
BB->>M: observe_block_proposal_aggregates_selected(signatures.len())
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
crates/blockchain/src/metrics.rs:862-889
**Test assertions race against shared global counters**
The assertions on absolute counter values (`get() == 1`, `get() == 3`, `get_sample_count() == 1`) assume the global metric statics start at zero when this test runs. However, `build_block_caps_attestation_data_entries`, `build_block_absorbs_older_but_justified_source`, and `build_block_cascades_projected_justification_across_rounds` all call `build_block`, which now increments `LEAN_BLOCK_PROPOSAL_ATTESTATION_BUILDS_TOTAL`, `LEAN_BLOCK_PROPOSAL_CHILD_PAYLOADS_CONSUMED_TOTAL`, and adds phase-histogram observations. Because `cargo test --lib` runs tests in parallel by default, any of those three tests racing ahead will leave the counters above zero, causing the assertions here to fail non-deterministically. A safer approach is to read the current value before the observation and assert a delta of exactly one, or restrict the assertions to relative `>=` comparisons.
Reviews (1): Last reviewed commit: "Add lean_block_proposal_* metrics for bl..." | Re-trigger Greptile
…tation Address review feedback on PR #414: - Move the inc_block_proposal_attestation_builds() call into the select attestations fixed-point loop so it counts each attestation selected (one per round that picks an AttestationData), rather than once per build_block. Update the counter help text and docs/metrics.md accordingly. - Remove the metrics unit test: its absolute-value assertions on process-global Prometheus statics race against the parallel build_block_* tests that now touch the same counters. The build_block_* tests already exercise the metric call paths. - Drop the redundant child_payloads_consumed comment.
🗒️ Description / Motivation
Ports the five
lean_block_proposal_*observability metrics from leanSpec PR #753 into the ethlambda block builder.These metrics give cross-client visibility into the block-proposal attestation-selection path (
build_block): how long each phase takes, how many proposal builds run, how many child payloads are greedily consumed, and how many distinctAttestationData/ aggregated proofs end up in the proposed block. They align with zeam #914'sgetProposalAttestationsinstrumentation and the leanSpec naming so the leanMetrics dashboards work across clients.What Changed
crates/blockchain/src/metrics.rs— five new metrics registered with the existingLazyLock+register_*!pattern, aBLOCK_PROPOSAL_ATTESTATION_BUILD_PHASESlabel constant, registration ininit(), public API functions, and a unit test:lean_block_proposal_attestation_build_phase_secondsphase=select_payloads,compact,stf_simulate; buckets0.001…8lean_block_proposal_attestation_builds_totallean_block_proposal_child_payloads_consumed_totallean_block_proposal_attestation_data_selected0, 1, 2, 4, 8, 16, 32lean_block_proposal_aggregates_selected0, 1, 2, 4, 8, 16, 32, 64, 128crates/blockchain/src/block_builder.rs— instrumentsbuild_block: times theselect_attestations,compact_attestations, and STF (process_slots+process_block) phases, and emits the counters/histograms after a successful build.docs/metrics.md— documents all five in the Block Production Metrics table.Correctness / Behavior Guarantees
stf_simulateper round. ethlambda projects justification/finalization incrementally during selection and runs the STF exactly once at the end, so itsstf_simulateis a single observation per build. This is noted on theBLOCK_PROPOSAL_ATTESTATION_BUILD_PHASESdoc comment, consistent with the upstream PR's own caveat that phase timings are not directly comparable across clients.attestation_data_selectedandaggregates_selectedare observed from the post-compaction body (one merged proof per distinctAttestationData), matching the spec's intent.lean_block_building_failures_total.Tests Added / Run
metrics::tests::block_proposal_attestation_build_metrics_are_usable— verifies the phase metric registers and accepts every label inBLOCK_PROPOSAL_ATTESTATION_BUILD_PHASES, and that the companion counters/histograms are callable. Guards against drift between the label constant and the strings passed at thebuild_blockcall sites.block_buildertests (build_block_*,compact_attestations_*,extend_proofs_greedily_*) now exercise the new metric paths and pass unchanged.Commands run:
make fmt— cleancargo clippy -p ethlambda-blockchain --all-targets -- -D warnings— cleancargo test -p ethlambda-blockchain --lib— 23 passingRelated Issues / PRs
✅ Verification Checklist
make fmt— cleanmake lint(clippy with-D warnings) — cleancargo test --workspace --release— onlyethlambda-blockchainlib suite run (23 passing); full workspace release run not yet executed