erigontech / erigontech/erigon

execution: FCU can publish uncommitted state changes to RPC caches

Open
#23,240 1 comment 0 reactions 1 assignee Claimed by @yperbasis View on GitHub
RPC
Dominant language
Go
Stars
3.6k
Forks
1.5k
Avg merge
1d 16h
Merged PRs (30d)
455

Description

## Problem

The Engine API forkchoice path [dispatches accumulated state changes from the overlay](https://github.com/erigontech/erigon/blob/5edc6c19f383d705b9827ed17d55c0316c224634/execution/execmodule/forkchoice.go#L690-L697) before it [commits the corresponding database transaction](https://github.com/erigontech/erigon/blob/5edc6c19f383d705b9827ed17d55c0316c224634/execution/execmodule/forkchoice.go#L712-L717).

`Dispatcher.Dispatch` sends the batch immediately and resets the accumulator. Remote consumers such as `kvcache.Coherent` then advance or mutate the cache root identified by `StateVersionId`.

If the database commit subsequently fails, the durable database remains at its previous state while RPC caches have already accepted changes from the aborted FCU. On current main, the version is read from the pre-commit overlay, whose sequence view may still identify the current root. More generally, an identity chosen before commit cannot prove that the represented state became durable and may be reused by a retry. Values from the failed attempt can therefore remain reachable through the RPC cache.

This is present on main and should be fixed independently of #23005.

## Required behavior

- Do not send externally visible state-change notifications until the corresponding database commit succeeds.
- Derive `StateVersionId` from committed database state.
- On commit failure, send no batch and discard the aborted pending changes so they cannot leak into a later successful notification.
- If the overlay remains published temporarily for embedded readers during commit, keep that mechanism separate from the durable state-change stream and clear it on failure.

## Regression test

Inject a commit failure after an FCU has accumulated state changes, then verify:

1. The state-change consumer receives no batch from the failed attempt.
2. Failed-only changes are absent from the next successful notification.
3. A successful retry emits exactly one batch whose `StateVersionId` equals the committed database version, and the coherent RPC cache contains no failed-only value.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.