Populates per-block state read/write counts in slow-block JSON for BAL
blocks (which #34892 left as TBD), and adds reader-level read timing.
Builds on top of bal-devnet-3 — most of the PR's earlier slow-block log
infrastructure was adapted into upstream by that commit, so this change
is now scoped to the metric population that the BAL alone can derive.
- BAL helpers: BlockAccessList.{UniqueAccountCount, UniqueStorageSlotCount,
WrittenCounts}. WrittenCounts walks the BAL once and returns the
block-aggregate write counts.
- Reader-level read timing: *reader times all synchronous Account/Storage/
Code/CodeSize calls via atomic counters; exposed via ReadTimes()
ReadDurations and the new state.ReadTimer interface. Replaces StateDB-
level AccountReads/StorageReads/CodeReads tracking (the StateDB shouldn't
time its dependencies — the reader is where the I/O happens).
- Reader-level code-load dedup: *reader.codeLoaded sync.Map records the
first-seen byte length per address; CodeLoads() returns (count, bytes).
Exposed via state.CodeLoadTracker. Replaces StateDB CodeLoaded/
CodeLoadBytes tracking and the SnapshotCodeLoads aggregation pattern.
- BALStateTransition: caches BlockAccessList.WrittenCounts() once at
construction; tracks accountDeleted/storageDeleted atomics for the
parallel root-pass (the BAL alone can't distinguish a selfdestruct from
a balance/nonce reset). Exposes Deletions() DeletionCounts. Drops the
older accountUpdated/storageUpdated/codeUpdated/codeUpdateBytes counters
(now derived from WrittenCounts).
- BAL block stats path (blockchain.go): populates StateCounts directly —
AccountUpdated = WrittenCounts.Accounts - Deletions.Accounts (same for
storage). AccountLoaded/StorageLoaded come from BAL. CodeLoaded/
CodeLoadBytes come from the shared *reader (deduplicated across phase
StateDBs naturally because they share one reader instance).
- Non-BAL block stats path: read durations come from the reader; counts
from StateDB fields. StorageUpdated/StorageDeleted unified to int width.
- Hard type assertions: state.ReadTimer / state.CodeLoadTracker /
state.ReaderStater consumers use direct casts (no silent zero
fallback) — every Reader chain in production satisfies these
interfaces.
- Meter alignment: account/storage Updated meters subtract Deletions to
avoid double-reporting blocks under both Update and Delete dashboards.
Adapts some of the changes from
https://github.com/ethereum/go-ethereum/pull/34861 . Some other metrics
which are recorded manually during execution in that PR, but can be
deduced from the BAL are TBD.
I've added two bal feature flags:
* `--bal.prefetchworkers <uint>`: this tunes the number of concurrent
go-routines that will be used to perform state fetching tasks by the BAL
prefetcher. Default is `runtime.NumCPUs`, the current behavior in
`bal-devnet-3`.
* `--bal.blockingprefetch`: If set, state prefetching will block the
execution of transactions and state root update.
---------
Co-authored-by: CPerezz <cperezz19@pm.me>
To check whether a transaction can be applied, we validate that
`blockGasLimit > txGasLimit + (cumulativeRegularGasUsed +
cumulativeStateGasUsed)`. However, the check should only be applied to
the bottleneck resource, i.e. `blockGasLimit >
max(txRegularGasUsed+cumulativeRegularGasUsed, txStateGasUsed+
cumulativeStateGasUsed)`.
The changes here break multiple tests. I am trying to determine why.
---------
Co-authored-by: qu0b <stefan@starflinger.eu>