Skip to content

docs: QBFT decision timing analytics for proposer and committee duties - #2883

Open
iurii-ssv wants to merge 13 commits into
stagefrom
docs/proposer-qbft-timing-analysis
Open

docs: QBFT decision timing analytics for proposer and committee duties#2883
iurii-ssv wants to merge 13 commits into
stagefrom
docs/proposer-qbft-timing-analysis

Conversation

@iurii-ssv

@iurii-ssv iurii-ssv commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Adds two analytics documents under docs/analytics/ quantifying how QBFT decision timing relates to on-chain outcomes on Ethereum mainnet, based on 35 days of network-wide data (2026-05-07 → 2026-06-10). Docs-only change, no code.

docs/analytics/proposer/ — block proposals

44,838 proposer duties, 99.93% exporter-trace coverage, every miss verified against the canonical chain.

  • Round 2 is rare (0.29%), but round-2 decisions miss 11.4% of blocks vs 0.049% for round-1 (~230×).
  • The driver is wall-clock decision time vs the 4s attestation deadline: ~0.05% missed when QBFT decides by 3s, 30% at 3.5–4.0s, 100% (8/8) past 4.0s. A round-2 decision completing by ~3.5s still lands 98% of the time.
  • On-time round-1 misses are a separate failure class (relay/submission/orphaning, not consensus timing).
  • Cross-references docs/MEV_CONSIDERATIONS.md (ProposerDelay headroom: p50 decision 1.40s, p99 2.25s) and #2429.

docs/analytics/attester/ — committee duties (attestations)

Stratified sample of 36 epochs (216,243 committee duties, 3.89M validator-attestations) + complete cluster-failure forensics over the full window (7,732 events). The conclusion is the opposite of the proposer story:

  • Attestation inclusion is insensitive to decision time: 0 missed attestations across the 2,826 round-2-decided duties (19,463 attestations), 0 across round-3+, 0 in duties decided 7–8.5s into the slot.
  • 86% of missed attestations come from duties whose QBFT never decided; full-window forensics: 82% never decided, 13% decided on time and failed at submission, only 15 of 7,611 events decided ≥7s. Five chronic clusters account for 82% of all cluster-failure events — reliability is an operator-health problem, not a timing problem.
  • Lateness costs quality, not inclusion: first-possible-block inclusion drops 99% → 57% across 7–8s, and the 4s no-block fallback path costs head-vote correctness (~96.4%), which round-2 retries heal (99.6%+) — round changes improve head votes.
  • Miss data guarded against the monitor's known whole-committee false-negative mode via a full-window block-gap scan (exactly one gap slot found in 35 days, the previously documented incident; affected events excluded).

Contents

  • docs/analytics/proposer/README.md + miss-rate-vs-decision-time chart
  • docs/analytics/attester/README.md + four charts: miss sources, quality vs decision time, and round-1-only / round-2-only conditioned variants
  • A note in the attester doc explaining why round changes are ~7x more common for committee duties than proposals (instance-relative vs slot-aligned timers, slot-correlated late-block bursts, per-slot vs per-validator weighting)
  • Step-by-step methodology in both Reproduction sections: pipeline scripts, endpoints and server caps, sampling design (stratified one-epoch-per-day, fixed seed), metric definitions, and re-run constraints
  • The two docs cross-link each other

Data sources for both: e2m duty monitor (duty enumeration/outcomes), exporter duty traces (QBFT rounds and message timing, network-wide P2P observation), public beacon API (canonical-chain verification).

iurii-ssv and others added 2 commits May 28, 2026 13:40
35 days of mainnet data (44,838 proposer duties, network-wide):
round 2 is rare (0.29%) but round-2 decisions miss 11.4% vs 0.049%
for round-1; the driver is wall-clock decision time vs the 4s
attestation deadline - miss rate is ~0.05% when QBFT decides by 3s,
30% at 3.5-4s, and 100% past 4s. Includes the miss-rate vs
decision-time chart and implications for ProposerDelay tuning.
@iurii-ssv
iurii-ssv requested review from a team as code owners June 11, 2026 10:06
@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.90252% with 421 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.3%. Comparing base (34657cf) to head (7e17f78).
⚠️ Report is 135 commits behind head on stage.

