Commit graph

616 commits

Author SHA1 Message Date
Jared Wasinger
da9e5177f9 set prefetcher metrics upon completion 2026-05-06 15:03:49 -04:00
Jared Wasinger
b7118dccfe cleanup 2026-05-06 14:43:40 -04:00
Jared Wasinger
aa8745521f core/state: note that error case is unreachable 2026-05-06 14:28:25 -04:00
Jared Wasinger
ac8354d4ca add --bal.blockingprefetch: if enabled, will ensure that when executing with a BAL, state loading tasks are completed before tx and state root calculation. can be used with --bal.prefetchworkers 2026-05-06 13:48:19 -04:00
Jared Wasinger
5c101bba03 try fix 2026-05-06 12:51:10 -04:00
Jared Wasinger
90175152bb more changes (wip) 2026-05-06 12:00:33 -04:00
Jared Wasinger
b01202e3fe the start of some changes I was experimenting with. broken 2026-05-05 11:33:39 -04:00
Jared Wasinger
f5d50d065b fix for code mutation 2026-05-05 10:36:37 -04:00
CPerezz
51fdf0e053
core: drop and tighten comments per PR feedback 2026-05-04 18:42:03 +02:00
CPerezz
adb545b20c
core/state: colocate StateCounts/ReadDurations with StateDB
Moves the snapshot DTOs into statedb.go directly above SnapshotCounts
and SnapshotReads, so the types and their sole constructors live in the
same file. Avoids a single-purpose state_counts.go.
2026-05-01 15:31:22 +02:00
CPerezz
aa13b208b1
core: deduplicate CodeLoaded/CodeLoadBytes for BAL blocks
The previous follow-up note: per-tx + pre-tx + post-tx StateDBs each
have their own stateObjects, so summing CodeLoaded/CodeLoadBytes
over-counts contracts whose code body was fetched by multiple phases.

Fix: snapshot per-StateDB the {address: codeLen} map of contracts whose
s.code is populated, plumb through the existing aggregation pipeline,
dedupe by address in resultHandler/prepareExecResult. The merged map's
size and value-sum become CodeLoaded and CodeLoadBytes respectively,
overriding the per-tx-summed values at the wiring site.

Empirical: a 3-tx block touching the same set of system contracts now
reports code=4, code_bytes=1098 (matches single-tx baseline) instead
of code=12, code_bytes=3294 under the prior over-count.
2026-05-01 10:40:40 +02:00
CPerezz
8797d1af8e
core: tighten metric doc comments
- Replace reader.go:553 line citation in GetStateStats with the function
  name; line numbers rot.
- Note the BAL sum-of-CPU-time semantics on the read-time field group
  in ExecuteStats so cross-client consumers don't read total ≤ TotalTime
  as an invariant.
2026-05-01 00:38:31 +02:00
CPerezz
13733390da
core: extract state.ReadDurations triple
Replace the {Account, Storage, Code} time.Duration scalars threaded through
ProcessResultWithMetrics, txExecResult, processBlockPreTx and resultHandler
with a single ReadDurations struct + Add merge primitive. Same shape as
StateCounts. Adds (*StateDB).SnapshotReads() helper at the boundary.
2026-05-01 00:16:55 +02:00
CPerezz
546d2b457e
core: split BAL read-time access from cached metrics struct
Replace the cached AccountReadTime/StorageReadTime fields (which had a
snapshot-staleness bug fixed in 16e98f5d9 by re-calling Metrics()) with
a live ReadTimes() accessor. Metrics() now only returns commit/hash-phase
timings — it no longer touches atomics. blockchain.go reads atomics
directly via stateTransition.ReadTimes(), eliminating the refresh hack.

