- Pre-BAL path keeps StateDB synchronous read-time accumulators
(AccountReads, StorageReads, CodeReads, CodeLoaded, CodeLoadBytes)
so Execution = ptime - reads stays well-formed under single-thread
execution.
- BAL path drops aggregate reader read-times; under parallel workers
they sum across goroutines and aren't a wall-clock proxy.
- Delete dead PrefetchReadTimes/WaitPrefetch forwarders on *reader and
the now-unused ReadTimer/ReadDurations scaffolding.
- Add regression test for EIP-7702 delegation clear: empty []byte code
in the BAL must reset CodeHash to EmptyCodeHash.
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>
Wire up slotnum for `testing_buildBlockV1` for `bal-devnet-3` branch
We are experimenting testing block building through hive via EELS (PR
[here](https://github.com/ethereum/execution-specs/pull/2679)). This is
the only change needed to test against `bal-devnet-3` - missing slotnum.
The BAL reader tracker captures access list reads at the reader level.
When statedb has an account cached the BAL tracker is not informed of
the access. This is ok during the lifetime of a transaction because you
only need to record the access the first time. It is also ok during the
lifetime of a block because BAL reads are block-level (same as statedb
caches).
Where I think the issue can rise is in the miner. Namely when building a
block, if the miner picks up a tx which fails, it drops it and picks up
another tx to include. There might be some edge case here where the
failed tx which is not included poisons the cache and a future block
which is included omits an account because it wasn't aware of the
access.
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>
## Summary
- The BAL refactoring in 5808d212b removed the line `env.header.GasUsed
= env.gasPool.Used()` from `applyTransaction()`, causing all
geth-proposed blocks to have `GasUsed=0` in the header
- Every other client rejects these blocks during validation, so geth can
never successfully propose on the network
- Restores the single line that was present in upstream master
## Test plan
- [x] Verified line exists in upstream/master at miner/worker.go:409
- [x] Confirmed all 34 geth-proposed blocks on a 4-client devnet had
`GasUsed=0` via `debug_getBadBlocks` on besu
- [ ] Build local image and verify geth proposals are accepted in a
multi-client Kurtosis network
* add method on StateReaderTracker to clear the accumulated reads
* don't factor the BAL size into the payload size during construction in the miner
* simplify miner code for constructing payloads-with-BALs via the use of aformentioned StateReaderTracker clear method
* clean up the configuration of the BAL execution mode based on the preset flag specified
Adds support for returning `blockAccessListHash` in the RPC block header
response.
This change includes `blockAccessListHash` in `RPCMarshalHeader` when
`head.BlockAccessListHash` is not nil, aligning the RPC output with the
Header struct which already contains this field.
CopyHeader copies all pointer-typed header fields (WithdrawalsHash,
RequestsHash, SlotNumber, etc.) but was missing the deep copy for
BlockAccessListHash added by EIP-7928. This caused the BAL hash
to be silently shared between the original and the copy, leading
to potential data races and incorrect nil-checks on copied headers.
This is a breaking change in the opcode (structLog) tracer. Several fields
will have a slight formatting difference to conform to the newly established
spec at: https://github.com/ethereum/execution-apis/pull/762. The differences
include:
- `memory`: words will have the 0x prefix. Also last word of memory will be padded to 32-bytes.
- `storage`: keys and values will have the 0x prefix.
---------
Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>
Add persistent storage for Block Access Lists (BALs) in `core/rawdb/`.
This provides read/write/delete accessors for BALs in the active
key-value store.
---------
Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
In this PR, we add support for protocol version eth/70, defined by EIP-7975.
Overall changes:
- Each response is buffered in the peer’s receipt buffer when the
`lastBlockIncomplete` field is true.
- Continued request uses the same request id of its original
request(`RequestPartialReceipts`).
- Partial responses are verified in `validateLastBlockReceipt`.
- Even if all receipts for partial blocks of the request are collected,
those partial results are not sinked to the downloader, to avoid
complexity. This assumes that partial response and buffering occur only
in exceptional cases.
---------
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
Co-authored-by: Felix Lange <fjl@twurst.com>