Files with missing lines Patch % Lines
network/p2p/p2p.go 48.4% 62 Missing and 6 partials ⚠️
ibft/storage/testutils.go 0.0% 63 Missing ⚠️
network/p2p/p2p_discovery.go 15.6% 42 Missing and 1 partial ⚠️
ekmadapter/database.go 0.0% 41 Missing ⚠️
network/discovery/dv5_service.go 49.3% 36 Missing and 4 partials ⚠️
network/p2p/p2p_setup.go 57.5% 13 Missing and 1 partial ⚠️
beacon/goclient/proposer.go 43.4% 12 Missing and 1 partial ⚠️
identity/store.go 78.4% 6 Missing and 5 partials ⚠️
api/pagination.go 84.3% 7 Missing and 3 partials ⚠️
eth/executionclient/bloom.go 83.8% 8 Missing and 2 partials ⚠️
... and 33 more

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This is a docs-only addition of an analytics write-up measuring the relationship between proposer-duty QBFT decision timing and block acceptance on Ethereum mainnet, based on 35 days of network-wide data (44,838 duties). No code is changed.

  • Core finding documented: The 4-second attestation deadline is the dominant miss predictor — miss rate jumps from ~0.05% at ≤3s to 30% at 3.5–4s to 100% past 4s; round-2 decisions that complete by ~3.5s still land 98% of the time.
  • ProposerDelay guidance: With p50 ≈ 1.4s and p99 ≈ 2.25s, the analysis reinforces that ~1.2s is the practical ceiling for ProposerDelay on mainnet, and cross-references docs/MEV_CONSIDERATIONS.md and issue #2429 for context on why round numbers don't map to fixed wall-clock times.

Confidence Score: 5/5

Docs-only change adding an analytics write-up; no code, config, or schema is touched, so there is no runtime risk.

All headline numbers are internally consistent (round counts, miss totals, derived percentages, and confidence intervals cross-check correctly), the chart is referenced correctly, and the relative-path link to docs/MEV_CONSIDERATIONS.md resolves. The only open question is a minor clarity gap around the 129-vs-115 "had round 2" distinction, which doesn't affect correctness.

No files require special attention — both changed files are documentation assets.

Important Files Changed

Filename Overview
docs/analytics/proposer/README.md New analytics write-up; numbers are internally consistent and cross-references resolve correctly; minor clarification opportunity around the 129-vs-115 "had round 2" distinction
docs/analytics/proposer/miss-rate-vs-decision-time.png Binary image asset for the miss-rate chart referenced in README.md; no issues

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Slot starts] --> B[RANDAO pre-consensus\n+ payload fetch\n~1.2s median]
    B --> C[QBFT instance starts]
    C --> D{Round 1 decision\nwithin 2s of start?}
    D -- Yes: ~99.75% of duties --> E{Decision time\nvs 4s deadline}
    D -- No: ~0.25% of duties --> F[Round 2 begins]
    F --> G{Decision time\nvs 4s deadline}
    E --> H["≤ 3.0s: ~0.05% miss"]
    E --> I["3.0–3.5s: ~1.9% miss"]
    E --> J["3.5–4.0s: ~30% miss"]
    E --> K["≥ 4.0s: 100% miss (8/8)"]
    G --> L["< 3.0s: 0% miss (7/7)"]
    G --> M["3.0–3.5s: 2.25% miss (2/89)"]
    G --> N["3.5–4.0s: 30% miss (3/10)"]
    G --> O["≥ 4.0s: 100% miss (8/8)"]
    H & I --> P[Block accepted]
    L & M --> P
    J & N --> Q[Block likely missed]
    K & O --> R[Block guaranteed missed\nAttesters already voted for parent]
Loading

Reviews (1): Last reviewed commit: "docs: add proposer QBFT decision timing ..." | Re-trigger Greptile

Comment thread docs/analytics/proposer/README.md
Companion to the proposer analysis with the opposite conclusion:
attestation inclusion is insensitive to QBFT decision time (0 misses
in 19,463 round-2 decisions; duties decided 7-8.5s all landed).
86% of missed attestations come from duties that never decided;
five chronic clusters account for 82% of cluster-failure events.
Lateness costs quality only: first-block inclusion drops past 7s and
the 4s no-block fallback costs head correctness, which round-2
retries heal. Cross-linked from the proposer doc.
@iurii-ssv iurii-ssv changed the title docs: proposer QBFT decision timing vs block acceptance analysis docs: QBFT decision timing analytics for proposer and committee duties Jun 11, 2026
0.25s buckets from 4s onward (the 6.5-7.5s transition was previously
hidden in 0.5s bins), Wilson 95% CI error bars on both lines, and an
in-figure definition of n (included attestations per bucket). Deadline
labels moved to the top to avoid colliding with sample-size labels.
Adjusts the one README sentence that cited the coarser buckets.
Round-1-only and round-2-only variants of the quality-vs-decision-time
chart, separating the two effects: the 4-5s head-vote dip belongs
entirely to round-1 fallback decisions, while round-2 decisions have
near-perfect head votes and only pay first-block inclusion when
deciding past ~7.2s.
The row reads as a subset of 'Decided round 3+' when it actually spans
all three decided rows; relabel it and spell out the 15/1,140 point.
Adds the round-1/2/3+ split of decided duties (98.67% / 1.31% / 0.013%)
so the chart's right side reads with the correct weight, and fixes
duty-vs-attestation units in the adjacent figures: 19,463 and 128 are
attestation counts; the duty counts are 2,826 (round 2) and 28 (round 3+).
The table flips from committee-duty counts (rows 1-2) to
validator-attestation counts (miss-rate rows) without saying so, and
row 1 uses traced duties while row 2 uses decided duties as the
denominator. Spell out the unit in every row and add a one-line note.
1.95% vs 0.29% touched-round-2 decomposes into: instance-relative vs
slot-aligned round timers (72% of touched committee duties had no
round-1 proposal - the leader was still waiting for the block),
slot-correlated late-block bursts (half of touches co-occur >=5 per
slot), and per-slot vs per-validator weighting of unhealthy clusters.
Both analytics docs now spell out the pipeline steps with the internal
script names, endpoints, batching and server caps, sampling design
(stratified one-epoch-per-day, fixed seed), key metric definitions,
verification mechanics, and the constraints to respect when re-running
(trace retention, settled-window margin, arrival-time semantics).
…units

