You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
node/shards.Events.LatestSD is a process-global atomic.Pointer[execctx.SharedDomains], set by PublishOverlay at each FCU and read by many consumers (RPC cache via execmodule.Cache, txpool OnNewBlock, the block builder, etc.). It is the only way to refer to "the current state publication," and that single mutable global is a source of coupling that this issue proposes to remove.
The coupling effect
No identity. The global names only "latest." A consumer cannot reference a specific publication, wait for one, or check it is reading the same one another consumer used. Coordination between consumers therefore degrades to matching by block number (lastSeenBlock / ParentBlockNum in the txpool's best()), which is fork/reorg-ambiguous (same height, different SD).
Unsynchronized read-fills. Readers off the global run without the exec-module semaphore, so the cache read-fills they trigger (commitment BranchCache, account/storage StateCache) can land from positions not synchronized with the FCU flush/refresh cycle. This is the coherence hazard already tracked in execution/execmodule: audit published-SD readers (Events.LatestSD, bg-commit) for shared-cache coherence #22214 — a symptom of the global, not a separate problem.
No lifetime / refcount. Because the global hands out a bare pointer with no reference tracking, in-flight generations cannot be freed precisely: ExecModule.drainCommittedGens is intentionally a no-op (model A) and generations are only released as a unit at shutdown.
Motivating use case (observed)
Under fcuBackgroundCommit=true, TestAssembleBlockWithStateVerification intermittently built a block with 0 transactions. Root cause: when building block N+1, the txpool had correctly processed block N (lastSeenBlock=N, nonce-N+1 txns pending), but the block builder's state reader was not pinned to the same publication of block N — so it saw a pre-N sender nonce and filtered every valid txn as nonce-gapped. The pool and the builder agreed on the block by number, but nothing pinned them to the same publication. (Fixed as a stopgap on PR #21414 by pinning the builder to the newest generation's retained SD — the same SD the pool reads — but the publication is identified implicitly as "newest generation" rather than by an explicit id.)
Goal
Remove the mutable Events.LatestSD global. Consumers should reference a specific state publication by a stable identifier and coordinate on it, rather than racing to read "the latest global."
Subtask: introduce a (db.sd) publication id
A monotonic major.minor identifier for each published state:
major = DB state version — already exists (rawdb.GetStateVersion / IncrementStateVersion, bumped per durable commit).
minor = SD id — new; numbers the in-flight generations published between two DB commits (ExecModule.gens). 0 under foreground commit, so it degenerates to today's behaviour when bg-commit is off.
This id gives: (a) a fork-unambiguous handle so the txpool can tag the txns it yields with the publication they are valid at and the builder can wait for that id or build on the parent; (b) a replacement for "latest global" references; (c) the refcount key that lets drainCommittedGens free generations precisely.
Summary
node/shards.Events.LatestSDis a process-globalatomic.Pointer[execctx.SharedDomains], set byPublishOverlayat each FCU and read by many consumers (RPC cache viaexecmodule.Cache, txpoolOnNewBlock, the block builder, etc.). It is the only way to refer to "the current state publication," and that single mutable global is a source of coupling that this issue proposes to remove.The coupling effect
lastSeenBlock/ParentBlockNumin the txpool'sbest()), which is fork/reorg-ambiguous (same height, different SD).ExecModule.drainCommittedGensis intentionally a no-op (model A) and generations are only released as a unit at shutdown.Motivating use case (observed)
Under
fcuBackgroundCommit=true,TestAssembleBlockWithStateVerificationintermittently built a block with 0 transactions. Root cause: when building blockN+1, the txpool had correctly processed blockN(lastSeenBlock=N, nonce-N+1txnspending), but the block builder's state reader was not pinned to the same publication of blockN— so it saw a pre-Nsender nonce and filtered every valid txn as nonce-gapped. The pool and the builder agreed on the block by number, but nothing pinned them to the same publication. (Fixed as a stopgap on PR #21414 by pinning the builder to the newest generation's retained SD — the same SD the pool reads — but the publication is identified implicitly as "newest generation" rather than by an explicit id.)Goal
Remove the mutable
Events.LatestSDglobal. Consumers should reference a specific state publication by a stable identifier and coordinate on it, rather than racing to read "the latest global."Subtask: introduce a
(db.sd)publication idA monotonic major.minor identifier for each published state:
rawdb.GetStateVersion/IncrementStateVersion, bumped per durable commit).ExecModule.gens).0under foreground commit, so it degenerates to today's behaviour when bg-commit is off.This id gives: (a) a fork-unambiguous handle so the txpool can tag the txns it yields with the publication they are valid at and the builder can wait for that id or build on the parent; (b) a replacement for "latest global" references; (c) the refcount key that lets
drainCommittedGensfree generations precisely.Related