A few updates for glamsterdam devnet, taking the original commits from
@spencer-tb
- making the TargetGasLimit as the optional parameters
- ensuring the system call's code exists (EIP-7002/7251/8282)
- rework the fork selection rules in the engine API
---------
Co-authored-by: spencer-tb <spencer.tb@ethereum.org>
When the full data domain (cell indices 0..DataPerBlob-1) is present, a
blob is the concatenation of its data cells, so it can be reconstructed
without any KZG work. Add BlobsFromDataCells, which returns the blobs by
concatenation when the data cells are present in canonical order and
declines otherwise (so callers fall back to RecoverBlobs). Its accepted
inputs are a strict subset of those accepted by RecoverBlobs, so a
successful result is byte-identical; being pure byte copying it is
independent of the selected KZG backend.
Shared primitive: used both to skip KZG recovery when serving blobs and
by the cell-recovery path (RecoverCells).
#35473 keys the precompile cache on the input, but SizeConstrainedCache
only counts the value’s bytes, so a cacheable empty output (e.g. a
failed ECRECOVER) is never evicted and grows the cache without bound.
Skipping empty outputs alone would still leave sha256/ripemd160 ~256x
over budget, and would only hold as long as every failing output happens
to be empty.
eth/72 announces blob transactions without the blob payload while eth/71
includes it, so the same transaction is announced with different
sizes. Compare each announcement against the size expected for that
peer's version instead of a single size so that honest peers on either version
are no longer dropped on delivery.
`BlobPool.Init` builds the lookup, index and store without holding
`p.lock`, and `eth/backend.go` publishes the pool to `blobpool.NewCache`
before `txpool.New` runs Init. Cache.update spawns a goroutine calling
`getByVhash`, so it can read the pool mid-construction:
```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x28]
blobpool.(*BlobPool).getByVhash(...) blobpool.go:1303
blobpool.(*Cache).update.func1() cache.go:429
```
`Init` fills the lookup inside `billy.Open`, whose index callback runs
`parseTransaction` -> `trackTransaction`, and assigns `p.store` only
once `billy.Open` returns. For that window a lookup hit names a
transaction whose store does not exist yet, and `p.store.Get`
dereferences nil.
Build the cache after `txpool.New` so no reader exists while `Init` runs
-- `getByVhash` has exactly one caller -- and have `getByVhash` read the
store under the same lock as the lookup, returning nil when it is not
set.
A benchmark harness that restarts the client once per test hit this on
1-4% of starts; a node that starts once rarely will.
This PR explicitly clears the referenced block access list at the end of
each transaction. This is essential because accounts are shadow-copied
into the global block access list, and it prevents accidental mutations
through stale references in StateDB.
Fixes#35418.
After a restart, the syncer sets the finalized marker to head−64 and the
safe marker to head−32 on every downloader sync event, ignoring epoch
boundaries. Since this service is registered unconditionally and
`api_backend` serves `CurrentFinalBlock()` verbatim,
`eth_getBlockByNumber("finalized")` can return a mid-epoch block that
was never finalized and can still be reorged.
The synthesized markers exist to make `finalized`/`safe` usable when no
consensus client is attached. This change scopes them to exactly that
case: they are only set when an explicit sync target has been specified
(`--synctarget`), which is the only mode where no CL supplies real
checkpoints. Normal nodes now never override consensus-client
checkpoints.
`TestSyncerDoesNotInventFinalityMarkers` syncs a node to head with no CL
finality input and asserts the chain's finalized/safe markers stay
unset; it fails on master (finalized invented at head−64) and passes
with this change.
---------
Co-authored-by: SillyZir <269283839+SillyZir@users.noreply.github.com>
Co-authored-by: Jonny Rhea <5555162+jrhea@users.noreply.github.com>
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
StateSize is a development tool for calculating and tracking the size of
the state. It was requested by ethPandaOps a while ago, but it has since
been superseded by another approach that captures state changes via a
live tracer. Therefore, this tool can be retired to reduce maintenance
overhead.
#35388 keys the cache on `keccak256(address, input)`. Hashing the input
is most of the cost of a lookup, and it scales with input size, so a
large input is expensive to look up even when the result is trivial.
That is why several precompiles had to opt out to stay ahead of it.
@ayamiyaguchi spotted this and wrote the first commit here, which
excluded the precompiles the key cost was hurting most. This takes the
same finding in a different direction by making the key cheap in the
first place, so those precompiles do not need excluding.
The solution here is to key on the input bytes directly, plus three
changes that follow from it:
1) Entries used to share one LRU, so a high-volume precompile could
evict the pairing and modexp results the cache exists to hold. Each
precompile now gets its own.
2) Now that the key is the input, entries run from tens of bytes to
kilobytes, and a count means very different memory depending on the mix.
Each precompile gets 1 MiB of keys and values.
3) A precompile is cached only if it says so, and can narrow an input to
the bytes that determine the result via `NormalizeInput` so padding
lands on the entry the unpadded call already made.
### Benchmarks
Medians of five runs.
#### Lookup versus running the precompile, at real vector sizes
| precompile | input | #35388 | this PR | run |
|----------------------|--------|------------|------------|-----------|
| ECREC | 128 | 480 ns | 55 ns | 18.2 µs |
| SHA256 | 128 | not cached | 58 ns | 79 ns |
| RIPEMD160 | 128 | not cached | 55 ns | 454 ns |
| ID | 128 | not cached | not cached | 16 ns |
| MODEXP | 609 | 1.1 µs | 128 ns | 2.9 µs |
| BN254_ADD | 128 | 478 ns | 54 ns | 1.0 µs |
| BN254_MUL | 96 | 279 ns | 52 ns | 13.4 µs |
| BN254_PAIRING | 384 | 698 ns | 85 ns | 490.1 µs |
| BLAKE2F | 213 | 486 ns | 67 ns | 118 ns |
| KZG_POINT_EVALUATION | 192 | 488 ns | 61 ns | 785.8 µs |
| BLS12_G1ADD | 256 | 697 ns | 68 ns | 1.9 µs |
| BLS12_G1MSM | 160 | 488 ns | 60 ns | 95.4 µs |
| BLS12_G2ADD | 512 | 911 ns | 103 ns | 2.9 µs |
| BLS12_G2MSM | 288 | 708 ns | 74 ns | 181.3 µs |
| BLS12_PAIRING_CHECK | 384 | 713 ns | 85 ns | 445.6 µs |
| BLS12_MAP_FP_TO_G1 | 64 | 282 ns | 45 ns | 30.7 µs |
| BLS12_MAP_FP2_TO_G2 | 128 | 490 ns | 55 ns | 135.0 µs |
| P256VERIFY | 160 | 494 ns | 60 ns | 33.6 µs |
RIPEMD160 wasn't cached before and a lookup now costs 55 ns against 454
ns to run it. BN254_ADD was cached previously, but at 478 ns to look up
against a 1 µs run the cache was barely paying for itself. With this
change, the lookup is now 54 ns and much more worth it.
#### The same measurement at the largest eligible input, 8 KiB
| precompile | #35388 | this PR | run |
|----------------------|------------|------------------|-----------|
| ECREC | 12.9 µs | 74 ns | 131 ns |
| SHA256 | not cached | 1.1 µs | 2.6 µs |
| RIPEMD160 | not cached | 1.2 µs | 17.9 µs |
| ID | not cached | not cached | 969 ns |
| MODEXP | 13.0 µs | 56 ns | 50 ns |
| BN254_ADD | 12.9 µs | 67 ns | 60 ns |
| BN254_MUL | 12.9 µs | 56 ns | 6.4 µs |
| BN254_PAIRING | 12.8 µs | 5 ns, not cached | 2 ns |
| BLAKE2F | 12.9 µs | 5 ns, not cached | 1 ns |
| KZG_POINT_EVALUATION | 12.9 µs | 4 ns, not cached | 1 ns |
| BLS12_G1ADD | 12.8 µs | 5 ns, not cached | 1 ns |
| BLS12_G1MSM | 13.0 µs | 4 ns, not cached | 1 ns |
| BLS12_G2ADD | 13.0 µs | 4 ns, not cached | 1 ns |
| BLS12_G2MSM | 12.9 µs | 4 ns, not cached | 1 ns |
| BLS12_PAIRING_CHECK | 13.0 µs | 5 ns, not cached | 1 ns |
| BLS12_MAP_FP_TO_G1 | 13.0 µs | 4 ns, not cached | 1 ns |
| BLS12_MAP_FP2_TO_G2 | 12.8 µs | 4 ns, not cached | 1 ns |
| P256VERIFY | 13.0 µs | 4 ns, not cached | 1 ns |
The `#35388` column is flat at ~13 µs because the key is a hash of the
input and does not depend on which precompile receives it. In the `this
PR` column, the number beside "not cached" is the cost of deciding not
to build a key: those precompiles require an exact length, so an 8 KiB
input is one they will reject, and there is no result worth keying. The
`run` column here is mostly a length rejection rather than work, so it
is context for the other two columns rather than a comparison.
---------
Co-authored-by: aya <aya@ethereum.org>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
Close the started signal only after the fetchers are registered on
cancelWg, so suspend's Cancel actually waits for them instead of racing
the registration.
`testing_buildBlockV1` decodes `targetGasLimit` from the payload
attributes but does not pass it to `miner.BuildPayloadArgs`. The miner
then falls back to its configured gas ceiling, so the field is silently
ignored. The engine API path (`forkchoiceUpdated`) already passes it
through.
This matters for fixture generation in ethereum/execution-apis, where
`testing_buildBlockV1` builds Amsterdam test blocks and the gas limit
must honor the CL-provided target (see ethereum/execution-apis#857 and
ethereum/execution-apis#862).
The new test builds an Amsterdam block with a target inside the
per-block adjustment bound and checks the payload hits it exactly.
Since #35386 blocks are delivered without waiting for their access list,
a reserved BAL task can outlive its block and hit the stale branch of
`reserveHeaders`, which logs at error level — demote that case to debug.
---------
Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
Completes the regular → execution gas rename from #35457. The constant
now matches the EIP-8037 spec name `EXECUTION_PER_AUTH_BASE_COST`.
Pure mechanical rename, no value change.
This PR implements the BAL downloader. Once the Amsterdam fork is
enabled, BALs are scheduled for download for BAL-eligible blocks.
Unlike mandatory components such as block bodies, BALs are optional and
are downloaded on a best-effort basis. If a block's essential components
are ready for delivery before its BAL has been retrieved, the block will
be delivered without the BAL.
Calling a function `do` is fine in go, but when interacting with other
languages, namely C, this clashes with a known keyword, which some
compilers don't like.
## Description
Blob mode cache entries (the default until a CL advertises
`engine_getBlobsV4` via `engine_exchangeCapabilities`) carry no cells,
but `Cache.GetCells` treated any entry as a hit and served null cells
from the empty custody set instead of falling back to the pool.
Found via the EELS execute-blobs simulator (EIP-8070 `engine_getBlobsV4`
tests), which never calls `engine_exchangeCapabilities`: null cells
appeared intermittently depending on the race with the 1s top-K preload.
With the fix the suite passes 139/139 (from 87/139 on master).
If snap sync v2 is re-enabled after a previous sync already completed
and committed its pivot, the leftover journal is now discarded instead
of resumed.
This PR aligns the `Cells` and `GetCells` message implementations with
the spec: https://github.com/ethereum/devp2p/blob/master/caps/eth.md#getcells-0x14
Previously, `GetCellsPacket` and `CellsPacket` embedded `GetCellsRequest`
and `CellsResponse`. This caused them to be encoded as nested lists, which
does not match the wire format defined by the spec. This PR inlines their fields
to flatten the RLP layout of `Cells` and `GetCells`.
Blocks heavy in precompile calls (e.g. Aztec's proof settlement txs)
spend most of their processing time on operations (ECMUL, pairings, KZG
point evaluation, MODEXP) that the state prefetcher has already computed
and thrown away.
This PR adds a precompile result cache shared between the prefetcher and
block processing (and the miner), following the JumpDestCache pattern.
Note that cached precompiles are keyed by address and input, with
entries partitioned by the active precompile set, so a fork that changes
the behavior behind an address can never be served results from before
it.
---------
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This PR fixes the incorrect size calculation for blob sidecar. The
original formula is for legacy sidecar without the version tag. As the
legacy version has been deprecated and no longer supported by the Geth's
blobPool, the size calculation should also be flipped to sidecar v1.