Also resolves the I1 fragility: Metrics() returning &s.metrics no longer
involves any writes inside the function, so concurrent callers can't race
on the read-time field updates.
2026-05-01 00:12:54 +02:00
CPerezz
eb4d17595f
core/state: change BAL plain-int counter fields from int64 to int 2026-04-30 23:59:14 +02:00
CPerezz
cd8ce62b40
core: wait for prefetcher before reading PrefetchReadTimes
Forward prefetchStateReader.Wait() through *reader.WaitPrefetch and call
it before reading the read-time atomics. Eliminates the edge-case where
prefetcher goroutines outlast block execution + commit. For slow blocks
(the metric's target audience) this is a no-op; for fast blocks it
ensures the metric is complete rather than slightly under.
2026-04-30 23:57:23 +02:00
CPerezz
1afcea992c
core/state: change StateCounts.Add to value receiver
The struct is 80 bytes (10 ints) — value semantics matches the type's
"snapshot, safe to pass by value" thesis stated in its doc comment, and
removes three unnecessary &-takings at call sites. No behavior change.
2026-04-30 14:03:23 +02:00
CPerezz
cdfad0d343
core/state: comment len(code) > 0 gate, drop dead OriginStorageLoadTime
- Add a comment at the code-mutation gate explaining the deliberate
  len(code) > 0 (vs code != nil) match against non-BAL semantics; in
  devnet-3 BAL access lists, an empty []byte is non-nil but encodes
  "no code install".
- Remove BALStateTransitionMetrics.OriginStorageLoadTime: declared but
  never assigned anywhere in the tree. The actual state-transition
  read time is captured by AccountReadTime/StorageReadTime added in
  the prior commit.
2026-04-30 14:03:23 +02:00
CPerezz
6b1ea9a498
core/state: forward prefetcher read times through the reader aggregator
Without this, the inline interface assertion in processBlockWithAccessList
silently fell through (the prefetchReader returned by ReaderEIP7928 is a
*reader wrapper, not the inner *prefetchStateReader), causing the
prefetcher contribution to state_read_ms to drop to zero in production.

Mirrors the existing GetStateStats forwarding pattern. Adds a regression
test that asserts *reader exposes PrefetchReadTimes via the BAL chain,
plus a fallback test for non-prefetch readers.
2026-04-30 14:03:23 +02:00
CPerezz
812fa198c3
core/state, core: introduce state.StateCounts snapshot type
Adds the StateCounts type that the BAL slow-block work depends on:
- core/state/state_counts.go: 10-field plain-int snapshot type with
  Add merge primitive; isolates the live atomic mutation surface from
  the value-typed aggregation pipeline.
- core/state/statedb.go: SnapshotCounts() method that converts the
  StateDB's atomic counters to a plain StateCounts at the boundary.
- core/blockchain_stats.go: ExecuteStats embeds state.StateCounts;
  adds ExecWall/PostProcess/Prefetch BAL extension fields, the
  slowBlockBAL JSON struct + BAL field on slowBlockLog, and extracts
  buildSlowBlockLog as a pure helper for direct testing.

Without this commit the bal-devnet-3 branch as committed in subsequent
commits would not build for a fresh clone (state.StateCounts undefined).
2026-04-30 14:03:23 +02:00
CPerezz
cd93a42b5b
core/state: instrument prefetcher read times 2026-04-30 14:03:23 +02:00
CPerezz
bcdc309f0b
core/state: instrument BAL state-transition read times 2026-04-30 14:03:22 +02:00
CPerezz
d419d91c44
core/state: surface BAL write counters via WriteCounts 2026-04-30 14:03:22 +02:00
CPerezz
78cb5b98df
core/state: increment write counters in BAL state transition 2026-04-30 14:03:22 +02:00
CPerezz
3dc4dcaff8
core/state: add code-write counter fields to BALStateTransition 2026-04-30 14:03:22 +02:00
CPerezz
f089266126
core/state: forward cache stats from prefetchStateReader 2026-04-30 14:03:22 +02:00
Sina M
407cf11930
core/state: touch BAL on statedb cache (#34684)
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.
2026-04-08 13:20:58 -04:00
Sina M
c3ad7547ce
core/state: various fixes in EIP-7928 (#34641)
Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-04-03 12:41:45 -04:00
Marius van der Wijden
18848bca26 all: fix rebasing issues 2026-03-31 17:56:41 -04:00
Jared Wasinger
c7ab99831a core: fix storage deletion 2026-03-31 17:53:30 -04:00
Jared Wasinger
71ad98ba90 cmd,core,eth,miner:
* 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
2026-03-31 17:53:28 -04:00
Jared Wasinger
787464adfc address more lint errors 2026-03-31 17:52:47 -04:00
Jared Wasinger
6d1df21ef9 fix some lint errors (TODO: merge this commit into the 7928 changes 2026-03-31 17:49:53 -04:00
Jared Wasinger
265d74b75e all: implement eip 7928 block access lists 2026-03-31 17:49:49 -04:00
CPerezz
3da517e239
core/state: fix storage counters in binary trie IntermediateRoot (#34110)
Add missing `StorageUpdated` and `StorageDeleted` counter increments
in the binary trie fast path of `IntermediateRoot()`.
2026-03-31 15:47:07 +02:00
rjl493456442
c3467dd8b5
core, miner, trie: relocate witness stats (#34106)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
This PR relocates the witness statistics into the witness itself, making
it more self-contained.
2026-03-27 17:06:46 +01:00
Felföldi Zsolt
b87340a856
core, core/vm: implement EIP-7708 (#33645)
This PR implements EIP-7708 according to the latest "rough consensus":

https://github.com/ethereum/EIPs/pull/9003
https://github.com/etan-status/EIPs/blob/fl-ethlogs/EIPS/eip-7708.md

---------

Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
Co-authored-by: raxhvl <raxhvl@users.noreply.github.com>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-03-23 22:29:53 +08:00
CPerezz
77779d1098
core/state: bypass per-account updateTrie in IntermediateRoot for binary trie (#34022)
## Summary

In binary trie mode, `IntermediateRoot` calls `updateTrie()` once per
dirty account. But with the binary trie there is only one unified trie
(`OpenStorageTrie` returns `self`), so each call redundantly does
per-account trie setup: `getPrefetchedTrie`, `getTrie`, slice
allocations for deletions/used, and `prefetcher.used` — all for the same
trie pointer.

This PR replaces the per-account `updateTrie()` calls with a single flat
loop that applies all storage updates directly to `s.trie`. The MPT path
is unchanged. The prefetcher trie replacement is guarded to avoid
overwriting the binary trie that received updates.

This is the phase-1 counterpart to #34021 (H01). H01 fixes the commit
phase (`trie.Commit()` called N+1 times). This PR fixes the update phase
(`updateTrie()` called N times with redundant setup). Same root cause —
unified binary trie operated on per-account — different phases.

## Benchmark (Apple M4 Pro, 500K entries, `--benchtime=10s --count=3`,
on top of #34021)

| Metric | H01 baseline | H01 + this PR | Delta |
|--------|:------------:|:-------------:|:-----:|
| Approve (Mgas/s) | 368 | **414** | **+12.5%** |
| BalanceOf (Mgas/s) | 870 | 875 | +0.6% |

Should be rebased after #34021 is merged.
2026-03-20 15:40:04 +01:00
CPerezz
519a450c43
core/state: skip redundant trie Commit for Verkle in stateObject.commit (#34021)
## Summary

**Bug fix.** In Verkle mode, all state objects share a single unified
trie (`OpenStorageTrie` returns `self`). During `stateDB.commit()`, the
main account trie is committed via `s.trie.Commit(true)`, which calls
`CollectNodes` to traverse and serialize the entire tree. However, each
dirty account's `obj.commit()` also calls `s.trie.Commit(false)` on the
**same trie object**, redundantly traversing and serializing the full
tree once per dirty account.

With N dirty accounts per block, this causes **N+1 full-tree
traversals** instead of 1. On a write-heavy workload (2250 SSTOREs),
this produces ~131 GB of allocations per block from duplicate NodeSet
creation and serialization. It also causes a latent data race from N+1
goroutines concurrently calling `CollectNodes` on shared `InternalNode`
objects.

This commit adds an `IsVerkle()` early return in `stateObject.commit()`
to skip the redundant `trie.Commit()` call.

## Benchmark (AMD EPYC 48-core, 500K entries, `--benchtime=10s
--count=3`)

| Metric | Baseline | Fixed | Delta |
|--------|----------|-------|-------|
| Approve (Mgas/s) | 4.16 ± 0.37 | **220.2 ± 10.1** | **+5190%** |
| BalanceOf (Mgas/s) | 966.2 ± 8.1 | 971.0 ± 3.0 | +0.5% |
| Allocs/op (approve) | 136.4M | 792K | **-99.4%** |

Resolves the TODO in statedb.go about the account trie commit being
"very heavy" and "something's wonky".

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-03-17 12:27:29 +01:00
CPerezz
4b915af2c3
core/state: avoid Bytes() allocation in flatReader hash computations (#34025)
## Summary

Replace `addr.Bytes()` and `key.Bytes()` with `addr[:]` and `key[:]` in
`flatReader`'s `Account` and `Storage` methods. The former allocates a
copy while the latter creates a zero-allocation slice header over the
existing backing array.

## Benchmark (AMD EPYC 48-core, 500K entries, screening
`--benchtime=1x`)

| Metric | Baseline | Slice syntax | Delta |
|--------|----------|--------------|-------|
| Approve (Mgas/s) | 4.13 | 4.22 | +2.2% |
| BalanceOf (Mgas/s) | 168.3 | 190.0 | **+12.9%** |
2026-03-17 11:42:42 +01:00
rjl493456442
91cec92bf3
core, miner, tests: introduce codedb and simplify cachingDB (#33816)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
2026-03-10 08:29:21 +01:00
rjl493456442
dd202d4283
core, ethdb, triedb: add batch close (#33708)
Pebble maintains a batch pool to recycle the batch object. Unfortunately
batch object must be
explicitly returned via `batch.Close` function. This PR extends the
batch interface by adding
the close function and also invoke batch.Close in some critical code
paths.

Memory allocation must be measured before merging this change. What's
more, it's an open
question that whether we should apply batch.Close as much as possible in
every invocation.
2026-03-04 11:17:47 +01:00
rjl493456442
e636e4e3c1
core/state: track slot reads for empty storage (#33743)
From the https://eips.ethereum.org/EIPS/eip-7928

> SELFDESTRUCT (in-transaction): Accounts destroyed within a transaction
   MUST be included in AccountChanges without nonce or code changes. 
   However, if the account had a positive balance pre-transaction, the
   balance change to zero MUST be recorded. Storage keys within the self-destructed
   contracts that were modified or read MUST be included as a storage_reads
   entry.

The storage read against the empty contract (zero storage) should also
be recorded in the BAL's readlist.
2026-02-24 21:57:50 +08:00
Felix Lange
8e1de223ad
crypto/keccak: vendor in golang.org/x/crypto/sha3 (#33323)
The upstream libray has removed the assembly-based implementation of
keccak. We need to maintain our own library to avoid a peformance
regression.

---------

Co-authored-by: lightclient <lightclient@protonmail.com>
2026-02-03 14:55:27 -07:00
Marius van der Wijden
16a6531ac2
core: miner: reduce allocations in block building (#33375)
I recently went on a longer flight and started profiling the geth block
production pipeline.
This PR contains a bunch of individual fixes split into separate
commits.
I can drop some if necessary.


Benchmarking is not super easy, the benchmark I wrote is a bit
non-deterministic.
I will try to write a better benchmark later
```
goos: linux
goarch: amd64
pkg: github.com/ethereum/go-ethereum/miner
cpu: Intel(R) Core(TM) Ultra 7 155U
                │ /tmp/old.txt │          /tmp/new.txt          │
                │    sec/op    │   sec/op     vs base           │
BuildPayload-14    141.5µ ± 3%   146.0µ ± 6%  ~ (p=0.346 n=200)

                │ /tmp/old.txt │             /tmp/new.txt             │
                │     B/op     │     B/op      vs base                │
BuildPayload-14   188.2Ki ± 4%   177.4Ki ± 4%  -5.71% (p=0.018 n=200)

                │ /tmp/old.txt │            /tmp/new.txt             │
                │  allocs/op   │  allocs/op   vs base                │
BuildPayload-14    2.703k ± 4%   2.453k ± 5%  -9.25% (p=0.000 n=200)
```
2026-02-03 08:19:16 +01:00
Noisy
a179ccf6f0
core/state: add bounds check in heap eviction loop (#33712)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
core/state: add bounds check in heap eviction loop

Add len(h) > 0 check before accessing h[0] to prevent potential panic
and align with existing heap access patterns in txpool, p2p, and mclock
packages.
2026-01-29 21:08:04 +08:00
CPerezz
1e9dfd5bb0
core: standardize slow block JSON output for cross-client metrics (#33655)
Some checks are pending
/ Docker Image (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
Implement standardized JSON format for slow block logging to enable
cross-client performance analysis and protocol research.

This change is part of the Cross-Client Execution Metrics initiative
proposed by Gary Rong: https://hackmd.io/dg7rizTyTXuCf2LSa2LsyQ

The standardized metrics enabled data-driven analysis like the EIP-7907
research: https://ethresear.ch/t/data-driven-analysis-on-eip-7907/23850

JSON format includes:
- block: number, hash, gas_used, tx_count
- timing: execution_ms, total_ms
- throughput: mgas_per_sec
- state_reads: accounts, storage_slots, bytecodes, code_bytes
- state_writes: accounts, storage_slots, bytecodes
- cache: account/storage/code hits, misses, hit_rate


This should come after merging #33522

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-01-28 20:58:41 +08:00
rjl493456442
c2595381bf
core: extend the code reader statistics (#33659)
Some checks are pending
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
This PR extends the statistics of contract code read by adding these
fields:

- **CacheHitBytes**: the total number of bytes served by cache
- **CacheMissBytes**: the total number of bytes read on cache miss
- **CodeReadBytes**: the total number of bytes for contract code read
2026-01-26 11:25:53 +01:00
rjl493456442
1022c7637d
core, eth, internal, triedb/pathdb: enable eth_getProofs for history (#32727)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
This PR enables the `eth_getProofs ` endpoint against the historical states.
2026-01-22 09:19:27 +08:00
forkfury
2eb1ccc6c4
core/state: ensure deterministic hook emission order in Finalise (#33644)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
Fixes #33630

Sort self-destructed addresses before emitting hooks in Finalise() to
ensure deterministic ordering and fix flaky test
TestHooks_OnCodeChangeV2.

---------

Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-01-20 20:36:07 +08:00