Skip to content

Add safe block visualization from fast_confirmation event stream#792

Open
barnabasbusa wants to merge 10 commits into
masterfrom
bbusa/fcr
Open

Add safe block visualization from fast_confirmation event stream#792
barnabasbusa wants to merge 10 commits into
masterfrom
bbusa/fcr

Conversation

@barnabasbusa

@barnabasbusa barnabasbusa commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Screenshot 2026-07-07 at 14 42 13 image

Config to test with:

participants_matrix:
  el:
    - el_type: geth

  cl:
    - cl_type: lodestar
      cl_extra_params:
        - --chain.fastConfirmation=true
    - cl_type: nimbus
    - cl_type: grandine
      cl_image: ethpandaops/grandine:bomanaps-feature-fcr-minimal
      cl_extra_params:
        - --fast-confirmation-rule
    - cl_type: prysm
  count: 2
global_log_level: debug
network_params:
  preset: minimal

additional_services:
  - dora

Adds support for the fast_confirmation beacon event stream topic (fast confirmation rule, see ethereum/beacon-APIs#616) and visualizes the resulting safe block in the UI.

Backend

  • Subscribes to the fast_confirmation topic as an optional ancillary SSE stream per beacon node. Nodes that don't support the topic reject the subscription with a 4xx response, in which case the stream silently gives up — so the feature auto-activates only on FCR-enabled nodes, with no config needed.
  • Parses the event payload (block, slot, and the optional current_slot added by beacon-APIs#616) with a local type, since the pinned go-eth2-client doesn't carry current_slot yet.
  • Tracks the most recent fast confirmed (safe) block per client (Client.GetLastFastConfirmation()) and network-wide in the chain state (ChainState.GetFastConfirmedBlock(), monotonic by slot), plus a per-client SubscribeFastConfirmationEvent() dispatcher for future consumers.

Frontend

  • Index page: the network overview shows the safe slot next to the current slot (with a shield indicator), and canonical slots at/below the safe slot get a shield marker in the recent slots list. Both update live via the existing /index/data polling.
  • Consensus clients page: new sortable "Safe Slot" column showing each node's last fast confirmed block (linked to the slot page). The column only appears when at least one node reports fast confirmations; nodes without FCR show a dash.
  • API: /v1/clients/consensus now includes fcr_enabled, safe_slot and safe_root per client, and a new dedicated /api/v1/network/fast_confirmation endpoint returns the network-wide safe block (slot, root, epoch, last confirmation time) plus per-client fast confirmation status.

The UI additions are hidden entirely on networks where no node emits fast confirmation events.

Subscribe to the fast_confirmation beacon event stream topic (fast
confirmation rule, see ethereum/beacon-APIs#616) as an optional ancillary
SSE stream. Nodes that don't support the topic reject the subscription
with a 4xx response, in which case the stream silently gives up, so the
feature auto-activates only on FCR-enabled nodes.

The most recent fast confirmed (safe) block is tracked per client and
network-wide in the chain state, and visualized in the frontend:

- index page: safe slot next to the current slot in the network overview,
  and a shield marker on fast confirmed slots in the recent slots list
- consensus clients page: sortable "Safe Slot" column (only shown when at
  least one node reports fast confirmations)
- /v1/clients/consensus API: fcr_enabled, safe_slot and safe_root fields
@barnabasbusa barnabasbusa added the build-docker-image Automatically build docker image for PR branch label Jul 7, 2026
Dedicated API method returning the network-wide safe block (slot, root,
epoch, last confirmation time) plus the per-client fast confirmation
status.
Comment thread clients/consensus/clientlogic.go
Iteration 1 of the safe block visualization: the block dot in the chain
fork graph (index, slots and blocks pages) turns green for canonical
blocks at or below the network-wide safe slot.
Iteration 2 of the safe block visualization: fast confirmed blocks get a
shield icon next to the status pill on the slots and blocks pages,
matching the index page recent slots list.
Iteration 3 of the safe block visualization: canonical blocks at or below
the safe slot get a teal "Proposed" pill instead of the default green,
on the index, slots and blocks pages.
Settle on the shield icon in the status column as the single safe block
visualization: drop the green fork graph dot and the teal status pill
variants again, and add the shield to the filtered slots and filtered
(EL) blocks views.
@qu0b-reviewer

qu0b-reviewer Bot commented Jul 7, 2026

Copy link
Copy Markdown

🤖 qu0b-reviewer

Confirmed: for offset = 2^64-1, offset+32 wraps to 31, which fails the > len(data) guard, so execution proceeds to data[offset : offset+32] with the original huge offset → panic (slice bounds out of range). This is reachable from an untrusted RPC response and would crash the ENS worker (restarting every 10s in a panic loop).

Summary

The PR adds safe-block shield icons (driven by GetFastConfirmedBlock) plus a new ENS resolver service that swaps rendered addresses for primary ENS names. The safe-block logic and most of the ENS plumbing look correct. One robustness bug exists in the ABI string decoder: a crafted/erroneous eth_call return can panic the resolver worker.

Issues

  • 🟡 services/ensresolver_ens.go:316decodeENSString guards with offset+32 > uint64(len(data)) and offset+32+length > uint64(len(data)), but offset/length are uint64 taken from raw return bytes. A value near 2^64 makes offset+32 wrap (e.g. 2^64-1+32 == 31), bypassing the guard, then data[offset : offset+32] indexes out of range and panics. Since runUpdaterLoop runs this in the ENS worker (and re-enqueues on error but not on panic), a single bad/malicious RPC response puts the resolver into a 10s panic-restart loop. Compare against data length with overflow-safe checks, e.g. offset <= uint64(len(data))-32 && length <= uint64(len(data))-(offset+32), or reject offset/length exceeding len(data).

Suggestions

  • services/ensresolver_ens.go:316 — clamp/validate offset and length with big.Int.Cmp against the actual byte length before slicing to avoid the unsigned-overflow wrap.

Reviewed @ af9d539b
"If your only tool is a hammer, every problem looks like a microservice."

@barnabasbusa barnabasbusa enabled auto-merge July 7, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build-docker-image Automatically build docker image for PR branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants