Handle wrong fork/finalization on hello - #598
Conversation
| return true; | ||
| } | ||
| if (state.finalizedCheckpoint.epoch >= request.finalizedEpoch && | ||
| !request.finalizedRoot.equals(getBlockRoot(this.config, state, request.finalizedEpoch))) { |
There was a problem hiding this comment.
if I'm not mistaken getBlockRoot only contains root for recent slots. I think it's safer to fetch block from database by request.finalizedEpoch start slot.
You should try to avoid fetching entire state here as that call isn't cheap, especially considering that this method will be called on each peer connect.
There was a problem hiding this comment.
I replaced getBlockRoot by getting block root from database as you said.
Regarding the state, I still need it for other calculations.
| } | ||
| // TODO handle incorrect forkVersion or disjoint finalizedCheckpoint | ||
| if (await this.shouldDisconnectOnHello(peerInfo, request)) { | ||
| this.network.reqResp.goodbye(peerInfo, 0n); |
There was a problem hiding this comment.
I correct the one in stop() too
| this.network.reqResp.removeListener("request", this.onRequest); | ||
| await Promise.all( | ||
| this.network.getPeers().map((peerInfo) => | ||
| this.network.reqResp.goodbye(peerInfo, 0n))); |
There was a problem hiding this comment.
I would extract reason codes to enum
| return true; | ||
| } | ||
| const startSlot = computeStartSlotOfEpoch(this.config, request.finalizedEpoch); | ||
| const startBlock = await this.db.block.get(startSlot); |
There was a problem hiding this comment.
If that block is finalized it will be in this.db.blockArchive
073121b to
6270e00
Compare
- Wires the new `fast_confirmation` Server-Sent Event from beacon-APIs PR [#598](ethereum/beacon-APIs#598). The event fires once per slot whenever the Fast Confirmation Rule executes and carries `{block, slot}`, where `slot` is the slot of the confirmed beacon block. - Crosses the fork-choice ↔ beacon-node boundary via a new optional `onFastConfirmation` callback on `ForkChoiceStore`, mirroring the existing `onJustified` / `onFinalized` plumbing. The emit is invoked from `ForkChoice.runFastConfirmation()` after the rule succeeds. - Removes the now-redundant Lodestar-namespace endpoint `GET /eth/v1/lodestar/fast_confirmation_info` (and its `getConfirmedBlock` helper) — the standard SSE event supersedes it, and the head/checkpoint fields it bundled are already available via standard beacon-API endpoints. This PR is aligned with the changes proposed in ethereum/beacon-APIs#616 ### Architecture ``` Chain.onClockSlot → forkChoice.updateTime └── (per tick) runFastConfirmation └── fcStore.notifyFastConfirmation({block, slot}) └── ChainEventEmitter.emit(EventType.fastConfirmation, {block, slot}) └── SSE subscribers via /eth/v1/events?topics=fast_confirmation ``` `ApiEvents` in `ChainEventEmitter` is derived from `routes.events.EventType`, so adding the new variant flows through automatically — no per-event boilerplate in the chain or events API layers. ### Edge cases | Scenario | Behavior | |---|---| | `--chain.fastConfirmation` disabled (default) | No emit (FCR doesn't run) | | FCR rule throws | No emit; existing warn-and-continue catch is unchanged | | Confirmed root not in `protoArray` (defensive) | Warn log with `slot`+`confirmedRoot`, skip emit | | `updateTime` advances multiple slots | One emit per tick |
Goal