Addresses the Greptile comment: the 129-vs-115 gap in the proposer
headline table is now explicit (14 duties had only round-change
messages observed). Aligns 'touched round >=2' terminology across both
docs, fixes the attester >=8s caveat to its real units (28 duties /
128 attestations), and removes detail duplicated between the Method
and Reproduction sections in both docs.
Comment thread docs/analytics/attester/README.md Outdated

- The ≥8s region is thin in the sample (28 duties / 128 attestations); conclusions there lean on the full-window forensics, which point the same way.
- Zero observed misses in round 2/3+ bounds the rate by sample size, not to literal zero.
- Scattered misses of 1–4 validators within decided duties exist (they are the 0.0011%) and are not part of the ≥5-validator forensics set.

@momosh-ssv momosh-ssv Jun 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth reconciling this with the TL;DR — 41 misses from just four duties averages ~10 per duty, so at least one of those duties must have had ≥5 validators missing together.

Seems that contradicts both the "1–4 validators" bound and these being outside the ≥5-validator forensics set; maybe the bound or the duty count needs adjusting.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reconciled: four duties is the correct figure, so the caveat was the loose part. Dropped the "1–4 validators" bound and the "not part of the forensics set" claim; it now notes that those four duties (the ones with ≥5 validators missing together) do appear in the full-window forensics under "decided round 1 (on time), failed downstream" — i.e. the sample misses and the forensics set overlap rather than partition.

Comment thread docs/analytics/attester/README.md Outdated
For block proposals, decision time is destiny (100% missed past 4.0s into the slot). For committee duties, decision time is **almost irrelevant to inclusion**:

- **0 of the 19,463 attestations from the 2,826 round-2-decided duties were missed** (CI95 ≤ 0.02%); likewise 0 of 128 from round-3+ decisions, and 0 of 355 from the 61 duties decided 7–8.5s into the slot. Round-1 decisions miss 0.0011%. Even the handful of duties decided past 10s were included, ~13 slots late.
- Of the 1,500 missed validator-attestations in the sample, 97% came from duties that never produced a decision: 86% where consensus messages were observed but a decide quorum never formed, and 12% where the exporter saw no consensus activity for the duty at all. The remaining 3% (41 misses, from just four duties) completed consensus early — between 2.3s and 5.1s — and failed after it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth considering rounding these consistently — 86% and 12% read as the decomposition of the 97% but sum to 98. The underlying fractions (85.5% + 11.7% = 97.3%) each round up; maybe 86% + 11%, or one decimal place, would avoid the double-take.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with 86% + 11% so the split sums to the 97% (and 86 + 11 + 3 = 100). The 11% is 176/1500 = 11.7% nudged down so the arithmetic reads clean — happy to switch to one decimal place instead if you'd rather not round that way.

Comment thread docs/analytics/attester/README.md Outdated

### Caveats

- The ≥8s region is thin in the sample (28 duties / 128 attestations); conclusions there lean on the full-window forensics, which point the same way.

@momosh-ssv momosh-ssv Jun 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about phrasing this as the round-3+ region instead?

The numbers match the round-3+ row exactly, but the TL;DR mentions round-2 duties decided up to 8.5s, so the ≥8s region presumably isn't only round-3+.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point: 28 duties / 128 attestations is the round-3+ count exactly, and the ≥8s time region also picks up late round-2 duties, so that label was wrong for these numbers. Relabeled the caveat to Round-3+.

@iurii-ssv
iurii-ssv changed the base branch from main to stage June 14, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants